<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Michael Okoko</title>
    <description>The latest articles on Forem by Michael Okoko (@idoko).</description>
    <link>https://forem.com/idoko</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F35579%2F99c5a559-5767-45df-a516-1587f35c45b6.jpg</url>
      <title>Forem: Michael Okoko</title>
      <link>https://forem.com/idoko</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/idoko"/>
    <language>en</language>
    <item>
      <title>Travis: Unable to Evaluate Symlinks in Dockerfile path</title>
      <dc:creator>Michael Okoko</dc:creator>
      <pubDate>Fri, 25 Oct 2019 10:01:08 +0000</pubDate>
      <link>https://forem.com/idoko/travis-unable-to-evaluate-symlinks-in-dockerfile-path-26o8</link>
      <guid>https://forem.com/idoko/travis-unable-to-evaluate-symlinks-in-dockerfile-path-26o8</guid>
      <description>&lt;p&gt;I was following some Docker/Kubernetes tutorial some time back, and all was bright and good until it wasn't. Travis was failing with the error "unable to prepare context: unable to evaluate symlinks in Dockerfile path" and the script causing the build to fail look like this:&lt;br&gt;
&lt;code&gt;docker build -t [secure]/client-test -f client/Dockerfile.dev ./client&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It was weird to me because I just used the same command to build and tag the docker image locally, so I tried, again and again to replicate on local - but local worked every damn time.&lt;/p&gt;

&lt;p&gt;Now, in most cases when this error happens, it is caused by a wrongly typed folder/file name, or an incorrect file reference, and you can just double-check to get it fixed. But this case was different!&lt;/p&gt;
&lt;h2&gt;
  
  
  What really happened? Submodules!
&lt;/h2&gt;

&lt;p&gt;I removed the script instruction that was the culprit and watched the logs till I found something interesting, building the particular image for production was failing too, but all others were passing. At this point, it was becoming clear that my headache might have been caused by something around symlinks or so (it should have hit me from the error message anyway but &lt;em&gt;e dey happen&lt;/em&gt;). I went back to Github, mindlessly looking at the repo and noticed this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fqz6k8q4dm653v7ujmt29.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fqz6k8q4dm653v7ujmt29.png" alt="Github screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ha! My fear was confirmed!&lt;/p&gt;
&lt;h3&gt;
  
  
  What are Submodules again?
&lt;/h3&gt;

&lt;p&gt;Sub-module is Git's way of enabling you keep a git repository within another while maintaining their commit history separately. It's like having a project within a project. Gitbook has a quite &lt;a href="https://git-scm.com/book/en/v2/Git-Tools-Submodules" rel="noopener noreferrer"&gt;solid explanation&lt;/a&gt; on how it works.&lt;/p&gt;
&lt;h3&gt;
  
  
  So here is how it happened:
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;create-react-app&lt;/code&gt; automatically generated a git repository when it created the application (the client folder in this case), and I only initialized the repo on the parent folder after creating this react app. Somehow, the inner client directory (the react app) then became a submodule, and my naive self thought that deleting the &lt;code&gt;.git&lt;/code&gt; folder in that inner folder was enough to get me a smooth ride.&lt;/p&gt;
&lt;h2&gt;
  
  
  The fix.
&lt;/h2&gt;

&lt;p&gt;Fixing it is as simple as removing the submodule and re-adding the folder to your staging like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# delete the submodule reference&lt;/span&gt;
git &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;--cached&lt;/span&gt; submodule_path

&lt;span class="c"&gt;# remove the inner .git dir if it still exists&lt;/span&gt;
&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; submodule_path/.git

&lt;span class="c"&gt;# re-add the directory to the main repository&lt;/span&gt;
git add submodule_path

&lt;span class="c"&gt;# commit and profit&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"removed git submodule"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and that is all.&lt;/p&gt;

</description>
      <category>travis</category>
      <category>docker</category>
    </item>
    <item>
      <title>Persistent SSH Sessions with Tmux</title>
      <dc:creator>Michael Okoko</dc:creator>
      <pubDate>Tue, 26 Mar 2019 05:39:28 +0000</pubDate>
      <link>https://forem.com/idoko/persistent-ssh-sessions-with-tmux-25dm</link>
      <guid>https://forem.com/idoko/persistent-ssh-sessions-with-tmux-25dm</guid>
      <description>&lt;h2&gt;
  
  
  Hello SSH
&lt;/h2&gt;

&lt;p&gt;The SSH (Secure Shell) is a widely used protocol that helps you drop into a remote system, do what you want to do, and get out. Which means, you could check your server logs remotely from an android device, monitor the raspberry pie lying somewhere in your bedroom from your office machine, or go full hacker mode and do stuff like keeping a connection alive when your firewall keeps dropping it or tunneling a network service securely through a remote machine.&lt;br&gt;
But here's the thing. Each time we exit/logout from our remote SSH server, we lose our session and with it, every program that was running. And we don't want that.&lt;br&gt;
That is, we might want an opened program, say an IRC client, a crawler script, anything, to continue running even when we've left it alone, without us starring at black screens with walls of white and green text, but this is where "bare-bones SSH" falls short, and Tmux takes the shine - a little of it anyway.&lt;/p&gt;
&lt;h2&gt;
  
  
  Meet Tmux
&lt;/h2&gt;

&lt;p&gt;Tmux - which is actually short for "Terminal Multiplexer" - is a tool that lets you create different windows and panes in a single terminal window, while also letting you persist those sessions so you can continue from where you left off the last time (you see what I'm saying?)&lt;/p&gt;
&lt;h2&gt;
  
  
  To the meat...
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Setting up tmux
&lt;/h3&gt;

&lt;p&gt;If you have used tmux and are already comfortable with it, feel free to jump to the next section. If you haven't, it's a fairly straightforward process so let's breeze through it:&lt;/p&gt;

&lt;p&gt;You are highly likely to find the tmux package in your linux distro's package repositories so installing it is as easy as:&lt;/p&gt;
&lt;h4&gt;
  
  
  Ubuntu/Debian
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;sudo apt install tmux&lt;/code&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Archlinux/Archlinux Derivates
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;sudo pacman install tmux&lt;/code&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  CentOS
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;sudo yum install tmux&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now, navigating tmux is a bit more involved and though mouse support exists, it is almost always better to get the hang of a couple of commands. The good thing is all of the commands are configurable which means you get to map them to fit your workflow better. &lt;a href="https://dev.toHackernoon"&gt;Hackernoon&lt;/a&gt; has a &lt;a href="https://hackernoon.com/a-gentle-introduction-to-tmux-8d784c404340"&gt;solid beginner's guide here&lt;/a&gt; to help you find your way around if you're just starting out though.&lt;/p&gt;
&lt;h2&gt;
  
  
  Ehem...Persistent Sessions.
&lt;/h2&gt;

&lt;p&gt;First, we modify our zsh/bash configuration file (depending on &lt;del&gt;if you have seen the light or not&lt;/del&gt; your preferred shell ) to automatically create a new tmux session if there's no available session, or attach itself to an existing one if it exists. So open up the configuration file i.e &lt;code&gt;~/.bashrc&lt;/code&gt; or &lt;code&gt;~/.zshrc&lt;/code&gt; and type the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;tty&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; /dev/tty1 &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
  /usr/bin/tmux new &lt;span class="nt"&gt;-s&lt;/span&gt; 0
  /usr/bin/tmux attach &lt;span class="nt"&gt;-t&lt;/span&gt; 0
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Next, we setup our profile to automatically attach itself to the existing tmux session (labelled '0') so we append the following to our &lt;code&gt;~/.profile&lt;/code&gt; (you'll have to create it if it doesn't exist.):&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/usr/bin/tmux attach -t 0&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Side Attraction: Termux for Android
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://termux.com"&gt;Termux&lt;/a&gt; is an Android terminal emulator that actually works. It comes with niceties such as not requiring root access and a pretty loaded package repository, as well as been able to compile your own packages on your device. To use SSH on termux is as simple as running &lt;code&gt;pkg install openssh&lt;/code&gt; in the app - after installing the termux app of course. Installing the &lt;code&gt;openssh&lt;/code&gt; package also set up your SSH keys, which you can install on your remote SSH server and get going.&lt;/p&gt;

&lt;p&gt;Now we can hop back into our SSH server, but this time, with an extra coolness.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Cover Image Credit: &lt;a href="https://reddit.com/user/authorice"&gt;u/authorice&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ssh</category>
      <category>tmux</category>
      <category>linux</category>
      <category>termux</category>
    </item>
    <item>
      <title>Setting up a Docker-Based Gitlab Runner on Alibaba Cloud ECS</title>
      <dc:creator>Michael Okoko</dc:creator>
      <pubDate>Thu, 18 Oct 2018 05:46:30 +0000</pubDate>
      <link>https://forem.com/idoko/setting-up-a-docker-based-gitlab-runner-on-alibaba-cloud-ecs-1o8g</link>
      <guid>https://forem.com/idoko/setting-up-a-docker-based-gitlab-runner-on-alibaba-cloud-ecs-1o8g</guid>
      <description>&lt;p&gt;Gitlab offers a couple of amazing features, one of which is its Continous Integration/Delivery tool using GitlabCI. By default, your builds are run on gitlab's servers for free and capped at 2000 minutes across private projects, after which you either pay for an upgraded plan or use your own server.&lt;br&gt;
In this guide, we will set up a private gitlab runner on our Alibaba Cloud ECS instance while hosting our project on gitlab.&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting Started
&lt;/h3&gt;

&lt;p&gt;To kickstart, let's create an Alibaba Cloud ECS instance (if there's none already) with at least 1GB of RAM and either of Debian, CentOS or Ubuntu as our base OS. For this guide, we will be using Ubuntu version 16.04. If you're totally new here, the Alibaba Cloud documentation has &lt;a href="https://www.alibabacloud.com/help/doc-detail/25423.htm" rel="noopener noreferrer"&gt;an excellent guide to creating your first ECS instance&lt;/a&gt;.&lt;br&gt;
The rest of this guide will be mostly CLI-based so a pretty lack-of-fear-of-the-command-line would be welcomed 😄 .&lt;/p&gt;

&lt;h3&gt;
  
  
  Hello Docker
&lt;/h3&gt;

&lt;p&gt;Our next step is to install docker on our ECS instance. Since we are using Ubuntu for our guide, installing docker is as simple as running:&lt;br&gt;
&lt;code&gt;apt install docker.io&lt;/code&gt;. &lt;br&gt;
Note: We are installing &lt;code&gt;docker.io&lt;/code&gt; instead of  &lt;code&gt;docker&lt;/code&gt; since the later will only install the system tray package on our system. &lt;br&gt;
You can confirm the installation by running &lt;code&gt;docker info&lt;/code&gt; which should print out your container information to the terminal.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing the Gitlab Runner
&lt;/h3&gt;

&lt;p&gt;Once docker is installed, we will use the runner installation script provided by Gitlab. Currently, it supports Ubuntu, CentOS and Debian (See why we needed one of those OSs now?). So go ahead and type:&lt;br&gt;
&lt;code&gt;curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh | sudo bash&lt;/code&gt; to download the script and then proceed with the installation by running:&lt;br&gt;
&lt;code&gt;sudo apt install gitlab-runner&lt;/code&gt;&lt;br&gt;
As confirmation, you can run: &lt;code&gt;gitlab-runner --help&lt;/code&gt; to display the help information on your terminal.&lt;/p&gt;

&lt;p&gt;There is a runner installed on our ECS instance, now what?&lt;/p&gt;

&lt;p&gt;As you might know, the runners are used to build and deploy our code from a gitlab project/repository which means, we will have to bind the same runner to our project on gitlab by registering it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Registering a Gitlab Runner
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;gitlab-runner&lt;/code&gt; we installed earlier comes with interactive CLI tool to be used for registration but to get the required info, we will need to visit our target gitlab project i.e, the project we are looking to build on our ECS instance. So visit your project's CI settings page which should live at  &lt;code&gt;https://gitlab.com/{gitlab-username}/{project-name}/settings/ci_cd&lt;/code&gt; (We are assuming it is hosted on gitlab.com) and expand the "Runners" section. Take note of the URL and the registration token on the page (shown in the expansion below) as we'll be using that shortly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F0lcf7jbvewfm2ozfxzcw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F0lcf7jbvewfm2ozfxzcw.png" alt="runner-setting-expand"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Back to our SSH connection, run: &lt;br&gt;
&lt;code&gt;sudo gitlab-runner register&lt;/code&gt; and you'll be presented with a couple of prompts and here is a little break down of each prompt:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Co-ordinator URL&lt;/strong&gt;: This is the URL as shown in the image. It refers to where our gitlab instance is hosted and for our case, it's &lt;code&gt;https://gitlab.com/&lt;/code&gt;.&lt;br&gt;
&lt;strong&gt;Runner Token&lt;/strong&gt;: The registration token on the page, it's used to uniquely identify projects so you will have to copy it from the page and paste on your terminal.&lt;br&gt;
&lt;strong&gt;Runner description&lt;/strong&gt;: Helps to identify the specific runner in cases where we have multiple runners working together, it defaults to our hostname.&lt;br&gt;
&lt;strong&gt;Runner tags&lt;/strong&gt;: Comma-separated values that we can use to delegate jobs from our CI configuration file i.e our &lt;code&gt;gitlab-ci.yml&lt;/code&gt;. We'll leave ours blank.&lt;br&gt;
&lt;strong&gt;Executor&lt;/strong&gt;: This is the method used to run our jobs and the options are laid out for us. We will be using &lt;code&gt;docker&lt;/code&gt; here.&lt;br&gt;
&lt;strong&gt;Docker Image&lt;/strong&gt;: The default image used when none is specified in our &lt;code&gt;gitlab-ci.yml&lt;/code&gt;. Gitlab advises you use a general image and get more specific if required in the CI config file. In the spirit of keeping our image as small as possible, we will use Alpine Linux - a &lt;strong&gt;really&lt;/strong&gt; minimal Linux distro that is designed to be simple and resource efficient, so go ahead and type &lt;code&gt;alpine:latest&lt;/code&gt; on the prompt.&lt;/p&gt;

&lt;p&gt;An important thing to note here is that our configurations are stored in &lt;code&gt;/etc/gitlab-runner/config.toml&lt;/code&gt; so you can always edit the file directly and reload in case you somehow, need to update any of the provided information.&lt;/p&gt;

&lt;p&gt;Going back to our project's CI/CD settings page, we should see our shiny new runner added and we can safely disable the shared runners now.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;So there! We have configured our Alibaba Cloud ECS instance to handle CI builds for our gitlab project. You may want to register more runners for different projects and it's as easy as the same steps above or you may want to optimize the runner you just created to improve your build times.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This post was originally published on &lt;a href="https://www.sitepoint.com/community/t/setting-up-a-docker-based-gitlab-runner-on-alibaba-cloud-ecs/307617" rel="noopener noreferrer"&gt;Sitepoint&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>gitlab</category>
      <category>alibabacloud</category>
    </item>
    <item>
      <title>Demystifying Laravel Queues</title>
      <dc:creator>Michael Okoko</dc:creator>
      <pubDate>Thu, 12 Jul 2018 15:45:37 +0000</pubDate>
      <link>https://forem.com/idoko/demystifying-laravel-queues-2ec3</link>
      <guid>https://forem.com/idoko/demystifying-laravel-queues-2ec3</guid>
      <description>&lt;p&gt;At some point, your application will need to listen for cues and emit an event for them. Those cues could be birthday or appointment reminders or expiry reminders for users of the trial version of your saas app. Unsurprisingly, Laravel has a built-in way to handle this graciously. Here, we would be sending out reminders to users of our amazing saas app who are on the trial version 15 days before their trial expires.&lt;/p&gt;

&lt;h3&gt;
  
  
  First of All...Drivers
&lt;/h3&gt;

&lt;p&gt;True to Laravel's reputation for including as many batteries as possible (which can definitely be good or bad), the framework comes with out-of-the-box support for different queue handlers including redis, beanstalk, amazon SQS and of course, relational databases, which we will be using here. There is also an amazing documentation on queue drivers &lt;a href="https://laravel.com/docs/5.6/queues#driver-prerequisites"&gt;here&lt;/a&gt; so feel free to explore them.&lt;br&gt;
    To use the database driver, we will need to create a table in our application database to hold the jobs and laravel provides a clean helper command for that. So we will create and run the necessary migrations like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan queue:table
php artisan migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Diving In
&lt;/h3&gt;

&lt;p&gt;We want to equip our job with the ability of being continuously run in the background so we will create a new artisan command to trigger the task. Artisan commands are laravel's way of extending the already powerful command-line interface and there is an extensive documentation for it living &lt;a href="https://laravel.com/docs/5.6/artisan"&gt;here&lt;/a&gt;. Creating a new one is as simple as running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan make:command SendExpiryCommand
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;which generates a new class in &lt;code&gt;app/Console/Commands&lt;/code&gt;. We will modify the &lt;code&gt;signature&lt;/code&gt; and &lt;code&gt;description&lt;/code&gt; attribute and the &lt;code&gt;handle()&lt;/code&gt; method of this new class before using. &lt;br&gt;
   The &lt;code&gt;signature&lt;/code&gt; is what we call from the CLI and has the format &lt;code&gt;command:name&lt;/code&gt;, - think &lt;code&gt;db:seed&lt;/code&gt;, &lt;code&gt;config:clear&lt;/code&gt;, etc, as such, let's change our signature to &lt;code&gt;trial_expiry:notify&lt;/code&gt; and the description to something actually more descriptive. Now the &lt;code&gt;handle()&lt;/code&gt; method is what gets called when we run our shiny command and it is where our code (or most of it anyway) will live. Now, we are going to assume that our app has a &lt;code&gt;Trials&lt;/code&gt; model with an &lt;code&gt;expires_in&lt;/code&gt; field which holds the date the trial is supposed to expire as well as a &lt;code&gt;user_id&lt;/code&gt; field which references our User model. So here is what our final handle() code looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cd"&gt;/**
* Execute the console command.
*
* @return mixed
*/&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="c1"&gt;//get the date of 15 days from now&lt;/span&gt;
    &lt;span class="nv"&gt;$actualDate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Carbon&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addDays&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$actualDate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$actualDate&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Y-m-d'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$candidates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Trial&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'expires_in'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'='&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$actualDate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;      
    &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$candidates&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$candidate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;SendExpiryNotification&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$candidate&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our &lt;code&gt;SendExpiryNotification&lt;/code&gt; is the actual queue-able job but it doesn't exist yet so let's create that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan make:job SendExpiryNotification
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above command will create a new class in &lt;code&gt;app/Jobs&lt;/code&gt; which implements a &lt;code&gt;ShouldQueue&lt;/code&gt; indicating that the job is to be run asynchronously. Don't worry if the Jobs folder doesn't exist yet, &lt;code&gt;artisan&lt;/code&gt; will create it if it's not there. In the new class we meet another &lt;code&gt;handle()&lt;/code&gt; method which like the command, is the sauce of our class which gets called when we run &lt;code&gt;dispatch&lt;/code&gt; and it where our code will live. &lt;br&gt;
   Hey there! Now the some of the reasons we are passing a Trial instance instead of say, email, might be obvious but in addition to what is in your head, we want a fresh instance of our eloquent model just before running it from the queue which is exactly what this does. &lt;a href="https://twitter.com/JacobBennett"&gt;Jacob Bennet&lt;/a&gt; has an amazing &lt;a href="https://gistlog.co/JacobBennett/e60d6a932db98985f160146b09455988"&gt;blog post&lt;/a&gt; that details this. Also, our handle method won't take a trial instance as a parameter directly, instead, we feed the instance to the job constructor and call it from the handler.&lt;br&gt;
Enough talk, show me the code! Alright, so here is what our &lt;code&gt;SendExpiryNotification&lt;/code&gt; job looks like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\Jobs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Bus\Queueable&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Queue\SerializesModels&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Queue\InteractsWithQueue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Contracts\Queue\ShouldQueue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Foundation\Bus\Dispatchable&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Support\Facades\Mail&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SendExpiryNotification&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;ShouldQueue&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Dispatchable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;InteractsWithQueue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Queueable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;SerializesModels&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nv"&gt;$trial&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$candidate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;trial&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$candidate&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;trial&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;Mail&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Hello, Your trial would be expiring soon and we wanted you to know!'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;$message&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ...hang in there
&lt;/h3&gt;

&lt;p&gt;Now that the big part is done, let's &lt;del&gt;see&lt;/del&gt; make it work. We will start our queue listen with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan queue:listen
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan queue:work &lt;span class="nt"&gt;--daemon&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
 though general opinion is that the second works much better. So while our queue listeners are still running, we launch our command using the command signature which in this case would be&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan trial_expiry:notify
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Easy-peasy innit? Oh and by the way, &lt;a href="https://laravel.com/docs/5.6/queues"&gt;here&lt;/a&gt; is laravel's queue documentation if you are that kind of person.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>queue</category>
      <category>jobs</category>
    </item>
    <item>
      <title>Building for Android SuperUsers: Let's extract WiFi passwords</title>
      <dc:creator>Michael Okoko</dc:creator>
      <pubDate>Sun, 05 Nov 2017 19:04:39 +0000</pubDate>
      <link>https://forem.com/idoko/building-for-android-superusers-lets-extract-wifi-passwords-3hp</link>
      <guid>https://forem.com/idoko/building-for-android-superusers-lets-extract-wifi-passwords-3hp</guid>
      <description>&lt;p&gt;In the beginning was a Manifest permission entry, and big G tagged it &lt;code&gt;android.permission.ACCESS_SUPERUSER&lt;/code&gt;, and it was okay. But then Android Lollipop came, and the simple snippet was removed, and Chainfire's superuser library came to the rescue.&lt;/p&gt;

&lt;h4&gt;
  
  
  What is libsuperuser?
&lt;/h4&gt;

&lt;p&gt;Libsuperuser is an android library that makes requesting and maintaining root access in your app as easy as you could ever imagine. We will be merely implementing it here in this demo app but if you feel like digging deeper (of course you should), you can check out the full &lt;a href="http://su.chainfire.eu/"&gt;HOW-to SU post&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  What are we building?
&lt;/h4&gt;

&lt;p&gt;We will be creating an app named Fi.Sniff. Android stores it's wireless networks data - SSID, Key, etc - in a file named &lt;code&gt;wpa_supplicant.conf&lt;/code&gt; in the &lt;code&gt;/data/misc/wifi/&lt;/code&gt; directory which can only be accessed by the root user. This is the file we will be exploring and parsing once the user gives us root access in the Fi.Sniff app.&lt;br&gt;
    Before we get started, Let's make sure we have android studio and the SDKs installed and working as well as a rooted android phone. Emulators won't work here.&lt;/p&gt;
&lt;h4&gt;
  
  
  Let's get coding!
&lt;/h4&gt;

&lt;p&gt;Open up android studio and create a new android project. Once your project is done and android studio is ready to rock, we need to add two dependencies, the first is the libsuperuser and then, android's recyclerview library to handle our list. So open your &lt;code&gt;app/build.gradle&lt;/code&gt; and add the following within the &lt;code&gt;dependencies&lt;/code&gt; block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;implementation 'eu.chainfire:libsuperuser:1.0.0.+'
implementation 'com.android.support:recyclerview-v7:26.0.0'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now getting to the meat of our application, let's edit the layout file associated with our main activity (I am assuming &lt;code&gt;activity_main.xml&lt;/code&gt; here) and replace the content with the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;android.support.constraint.ConstraintLayout&lt;/span&gt; &lt;span class="na"&gt;xmlns:android=&lt;/span&gt;&lt;span class="s"&gt;"http://schemas.android.com/apk/res/android"&lt;/span&gt;
    &lt;span class="na"&gt;xmlns:app=&lt;/span&gt;&lt;span class="s"&gt;"http://schemas.android.com/apk/res-auto"&lt;/span&gt;
    &lt;span class="na"&gt;xmlns:tools=&lt;/span&gt;&lt;span class="s"&gt;"http://schemas.android.com/tools"&lt;/span&gt;
    &lt;span class="na"&gt;android:layout_width=&lt;/span&gt;&lt;span class="s"&gt;"match_parent"&lt;/span&gt;
    &lt;span class="na"&gt;android:layout_height=&lt;/span&gt;&lt;span class="s"&gt;"match_parent"&lt;/span&gt;
    &lt;span class="na"&gt;tools:context=&lt;/span&gt;&lt;span class="s"&gt;"com.okmichaels.fisniff.MainActivity"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;android.support.v7.widget.RecyclerView&lt;/span&gt;
        &lt;span class="na"&gt;android:layout_width=&lt;/span&gt;&lt;span class="s"&gt;"match_parent"&lt;/span&gt;
        &lt;span class="na"&gt;android:layout_height=&lt;/span&gt;&lt;span class="s"&gt;"wrap_content"&lt;/span&gt;
        &lt;span class="na"&gt;android:id=&lt;/span&gt;&lt;span class="s"&gt;"@+id/network_list_recycler_view"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;/android.support.v7.widget.RecyclerView&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/android.support.constraint.ConstraintLayout&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the above code block as well as all subsequent ones, be sure to replace the package name with your app's. With that done, let's sprinkle some recycler view adapter and its variety of ingredients. But before we can dive into the adapter, let's create a layout that will reflect each of our wifi item on our user's screen. Create a new layout file (network_item_layout) and add the code below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;LinearLayout&lt;/span&gt; &lt;span class="na"&gt;xmlns:android=&lt;/span&gt;&lt;span class="s"&gt;"http://schemas.android.com/apk/res/android"&lt;/span&gt;
    &lt;span class="na"&gt;android:orientation=&lt;/span&gt;&lt;span class="s"&gt;"vertical"&lt;/span&gt; &lt;span class="na"&gt;android:layout_width=&lt;/span&gt;&lt;span class="s"&gt;"match_parent"&lt;/span&gt;
    &lt;span class="na"&gt;android:layout_height=&lt;/span&gt;&lt;span class="s"&gt;"wrap_content"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;TextView&lt;/span&gt;
        &lt;span class="na"&gt;android:id=&lt;/span&gt;&lt;span class="s"&gt;"@+id/network_ssid_view"&lt;/span&gt;
        &lt;span class="na"&gt;android:layout_width=&lt;/span&gt;&lt;span class="s"&gt;"match_parent"&lt;/span&gt;
        &lt;span class="na"&gt;android:layout_height=&lt;/span&gt;&lt;span class="s"&gt;"wrap_content"&lt;/span&gt;
        &lt;span class="na"&gt;android:textSize=&lt;/span&gt;&lt;span class="s"&gt;"14sp"&lt;/span&gt;
        &lt;span class="na"&gt;android:textStyle=&lt;/span&gt;&lt;span class="s"&gt;"bold"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;TextView&lt;/span&gt;
        &lt;span class="na"&gt;android:id=&lt;/span&gt;&lt;span class="s"&gt;"@+id/network_psk_view"&lt;/span&gt;
        &lt;span class="na"&gt;android:layout_width=&lt;/span&gt;&lt;span class="s"&gt;"match_parent"&lt;/span&gt;
        &lt;span class="na"&gt;android:layout_height=&lt;/span&gt;&lt;span class="s"&gt;"wrap_content"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/LinearLayout&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the adapter, we will be creating a new class named &lt;code&gt;NetworkListAdapter&lt;/code&gt; as well as an associated inner ViewHolder class (&lt;code&gt;NetworkViewHolder&lt;/code&gt;). Our adapter class should look like this when we are done:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;com.okmichaels.fisniff&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;android.content.Context&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;android.support.v7.widget.RecyclerView&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;android.view.LayoutInflater&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;android.view.View&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;android.view.ViewGroup&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;android.widget.TextView&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.List&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NetworkListAdapter&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;RecyclerView&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Adapter&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;NetworkListAdapter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;NetworkViewHolder&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Network&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;networkList&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Context&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;NetworkListAdapter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Context&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Network&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;networkList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;getItemCount&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;networkList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;NetworkViewHolder&lt;/span&gt; &lt;span class="nf"&gt;onCreateViewHolder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ViewGroup&lt;/span&gt; &lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;viewtype&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;View&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LayoutInflater&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getContext&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;inflate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;R&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;layout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;network_item_layout&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;NetworkViewHolder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onBindViewHolder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;NetworkViewHolder&lt;/span&gt; &lt;span class="n"&gt;holder&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Network&lt;/span&gt; &lt;span class="n"&gt;network&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;networkList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;holder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ssidView&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setText&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;network&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getSsid&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="n"&gt;holder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;pskView&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setText&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;network&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getPsk&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NetworkViewHolder&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;RecyclerView&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ViewHolder&lt;/span&gt;
    &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;TextView&lt;/span&gt; &lt;span class="n"&gt;ssidView&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="nc"&gt;TextView&lt;/span&gt; &lt;span class="n"&gt;pskView&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

        &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;NetworkViewHolder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;View&lt;/span&gt; &lt;span class="n"&gt;itemView&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;super&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;itemView&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;ssidView&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;itemView&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;findViewById&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;R&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;network_ssid_view&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;pskView&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;itemView&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;findViewById&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;R&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;network_psk_view&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;refreshList&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Network&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;networks&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;networkList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;clear&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;networkList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addAll&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;networks&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;notifyDataSetChanged&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;PS: If the whole RecyclerView and ViewHolder pattern thingy seems foreign to you, try looking up the official documentation here or this awesome tutorial by&lt;br&gt;
Another PS: If you get squigly red lines beneath the Network class in the above, Farabale - we are coming to that soon.&lt;/p&gt;

&lt;p&gt;Next, we need to create a data class (ViewModel in android lingo). Basically, this class reflects the items to be displayed in the adapter so create a new &lt;code&gt;Network&lt;/code&gt; class and add the code below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;com.okmichaels.fisniff&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Network&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;ssid&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;psk&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Network&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ssid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;psk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setSsid&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;ssid&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ssid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ssid&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setPsk&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;psk&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;psk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;psk&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Network&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;ssid&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ssid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ssid&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;psk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getSsid&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ssid&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getPsk&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;psk&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now to our main activity. This is where stuff gets interesting. You remember that superuser library you added? This is where you get to make it work but hang on! Modify your Main Activity file to look like this first: Android Studio might whine about unused imports blah blah blah, ask it to drink water and proceed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;com.okmichaels.fisniff&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;android.os.AsyncTask&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;android.support.v7.app.AppCompatActivity&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;android.os.Bundle&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;android.support.v7.widget.LinearLayoutManager&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;android.support.v7.widget.RecyclerView&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.ArrayList&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.Arrays&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.List&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.regex.Matcher&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.regex.Pattern&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;eu.chainfire.libsuperuser.Shell&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MainActivity&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;AppCompatActivity&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;RecyclerView&lt;/span&gt; &lt;span class="n"&gt;networkListView&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;NetworkListAdapter&lt;/span&gt; &lt;span class="n"&gt;adapter&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onCreate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Bundle&lt;/span&gt; &lt;span class="n"&gt;savedInstanceState&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;onCreate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;savedInstanceState&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;setContentView&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;R&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;layout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;activity_main&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;networkListView&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;findViewById&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;R&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;network_list_recycler_view&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;networkListView&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setLayoutManager&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;LinearLayoutManager&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;getApplicationContext&lt;/span&gt;&lt;span class="o"&gt;()));&lt;/span&gt;
        &lt;span class="n"&gt;adapter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;NetworkListAdapter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;getApplicationContext&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt;
                &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Network&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;());&lt;/span&gt;
        &lt;span class="n"&gt;networkListView&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setAdapter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;adapter&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now back to the shell. Good news is this is probably the easiest part. Bad news is you don't run SU commands on the main thread plus it returns an ArrayList of Strings where each element is a line in the command's return value. Anyway, let's add it up and be done with right? Add a new AsyncTask child within your main activity and let it mirror the code as shown: (Mine is named NetworkFetcherTask and I've added comments where necessary to shed light on what we are trying to do)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NetworkFetcherTask&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;AsyncTask&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Void&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Void&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Network&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;suEh&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="nd"&gt;@Override&lt;/span&gt;
        &lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Network&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;doInBackground&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Void&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="n"&gt;voids&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Network&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;networks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
            &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;supplicant&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
            &lt;span class="cm"&gt;/*this is what triggers the SuperUser permission on the device, if the phone is not rooted or the permissioin is denied, it returns false.*/&lt;/span&gt;
            &lt;span class="n"&gt;suEh&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Shell&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SU&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;available&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;suEh&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="cm"&gt;/*android stores wifi data in the wpa_supplicant.conf file in the location below, let's try printing it ðŸ™ðŸ™*/&lt;/span&gt;
                &lt;span class="n"&gt;supplicant&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Shell&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SU&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"cat /data/misc/wifi/wpa_supplicant.conf"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="cm"&gt;/*the return value of SU.run() is an array list, let's flatten it into a string to ease parsing with regex*/&lt;/span&gt;
                &lt;span class="nc"&gt;StringBuilder&lt;/span&gt; &lt;span class="n"&gt;flattener&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;StringBuilder&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;supplicant&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nl"&gt;line:&lt;/span&gt; &lt;span class="n"&gt;supplicant&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                        &lt;span class="n"&gt;flattener&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;append&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
                    &lt;span class="o"&gt;}&lt;/span&gt;
                &lt;span class="o"&gt;}&lt;/span&gt;
                &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;flattened&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;flattener&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

                &lt;span class="cm"&gt;/*okay, let's find every network block(they exist within curly brackets hence the expression*/&lt;/span&gt;
                &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;exp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"\\{(.*?)\\}"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
                &lt;span class="nc"&gt;Pattern&lt;/span&gt; &lt;span class="n"&gt;pattern&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Pattern&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;compile&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exp&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
                &lt;span class="nc"&gt;Matcher&lt;/span&gt; &lt;span class="n"&gt;matcher&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pattern&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;matcher&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;flattened&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

                &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;matcher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;find&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                    &lt;span class="nc"&gt;Network&lt;/span&gt; &lt;span class="n"&gt;network&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Network&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
                    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;el&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;matcher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;group&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
                    &lt;span class="c1"&gt;//List&amp;lt;String&amp;gt; lineAsItem = Arrays.asList(el.split(" "));&lt;/span&gt;
                    &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;lineAsItem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;el&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;split&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\\s+"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
                    &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nl"&gt;line:&lt;/span&gt; &lt;span class="n"&gt;lineAsItem&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

                        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;contains&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"="&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                            &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;split&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"="&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
                            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="na"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ssid"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                                &lt;span class="n"&gt;network&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setSsid&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;]);&lt;/span&gt;
                            &lt;span class="o"&gt;}&lt;/span&gt;
                            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="na"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"psk"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                                &lt;span class="n"&gt;network&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setPsk&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;]);&lt;/span&gt;
                            &lt;span class="o"&gt;}&lt;/span&gt;
                        &lt;span class="o"&gt;}&lt;/span&gt;
                    &lt;span class="o"&gt;}&lt;/span&gt;
                    &lt;span class="n"&gt;networks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;network&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
                &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;networks&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onPostExecute&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Network&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;adapter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;refreshList&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One more thing. We need to ask our MainActivity (nicely) to execute this async task so add the following in your MainActivity's onCreate() method to call the task once the activity is setup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;NetworkFetcherTask&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;execute&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run your application and see the glory!&lt;/p&gt;

</description>
      <category>superuser</category>
      <category>su</category>
      <category>android</category>
      <category>root</category>
    </item>
  </channel>
</rss>
