title: Finding Miracast connections with Android
body: <p>I am trying to build an Android app that scans for local Miracast connections and connects to them to mirror the screen automatically. I also want the ability to save connections that the user has already connected to before and give them nicknames so the user can recognize them easier. I don't have hardly any experience with Android development, but I have years of experience with Java and other languages.</p>
  
  <p>Right now, the problem I have is my ListView returns a null pointer exception when I try to set the Adapter in the OnCreate method of my MainActivity.</p>
  
  <p><strong>MainActivity.java</strong>   </p>
  
  <pre><code>import java.io.IOException;
  import java.net.InetAddress;
  import java.net.ServerSocket;
  import java.net.Socket;
  import java.util.ArrayList;
  import java.util.Collection;
  
  import android.app.Fragment;
  import android.app.Presentation;
  import android.content.Context;
  import android.content.Intent;
  import android.content.IntentFilter;
  import android.content.SharedPreferences;
  import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
  import android.hardware.display.DisplayManager;
  import android.media.MediaRouter;
  import android.net.NetworkInfo;
  import android.net.wifi.WpsInfo;
  import android.net.wifi.p2p.WifiP2pConfig;
  import android.net.wifi.p2p.WifiP2pDevice;
  import android.net.wifi.p2p.WifiP2pDeviceList;
  import android.net.wifi.p2p.WifiP2pGroup;
  import android.net.wifi.p2p.WifiP2pInfo;
  import android.net.wifi.p2p.WifiP2pManager;
  import android.net.wifi.p2p.WifiP2pManager.ActionListener;
  import android.net.wifi.p2p.WifiP2pManager.Channel;
  import android.net.wifi.p2p.WifiP2pManager.ChannelListener;
  import android.net.wifi.p2p.WifiP2pManager.GroupInfoListener;
  import android.net.wifi.p2p.WifiP2pManager.PeerListListener;
  import android.os.Bundle;
  import android.support.v4.app.DialogFragment;
  import android.support.v4.app.FragmentActivity;
  import android.util.Log;
  import android.view.Display;
  import android.view.LayoutInflater;
  import android.view.Menu;
  import android.view.MenuItem;
  import android.view.View;
  import android.view.ViewGroup;
  import android.widget.Button;
  import android.widget.CheckBox;
  import android.widget.ListView;
  import android.widget.ProgressBar;
  import android.widget.TextView;
  import android.widget.Toast;
  
  public class MainActivity extends FragmentActivity implements OnSharedPreferenceChangeListener{
  
  public static final String TAG = "MainActivity";
  private MediaRouter mMediaRouter;
  private WifiP2pManager wifimngr; 
  protected Channel channel;
  private boolean paused = false;
  private boolean connected = false;
  private boolean scanning = false;
  protected boolean isWifiEnabled;
  protected boolean onCharge;
  protected boolean onAlways;
  protected MyBroadcastReceiver receiver;
  protected ArrayList&lt;WifiP2pDevice&gt; connectionList;
  protected int listsize;
  private DisplayManager mDisplayManager;
  protected ConnectionAdapter adapter;
  protected ArrayList&lt;WifiP2pDevice&gt; devices;
  private final IntentFilter intentFilter = new IntentFilter();
  
  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
  
      connectionList = new ArrayList&lt;WifiP2pDevice&gt;();
      adapter = new ConnectionAdapter(this, devices);
      ListView listview = (ListView) findViewById(R.id.list);
      listview.setAdapter(adapter);
  
      //Connection newCon = new Connection("My address", "My nickname", false);
      //adapter.add(newCon);
      //newCon = new Connection("My address2", "My nickname2", true);
      //adapter.add(newCon);
  
      //  Indicates a change in the Wi-Fi P2P status.
      intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
  
      // Indicates a change in the list of available peers.
      intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
  
      // Indicates the state of Wi-Fi P2P connectivity has changed.
      intentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
  
      // Indicates this device's details have changed.
      intentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
  
  
      mDisplayManager = (DisplayManager)this.getSystemService(Context.DISPLAY_SERVICE);
      if (savedInstanceState == null) {
          getFragmentManager().beginTransaction()
                  .add(R.id.container, new PlaceholderFragment())
                  .commit();
      }
  
      wifimngr = (WifiP2pManager)getSystemService(Context.WIFI_P2P_SERVICE);
      channel  = wifimngr.initialize(this, getMainLooper(), new ChannelListener() {
          public void onChannelDisconnected() {
              channel = null;
          }
      });
  
  }
  
  PeerListListener myPeerListListener =
             new PeerListListener() {
                  @Override
                  public void onPeersAvailable(WifiP2pDeviceList peerList) {
  
                      // Out with the old, in with the new.
                      devices.clear();
                      devices.addAll(peerList.getDeviceList());
  
                      // If an AdapterView is backed by this data, notify it
                      // of the change.  For instance, if you have a ListView of available
                      // peers, trigger an update.
                      //((ConnectionAdapter) getListAdapter()).notifyDataSetChanged();
                      if (devices.size() == 0) {
                          Log.d("TAG", "No devices found");
                          return;
                      }
                  }
  
          };
  
  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
  
      // Inflate the menu; this adds items to the action bar if it is present.
      getMenuInflater().inflate(R.menu.main, menu);
      return true;
  }
  
  @Override
  public boolean onOptionsItemSelected(MenuItem item) {
      // Handle action bar item clicks here. The action bar will
      // automatically handle clicks on the Home/Up button, so long
      // as you specify a parent activity in AndroidManifest.xml.
      int id = item.getItemId();
      if (id == R.id.action_settings) {
          openSettings();
          return true;
      }
      return super.onOptionsItemSelected(item);
  }
  
  /**
   * A placeholder fragment containing a simple view.
   */
  public static class PlaceholderFragment extends Fragment {
  
      public PlaceholderFragment() {
      }
  
      @Override
      public View onCreateView(LayoutInflater inflater, ViewGroup container,
              Bundle savedInstanceState) {
          View rootView = inflater.inflate(R.layout.fragment_main, container, false);
          return rootView;
      }
  }
  
  public void updateStatus(String input)
  {
      TextView edit = (TextView) findViewById(R.id.statusText);
      edit.setText(input);
  }
  
  //What happens when the pause button is clicked
  public void pauseConnections(View view)
  {
      if(!paused)
      {
          updateStatus("Streaming");
          mMediaRouter = (MediaRouter) this.getSystemService(Context.MEDIA_ROUTER_SERVICE);
  
           MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute(mMediaRouter.ROUTE_TYPE_LIVE_VIDEO);
           if (route != null) {
               Display presentationDisplay = route.getPresentationDisplay();
               if (presentationDisplay != null) {
                   Presentation presentation = new Presentation(this, presentationDisplay, 0);
                   presentation.show();
               }
           }
          ProgressBar pg = (ProgressBar) findViewById(R.id.progressBar1);
          pg.setVisibility(View.VISIBLE);
          Button edit = (Button) findViewById(R.id.pauseButton);
          edit.setText("Pause");
          edit = (Button) findViewById(R.id.scanbutton);
          edit.setEnabled(false);
      }else
      {
          updateStatus("Paused");
  
  
           MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute(mMediaRouter.ROUTE_TYPE_LIVE_VIDEO);
           if (route != null) {
               Display presentationDisplay = route.getPresentationDisplay();
               if (presentationDisplay != null) {
                   Presentation presentation = new Presentation(this, presentationDisplay, 0);
                   presentation.show();
               }
           }
          ProgressBar pg = (ProgressBar) findViewById(R.id.progressBar1);
          pg.setVisibility(View.INVISIBLE);
          Button edit = (Button) findViewById(R.id.pauseButton);
          edit.setText("Stream");
          edit = (Button) findViewById(R.id.scanbutton);
          edit.setEnabled(true);
      }
      paused=!paused;
  
  
  }
  
  //What happens when the scan button is clicked
  public void scanConnections(View view)
  {
  
      if(!scanning)
      {
  
          updateStatus("Scanning...");
          ProgressBar pg = (ProgressBar) findViewById(R.id.progressBar1);
          pg.setVisibility(View.VISIBLE);
          wifimngr.setMiracastMode(1);
          wifimngr.discoverPeers(channel, new WifiP2pManager.ActionListener() {
  
              @Override
              public void onSuccess() {
  
              }
  
              @Override
              public void onFailure(int reason) {
                  if(reason == 1)
                  {
                      updateStatus("Failed to get devices. Device not supported");
  
                  }else if(reason == 2)
                  {
                      updateStatus("Failed to get devices. Busy");
                  }else
                  {
                      updateStatus("Failed to get devices. Error");
                  }
                  ProgressBar pg = (ProgressBar) findViewById(R.id.progressBar1);
                  pg.setVisibility(View.INVISIBLE);
                  Button edit = (Button) findViewById(R.id.scanbutton);
                  edit.setText("Scan");
                  edit = (Button) findViewById(R.id.pauseButton);
                  edit.setEnabled(true);
                  scanning=!scanning;
  
              }
          });
  
          Button edit = (Button) findViewById(R.id.scanbutton);
          edit.setText("Stop");
          edit = (Button) findViewById(R.id.pauseButton);
          edit.setEnabled(false);
      }else
      {
  
          ProgressBar pg = (ProgressBar) findViewById(R.id.progressBar1);
          pg.setVisibility(View.INVISIBLE);
          wifimngr.removeGroup(channel, new WifiP2pManager.ActionListener() {
  
              @Override
              public void onSuccess() {
  
  
              }
  
              @Override
              public void onFailure(int reason) {
                  if(reason == 1)
                  {
                      updateStatus("Failed to disconnect. Device not supported");
  
                  }else if(reason == 2)
                  {
                      updateStatus("Failed to disconnect. Busy");
                  }else
                  {
                      updateStatus("Failed to disconnect. Error");
                  }
                  ProgressBar pg = (ProgressBar) findViewById(R.id.progressBar1);
                  pg.setVisibility(View.INVISIBLE);
  
              }
          });         
  
          updateStatus("Waiting");
          Button edit = (Button) findViewById(R.id.scanbutton);
          edit.setText("Scan");
          edit = (Button) findViewById(R.id.pauseButton);
          edit.setEnabled(true);
      }
      scanning=!scanning;
  }
  
  public void openSettings()
  {
      Intent intent = new Intent(this, SettingsActivity.class);
      intent.putExtra("onCharge", onCharge);
      intent.putExtra("onAlways", onAlways);
      startActivity(intent);
  
  }
  
  public void onCheckboxClicked(View view)
  {
      boolean checked = ((CheckBox) view).isChecked();
  
  }
  
  public void onConnectionClick(View view)
  {
      DialogFragment dialog = new ConnDialogFragment();
      dialog.show(getSupportFragmentManager(), "NoticeDialogFragment");
  
  }
  
  public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
          String key) {
          if (key.equals("pref_onCharge")) {
  
              // Set summary to be the user-description for the selected value
              onCharge = sharedPreferences.getBoolean(key, true);
          }else if (key.equals("pref_onAlways")) {
  
              // Set summary to be the user-description for the selected value
              onAlways = sharedPreferences.getBoolean(key, false);
          }else if(key.equals("pref_listsize"))
          {
              listsize = sharedPreferences.getInt(key, 0);
          }
      }
  
  private void onPeersChanged(Intent intent)
  {
      wifimngr.requestPeers(channel, myPeerListListener);
  }
  
  private void onConnectionChanged(Intent intent) {
      WifiP2pInfo p2pInfo = intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO);
      NetworkInfo netInfo = intent.getParcelableExtra(WifiP2pManager.EXTRA_NETWORK_INFO);
      if (netInfo.isConnected()) 
      {
          updateInfos();
          useNetwork(p2pInfo);
      } else 
      {
          //resetInfos();
      }
  }
  
  
  public void connect() {
      // Picking the first device found on the network.
      WifiP2pDevice device = devices.get(0);
  
      WifiP2pConfig config = new WifiP2pConfig();
      config.deviceAddress = device.deviceAddress;
      config.wps.setup = WpsInfo.PBC;
  
      wifimngr.connect(channel, config, new ActionListener() {
  
          @Override
          public void onSuccess() {
              // WiFiDirectBroadcastReceiver will notify us. Ignore for now.
          }
  
          @Override
          public void onFailure(int reason) {
              Toast.makeText(MainActivity.this, "Connect failed. Retry.",
                      Toast.LENGTH_SHORT).show();
          }
      });
  }
  
  
  public void onConnectionInfoAvailable(final WifiP2pInfo info) {
  
      // InetAddress from WifiP2pInfo struct.
      InetAddress groupOwnerAddress = info.groupOwnerAddress;
  
      // After the group negotiation, we can determine the group owner.
      if (info.groupFormed &amp;&amp; info.isGroupOwner) {
          // Do whatever tasks are specific to the group owner.
          // One common case is creating a server thread and accepting
          // incoming connections.
      } else if (info.groupFormed) {
          // The other device acts as the client. In this case,
          // you'll want to create a client thread that connects to the group
          // owner.
      }
  }
  
  
  private void updateInfos() {
      wifimngr.requestGroupInfo(channel,
         new GroupInfoListener() {
          @Override
          public void onGroupInfoAvailable(WifiP2pGroup group)
         {
              String name = group.getNetworkName();
              String passphrase = group.getPassphrase();
              Collection&lt;WifiP2pDevice&gt; devices = group.getClientList();
                      // do stuff with devices
                      // but ... No way to get their IP addresses :(
          }
      });
  }
  
  private void useNetwork(WifiP2pInfo p2pInfo) {
      if (!p2pInfo.isGroupOwner) {
          InetAddress addr  = p2pInfo.groupOwnerAddress;
          try
          {
              Socket s  = new Socket(addr, 1234);
          }catch(IOException e)
          {
              e.printStackTrace();
          }
  
           //use the socket
      } else {
          try{
               //groupOwnerAddress is our local address
               ServerSocket serverSocket = new ServerSocket(1234);
              Socket s  = serverSocket.accept();
              }catch(IOException e)
              {
                  e.printStackTrace();
              }
           //use the socket
      }
  }
  
  private void connect(WifiP2pDevice device) {
      WifiP2pConfig config = new WifiP2pConfig();
      config.deviceAddress = device.deviceAddress;
      config.wps.setup = WpsInfo.PBC; // choose between what is available on the device.
      wifimngr.connect(channel, config, new WifiP2pManager.ActionListener() {
  
          @Override
          public void onSuccess() {
  
          }
  
          @Override
          public void onFailure(int reason) {
  
  
          }
      });
  }
  
  protected void setIsWifiP2pEnabled(boolean isEnabled)
  {
      isWifiEnabled = isEnabled;
  }
  
  /** register the BroadcastReceiver with the intent values to be matched */
  @Override
  public void onResume() {
      super.onResume();
      receiver = new MyBroadcastReceiver(wifimngr, channel, this);
      registerReceiver(receiver, intentFilter);
  }
  
  @Override
  public void onPause() {
      super.onPause();
      unregisterReceiver(receiver);
  }
  
  
  }
  </code></pre>
  
  <p><strong>ConnectionAdapter.java</strong></p>
  
  <pre><code>    import java.util.ArrayList;
  
      import android.content.Context;
      import android.net.wifi.p2p.WifiP2pDevice;
      import android.view.LayoutInflater;
      import android.view.View;
      import android.view.ViewGroup;
      import android.widget.ArrayAdapter;
      import android.widget.TextView;
  
      public class ConnectionAdapter extends ArrayAdapter&lt;WifiP2pDevice&gt; {
  
      public ConnectionAdapter(Context context, ArrayList&lt;WifiP2pDevice&gt; connections)
      {
          super(context, R.layout.connection, connections);
      }
  
      @Override
      public View getView(int position, View convertView, ViewGroup parent) {
         // Get the data item for this position
          WifiP2pDevice con = getItem(position);    
         // Check if an existing view is being reused, otherwise inflate the view
         ViewHolder viewHolder; 
  
         if (convertView == null) {
            viewHolder = new ViewHolder();
            LayoutInflater inflater = LayoutInflater.from(getContext());
            convertView = inflater.inflate(R.layout.connection, parent, false);
            viewHolder.name = (TextView) convertView.findViewById(R.id.conName);
            viewHolder.nickname = (TextView) convertView.findViewById(R.id.conNickname);
            convertView.setTag(viewHolder);
         }else {
             viewHolder = (ViewHolder) convertView.getTag();
         }
  
         // Populate the data into the template view using the data object
         viewHolder.name.setText(con.deviceName);
         viewHolder.nickname.setText(con.primaryDeviceType);
         // Return the completed view to render on screen
         return convertView;
      }
  
       private static class ViewHolder {
              TextView name;
              TextView nickname;
          }
      }
  
  
  **BroadcastReceiver.java**
  
  
      import android.content.BroadcastReceiver;
      import android.content.Context;
      import android.content.Intent;
      import android.net.NetworkInfo;
      import android.net.wifi.p2p.WifiP2pDevice;
      import android.net.wifi.p2p.WifiP2pManager;
      import android.net.wifi.p2p.WifiP2pManager.Channel;
      import android.net.wifi.p2p.WifiP2pManager.PeerListListener;
      import android.util.Log;
  
      public class MyBroadcastReceiver extends BroadcastReceiver{
  
      protected WifiP2pManager wifimngr;
      protected Channel channel;
      protected MainActivity activity;
  
      public MyBroadcastReceiver(WifiP2pManager iwifimngr, Channel ichannel, MainActivity iactivity)
      {
          super();
          wifimngr=iwifimngr;
          channel=ichannel;
          activity=iactivity;
      }
  
      @Override
      public void onReceive(Context context, Intent intent) {
          String action = intent.getAction();
          if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {
              // Determine if Wifi P2P mode is enabled or not, alert
              // the Activity.
              int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1);
              if (state == WifiP2pManager.WIFI_P2P_STATE_ENABLED) {
                  activity.setIsWifiP2pEnabled(true);
              } else {
                  activity.setIsWifiP2pEnabled(false);
              }
          } else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {
  
              // Request available peers from the wifi p2p manager. This is an
              // asynchronous call and the calling activity is notified with a
              // callback on PeerListListener.onPeersAvailable()
              if (wifimngr != null) {
                  wifimngr.requestPeers(channel, (PeerListListener) activity.getFragmentManager()
                           .findFragmentById(R.id.list));
              }
              Log.d(MainActivity.TAG, "P2P peers changed");
  
  
          } else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {
  
              if (wifimngr == null) {
                  return;
              }
  
              NetworkInfo networkInfo = (NetworkInfo) intent
                      .getParcelableExtra(WifiP2pManager.EXTRA_NETWORK_INFO);
  
              if (networkInfo.isConnected()) {
  
                  // we are connected with the other device, request connection
                  // info to find group owner IP
  
                 //DeviceDetailFragment fragment = (DeviceDetailFragment) activity
                  //        .getFragmentManager().findFragmentById(R.id.frag_detail);
                  //wifimngr.requestConnectionInfo(channel, fragment);
              } else {
                  // It's a disconnect
                  //activity.resetData();
              }
  
          } else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) {
              DeviceListFragment fragment = (DeviceListFragment) activity.getFragmentManager()
                      .findFragmentById(R.id.list);
              fragment.updateThisDevice((WifiP2pDevice) intent.getParcelableExtra(
                      WifiP2pManager.EXTRA_WIFI_P2P_DEVICE));
  
          }
      }
  
  
  
      }
  </code></pre>
  
  <p><strong>activity_main.xml</strong></p>
  
  <pre><code> &lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:tools="http://schemas.android.com/tools"
      android:id="@+id/container"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      tools:context="com.hpconcept.miracastconnector.MainActivity"
      tools:ignore="MergeRootFrame" &gt;
  
      &lt;ListView
          android:id="@+id/list"
          android:layout_width="wrap_content"
          android:layout_height="250dp"
          android:layout_marginTop="0dp"
          android:layout_marginBottom="0dp"
          android:paddingTop="0dp"
          android:textSize="20sp" &gt;
      &lt;/ListView&gt;
  
      &lt;View android:id="@+id/strut"
          android:layout_width="0dp"
          android:layout_height="0dp" 
          android:layout_marginTop="200dp"
          android:layout_below="@android:id/list"
          android:layout_centerHorizontal="true"/&gt;
  
      &lt;Button
          android:id="@+id/scanbutton"
          android:text="@string/scan_string"
          android:layout_height="wrap_content"
          android:layout_below="@android:id/list"
          android:layout_width="0dp"
          android:layout_alignParentBottom="true"
          android:onClick="scanConnections"
          android:layout_alignRight="@id/strut"
          android:layout_alignParentLeft="true"
           /&gt;
  
      &lt;Button
          android:id="@+id/pauseButton"
          android:text="@string/stream_string"
          android:layout_width="0dp"
          android:layout_height="wrap_content"
          android:onClick="pauseConnections"
          android:layout_gravity="bottom"
          android:layout_alignLeft="@id/strut"
          android:layout_alignParentRight="true"
          android:layout_alignParentBottom="true"
          android:layout_below="@android:id/list"
          android:layout_toRightOf="@+id/scanbutton" /&gt;
  
      &lt;TextView
          android:id="@+id/statusText"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:layout_above="@+id/pauseButton"
          android:layout_alignLeft="@+id/pauseButton"
          android:layout_marginLeft="42dp"
          android:gravity="center"
          android:text="@string/waiting_string" /&gt;
  
      &lt;ProgressBar
          android:id="@+id/progressBar1"
          style="?android:attr/progressBarStyleSmall"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:layout_alignBottom="@+id/statusText"
          android:layout_alignLeft="@+id/pauseButton"
          android:layout_marginLeft="24dp"
          android:visibility="invisible" /&gt;
  
      &lt;/RelativeLayout&gt;
  </code></pre>
  
  <p>So this whole project is basically turning into me trying to duct-tape together various pieces of sample code from around the internet. I could really use some help. I'm trying to use Google's Android development pages, but I don't always know where to put their snippets of code. I was trying to make my own Connection class, that would hold the WifiP2pDevice's in an arraylist along with the nicknames and other data, but I couldn't get it to work for some reason. So now my priority is just getting the program to run and find connections. I did finish the GUI to the best of my knowledge. I might need to change it or something though.
  This is not all of my code. If I posted it all, this question would be huge. lol If you want to see it all, let me know.</p>