Wifi P2P Android
Introduction
- L'API Level 14 introduit des fonctionnalités pour gérer des connexions Wifi entre appareils
- Il est possible de découvrir des appareils et d'établir des communications rapides
- Le principale avantage est l'absence de connexion à un réseau Wifi pour joindre des appareils
- Classe WifiP2pManager pour découvrir et se connecter à des apparei
- Des auditeurs d'événements permettent de traiter les opérations réalisées avec le manager
- Différentes intentions permettent d'identifier les événements
API Overview (1/2)
Méthodes du manager Wifi : classe WifiP2pManager
| Méthode | Description |
|---|---|
| initialize() | Première méthode à appeler pour utiliser le manager |
| connect() | Démarre la connexion à un appareil |
| cancelConnect() | Annule la connexion à un appareil |
| requestConnectInfo() | Requête d'information de l'appareil connecté |
| createGroup() | Créer un groupe (l'appareil devient le propriétaire) |
| removeGroup() | Supprime le groupe |
| requestGroupInfo() | Requête d'information d'un groupe |
| discoverPeers() | Scanne les appareils joignable en Wifi |
| requestPeers() | Requête de liste des appareils joignable en Wifi |
API Overview (2/2)
Auditeurs d'événements acceptés en paramètre
| Intention | Description |
|---|---|
| WIFI_P2P_CONNECTION_CHANGED_ACTION | Diffusée lorsque l'état d'une connexion d'un appareil change |
| WIFI_P2P_PEERS_CHANGED_ACTION | Diffusé lors de l'appel de discoverPeers() |
| WIFI_P2P_STATE_CHANGED_ACTION | Diffusé lorsque le Wifi P2P est activité ou désactivé |
| WIFI_P2P_THIS_DEVICE_CHANGED_ACTION | Diffusé lorsqu'une information de l'appareil change (comme le nom de l'appareil) |
Intentions diffusées par le manager
Broadcast Receiver
- Un broadcast receiver permet d'écouter des événements systèmes liées au Wifi
- Etendre la classe BroadcastReceiver et son constructeur
- L'instance du manager WifiP2pManager à utiliser et l'instance WifiP2pManager.Channel récupérée à l'initialisation du manager
- L'activité utilisant le broadcast receiver
public class WiFiDirectBroadcastReceiver extends BroadcastReceiver {
private WifiP2pManager mManager;
private Channel mChannel;
private MyWiFiActivity mActivity;
public WiFiDirectBroadcastReceiver(WifiP2pManager manager, Channel channel,
MyWifiActivity 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 to see if Wi-Fi is enabled and notify appropriate activity
int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1);
if (state == WifiP2pManager.WIFI_P2P_STATE_ENABLED) {
// Wifi P2P is enabled
} else {
// Wi-Fi P2P is not enabled
}
} else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {
// Call WifiP2pManager.requestPeers() to get a list of current peers
} else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {
// Respond to new connection or disconnections
} else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) {
// Respond to this device's wifi state changing
}
}
}Initialisation
- Indiquer la version 14 et les permissions nécessaires dans le manifeste
<uses-sdk android:minSdkVersion="14" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />- Initialiser le framework Wifi P2P
WifiP2pManager mManager;
Channel mChannel;
BroadcastReceiver mReceiver;
IntentFilter mIntentFilter;
@Override
protected void onCreate(Bundle savedInstanceState) {
// . . .
mManager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
mChannel = mManager.initialize(this, getMainLooper(), null);
mReceiver = new WiFiDirectBroadcastReceiver(mManager, mChannel, this);
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);
// . . .
}
/* register the broadcast receiver with the intent values to be matched */
@Override
protected void onResume() {
super.onResume();
registerReceiver(mReceiver, mIntentFilter);
}
/* unregister the broadcast receiver */
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(mReceiver);
}Découvrir des appareils
- Utiliser la méthode discoverPeers() pour lancer la détection d'appareils
- Le second paramètre WifiP2pManager.ActionListener est utilisé pour notifier le succès ou l'échec
- Le broadcast receiver est notifié en cas de succès
mManager.discoverPeers(channel, new WifiP2pManager.ActionListener() {
@Override
public void onSuccess() {
// TODO
}
@Override
public void onFailure(int reasonCode) {
// TODO
}
});
public class WiFiDirectBroadcastReceiver extends BroadcastReceiver {
// . . .
PeerListListener myPeerListListener;
@Override
public void onReceive(Context context, Intent intent) {
// . . .
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 (mManager != null) {
mManager.requestPeers(mChannel, myPeerListListener);
}
}
}
}Connexion avec un appareil
- Utiliser une instance WifiP2pConfig contenant les informations d'un appareil
- Utiliser l'instance WifiP2pDeviceList pour récupérer la config d'un appareil avec le PeerListListener
//obtain a peer from the WifiP2pDeviceList
WifiP2pDevice device;
WifiP2pConfig config = new WifiP2pConfig();
config.deviceAddress = device.deviceAddress;
mManager.connect(mChannel, config, new ActionListener() {
@Override
public void onSuccess() {
//success logic
}
@Override
public void onFailure(int reason) {
//failure logic
}
});
Transfert de données
- Des données peuvent être échangées une fois la connexion avec un appareil établie
-
Procédure standard
- Créer un serveur ServerSocket et attendre la connexion du client
- Côté client, créer un client Socket avec l'adresse IP et le port du serveur
- Le client envoi les données via des flux de bits
- Le serveur accepte les connexions des clients avec accept()
- Démonstration : WiFiDirectDemo et WiFiDirectServiceDiscovery
public static class FileServerAsyncTask extends AsyncTask {
private Context context;
private TextView statusText;
public FileServerAsyncTask(Context context, View statusText) {
this.context = context;
this.statusText = (TextView) statusText;
}
@Override
protected String doInBackground(Void... params) {
try {
/** Create a server socket and wait for client connections. This
* call blocks until a connection is accepted from a client */
ServerSocket serverSocket = new ServerSocket(8888);
Socket client = serverSocket.accept();
/** If this code is reached, a client has connected and transferred data
* Save the input stream from the client as a JPEG file */
final File f = new File(Environment.getExternalStorageDirectory() + "/"
+ context.getPackageName() + "/wifip2pshared-" + System.currentTimeMillis()
+ ".jpg");
File dirs = new File(f.getParent());
if (!dirs.exists())
dirs.mkdirs();
f.createNewFile();
InputStream inputstream = client.getInputStream();
copyFile(inputstream, new FileOutputStream(f));
serverSocket.close();
return f.getAbsolutePath();
} catch (IOException e) {
Log.e(WiFiDirectActivity.TAG, e.getMessage());
return null;
}
}
/** Start activity that can handle the JPEG image */
@Override
protected void onPostExecute(String result) {
if (result != null) {
statusText.setText("File copied - " + result);
Intent intent = new Intent();
intent.setAction(android.content.Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse("file://" + result), "image/*");
context.startActivity(intent);
}
}
}
Context context = this.getApplicationContext();
String host;
int port;
int len;
Socket socket = new Socket();
byte buf[] = new byte[1024];
...
try {
/**
* Create a client socket with the host,
* port, and timeout information.
*/
socket.bind(null);
socket.connect((new InetSocketAddress(host, port)), 500);
/**
* Create a byte stream from a JPEG file and pipe it to the output stream
* of the socket. This data will be retrieved by the server device.
*/
OutputStream outputStream = socket.getOutputStream();
ContentResolver cr = context.getContentResolver();
InputStream inputStream = null;
inputStream = cr.openInputStream(Uri.parse("path/to/picture.jpg"));
while ((len = inputStream.read(buf)) != -1) {
outputStream.write(buf, 0, len);
}
outputStream.close();
inputStream.close();
} catch (FileNotFoundException e) {
//catch logic
} catch (IOException e) {
//catch logic
}
/**
* Clean up any open sockets when done
* transferring or if an exception occurred.
*/
finally {
if (socket != null) {
if (socket.isConnected()) {
try {
socket.close();
} catch (IOException e) {
//catch logic
}
}
}
}Wifi P2P Android
By Steven Enten
Wifi P2P Android
- 1,634