I'm trying to connect 2 devices with wifi direct, let's say device A and device B with android > 4.1. If I'm on device A and I press the button to search for other devices it doesn't act always the same way.
For example if I press the search button on device A, it doesn't find anything until I press the search button on the device B too, even if the app is going on both. So the device B is not visible until it doesn't start searching for other devices too.
Other times if I search for devices with device A, it finds device B even if the app was closed recently on device B and if I try to connect to device B it works. The problem is that I want to establish a connection only if the app is running on both devices.
Sometimes when device A finds out device B and it tries to connect to it, it doesn't work until device B starts to find devices. So when I start the searching on device B it receives the connection request from A, but nothing until then.
Some other times, after pressing the search button on device A, it shows some devices that hasn't the wifi enabled at that moment or that are out of range.
Here's my code:
MainActivity.java
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.IntentFilter;
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.WifiP2pManager;
import android.net.wifi.p2p.WifiP2pManager.ActionListener;
import android.net.wifi.p2p.WifiP2pManager.Channel;
import android.net.wifi.p2p.WifiP2pManager.GroupInfoListener;
import android.net.wifi.p2p.WifiP2pManager.PeerListListener;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckedTextView;
import android.widget.ListView;
import android.widget.Toast;
public class MainActivity extends Activity implements OnItemClickListener, PeerListListener {
private WifiP2pManager mManager;
private Channel mChannel;
private BroadcastReceiver mReceiver;
private IntentFilter mIntentFilter;
private List<WifiP2pDevice> peers = new ArrayList<WifiP2pDevice>();
private List<WifiP2pDevice> peersConnect = new ArrayList<WifiP2pDevice>();
private ArrayList<String> peersName = new ArrayList<String>();
private ListView list;
private Button bSearch;
private Button bConnect;
private Button bDisconnect;
private int nSelectedDevices = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mManager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
mChannel = mManager.initialize(this, getMainLooper(), null);
try {
Class<?> wifiManager = Class
.forName("android.net.wifi.p2p.WifiP2pManager");
Method method = wifiManager
.getMethod(
"enableP2p",
new Class[] { android.net.wifi.p2p.WifiP2pManager.Channel.class });
method.invoke(mManager, mChannel);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mIntentFilter = new IntentFilter();
mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_DISCOVERY_CHANGED_ACTION);
bSearch = (Button) this.findViewById(R.id.searcher);
bSearch.setOnClickListener(new OnClickListener() {
public void onClick (View v) {
list.setVisibility(ListView.INVISIBLE);
bConnect.setVisibility(View.INVISIBLE);
bDisconnect.setVisibility(View.INVISIBLE);
nSelectedDevices = 0;
peersConnect.clear();
peers.clear();
peersName.clear();
searchDevices();
}
});
bConnect = (Button) this.findViewById(R.id.connecter);
bConnect.setOnClickListener(new OnClickListener() {
public void onClick (View v) {
bDisconnect.setVisibility(View.VISIBLE);
connectDevices();
bConnect.setVisibility(View.INVISIBLE);
nSelectedDevices = 0;
peersConnect.clear();
}
});
bDisconnect = (Button) this.findViewById(R.id.disconnecter);
bDisconnect.setOnClickListener(new OnClickListener() {
public void onClick (View v) {
disconnectDevices();
peersConnect.clear();
bDisconnect.setVisibility(View.INVISIBLE);
}
});
list = (ListView) this.findViewById(R.id.list);
list.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
//-- text filtering
list.setTextFilterEnabled(true);
}
/* register the broadcast receiver with the intent values to be matched */
@Override
protected void onResume() {
super.onResume();
mReceiver = new WifiReceiver(mManager, mChannel, this);
registerReceiver(mReceiver, mIntentFilter);
}
/* unregister the broadcast receiver */
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(mReceiver);
}
@Override
protected void onDestroy() {
super.onDestroy();
finish();
}
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
CheckedTextView item = (CheckedTextView) v;
if(item.isChecked()) {
nSelectedDevices++;
peersConnect.add(peers.get(position));
}
else {
nSelectedDevices--;
peersConnect.remove(peers.get(position));
}
if(nSelectedDevices == 1)
bConnect.setVisibility(View.VISIBLE);
else if(nSelectedDevices == 0)
bConnect.setVisibility(View.INVISIBLE);
}
@Override
public void onPeersAvailable(WifiP2pDeviceList peerList) {
// Out with the old, in with the new.
peers.clear();
peers.addAll(peerList.getDeviceList());
getDeviceName();
list.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_checked, peersName));
list.setOnItemClickListener(this);
list.setVisibility(ListView.VISIBLE);
// 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.
//((ListAdapter) getListAdapter()).notifyDataSetChanged();
if (peers.size() == 0) {
return;
}
}
private void searchDevices() {
mManager.discoverPeers(mChannel, new WifiP2pManager.ActionListener() {
@Override
public void onSuccess() {
//Toast.makeText(MainActivity.this, "Inizio ricerca...", Toast.LENGTH_SHORT).show();
}
@Override
public void onFailure(int reasonCode) {
//Toast.makeText(MainActivity.this, "Ricerca fallita!", Toast.LENGTH_SHORT).show();
}
});
}
private void connectDevices() {
for(int i = 0; i < peersConnect.size(); i++) {
// Picking the first device found on the network.
WifiP2pDevice device = peersConnect.get(i);
WifiP2pConfig config = new WifiP2pConfig();
config.deviceAddress = device.deviceAddress;
config.wps.setup = WpsInfo.PBC;
mManager.connect(mChannel, config, new ActionListener() {
@Override
public void onSuccess() {
// WiFiDirectBroadcastReceiver will notify us. Ignore for now.
Toast.makeText(MainActivity.this, "Connection requested...", Toast.LENGTH_SHORT).show();
}
@Override
public void onFailure(int reason) {
Toast.makeText(MainActivity.this, "Connect failed. Retry.", Toast.LENGTH_SHORT).show();
}
});
}
}
public void disconnectDevices() {
if (mManager != null && mChannel != null) {
mManager.requestGroupInfo(mChannel, new GroupInfoListener() {
@Override
public void onGroupInfoAvailable(WifiP2pGroup group) {
if (group != null && mManager != null && mChannel != null && group.isGroupOwner()) {
mManager.removeGroup(mChannel, new ActionListener() {
@Override
public void onSuccess() {
}
@Override
public void onFailure(int reason) {
}
});
}
}
});
}
}
private void getDeviceName() {
int i = 0;
peersName.clear();
while(i < peers.size()) {
peersName.add(peers.get(i).deviceName);
i++;
}
}
@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) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
WifiReceiver.java
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.wifi.p2p.WifiP2pManager;
import android.net.wifi.p2p.WifiP2pManager.Channel;
import android.widget.Toast;
public class WifiReceiver extends BroadcastReceiver {
private WifiP2pManager mManager;
private Channel mChannel;
private MainActivity mActivity;
public WifiReceiver(WifiP2pManager manager, Channel channel, MainActivity activity) {
super();
this.mManager = manager;
this.mChannel = channel;
this.mActivity = activity;
}
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) { // check if wifi is enabled/disabled
System.out.println("Connection changed");
int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1);
if (state == WifiP2pManager.WIFI_P2P_STATE_ENABLED) {
//mActivity.setIsWifiP2pEnabled(true);
} else {
//mActivity.setIsWifiP2pEnabled(false);
}
} else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {
// Call WifiP2pManager.requestPeers() to get a list of current peers
// 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()
System.out.println("Peers changed");
if (mManager != null) {
mManager.requestPeers(mChannel, mActivity);
}
} else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {
// Respond to new connection or disconnections
System.out.println("Connection changed");
} else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) {
// Respond to this device's wifi state changing
System.out.println("This device changed");
}
else if (WifiP2pManager.WIFI_P2P_DISCOVERY_CHANGED_ACTION.equals(action)) {
// Respond to this device's wifi state changing
System.out.println("Search peers");
}
}
}
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/linearlayout1" >
<Button
android:id="@+id/searcher"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/button_send" />
<Button
android:id="@+id/connecter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/button_connect"
android:visibility="invisible" />
<Button
android:id="@+id/disconnecter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/button_disconnect"
android:visibility="invisible" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/linearlayout1" >
<ListView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="380dp"
android:layout_alignParentLeft="true"
android:visibility="invisible" >
</ListView>
</LinearLayout>
"
</RelativeLayout>
I don't understand how works mManager.discoverPeers()
and mManager.requestPeers()
.
Thank you for your attention!!