J'espère que cela vous aidera, je viens de trouver votre solution sur Github. Pour plus de détails et pour le lien officiel, veuillez regardez ça je pense que cela peut vous être utile. Si ce n'est pas la réponse, veuillez ignorer cette réponse.
Nous utilisons AsyncTask pour éviter l'erreur fatale StrictMode pour l'accès au réseau (voir les références). La politique StrictMode nous interdit simplement d'affecter sur le Thread UI.
/* AsyncTask class which manages connection with server app and is sending shutdown command.
*/
public class ShutdownAsyncTask extends AsyncTask<String, String, TCPClient> {
private static final String COMMAND = "shutdown -s" ;
private TCPClient tcpClient ;
private Handler mHandler ;
private static final String TAG = "ShutdownAsyncTask";
/**
* ShutdownAsyncTask constructor with handler passed as argument. The UI is updated via handler.
* In doInBackground(...) method, the handler is passed to TCPClient object.
* @param mHandler Handler object that is retrieved from MainActivity class and passed to TCPClient
* class for sending messages and updating UI.
*/
public ShutdownAsyncTask(Handler mHandler){
this.mHandler = mHandler;
}
/**
* Overriden method from AsyncTask class. There the TCPClient object is created.
* @param params From MainActivity class empty string is passed.
* @return TCPClient object for closing it in onPostExecute method.
*/
@Override
protected TCPClient doInBackground(String... params) {
Log.d(TAG, "In do in background");
try{
tcpClient = new TCPClient(mHandler,
COMMAND,
"192.168.1.1",
new TCPClient.MessageCallback() {
@Override
public void callbackMessageReceiver(String message) {
publishProgress(message);
}
});
}catch (NullPointerException e){
Log.d(TAG, "Caught null pointer exception");
e.printStackTrace();
}
tcpClient.run();
return null;
}
Dans cet AsyncTask, nous créons un objet TCPClient (expliqué ci-dessous). Dans le constructeur de TCPClient, nous passons l'objet Handler pour changer l'interface utilisateur, COMMAND - la chaîne de caractères avec la commande "shutdown -s" pour arrêter l'ordinateur, le numéro IP - le numéro IP des serveurs ; l'objet Callback - lorsque nous obtenons la réponse des serveurs, la méthode de callback 'messageCallbackReceiver' lance la méthode 'publishProgress', qui publie la progression à la méthode de l'AsyncTask 'onProgressUpdate'.
/**
* Overriden method from AsyncTask class. Here we're checking if server answered properly.
* @param values If "restart" message came, the client is stopped and computer should be restarted.
* Otherwise "wrong" message is sent and 'Error' message is shown in UI.
*/
@Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
Log.d(TAG, "In progress update, values: " + values.toString());
if(values[0].equals("shutdown")){
tcpClient.sendMessage(COMMAND);
tcpClient.stopClient();
mHandler.sendEmptyMessageDelayed(MainActivity.SHUTDOWN, 2000);
}else{
tcpClient.sendMessage("wrong");
mHandler.sendEmptyMessageDelayed(MainActivity.ERROR, 2000);
tcpClient.stopClient();
}
}
Après avoir reçu le message approprié, nous envoyons la commande, ou si nous avons reçu un message erroné, nous envoyons le message "erroné" et arrêtons le client. Après cela, nous sommes transférés vers la méthode 'onPostExecute' :
@Override
protected void onPostExecute(TCPClient result){
super.onPostExecute(result);
Log.d(TAG, "In on post execute");
if(result != null && result.isRunning()){
result.stopClient();
}
mHandler.sendEmptyMessageDelayed(MainActivity.SENT, 4000);
}
}
Donc, étape par étape :
->AsyncTask crée l'objet TCPClient.
->Dans le constructeur de TCPClient, nous passons le Handler, la commande, le numéro IP et l'objet Callback.
->Lorsque TCPClient commence la connexion, il envoie le message "shutdown" au serveur.
->Lorsque nous recevons un message du serveur, le callback le transmet à 'onProgressUpdate'.
->Si le message reçu (réponse du serveur) est égal à "shutdown", nous envoyons une COMMANDE au serveur.
->Après l'avoir envoyé, nous arrêtons le client, qui nous transfère à la méthode "onPostExecute".
->Pendant ce temps, le gestionnaire reçoit des messages vides avec des entiers 'msg.what' définis dans MainActivity, qui sont responsables de la mise à jour de l'interface graphique.
Exemple de mise à jour de l'interface utilisateur du widget :
mHandler = new Handler(){
public void handleMessage(Message msg) {
switch(msg.what){
case SHUTDOWN:
Log.d(mTag, "In Handler's shutdown");
views = new RemoteViews(context.getPackageName(), R.layout.activity_main);
widget = new ComponentName(context, MainActivity.class);
awManager = AppWidgetManager.getInstance(context);
views.setTextViewText(R.id.state, "Shutting PC...");
awManager.updateAppWidget(widget,views);
break;
TCPClient
Cette classe est responsable du maintien de la connexion. Je vais l'expliquer étape par étape :
Dans la première étape, nous pouvons voir les objets passés par ShutdownAsyncTask et autres. De plus, nous pouvons voir les méthodes sendMessage et stopClient.
public class TCPClient {
private static final String TAG = "TCPClient" ;
private final Handler mHandler ;
private String ipNumber, incomingMessage, command;
BufferedReader in ;
PrintWriter out ;
private MessageCallback listener = null ;
private boolean mRun = false ;
/**
* TCPClient class constructor, which is created in AsyncTasks after the button click.
* @param mHandler Handler passed as an argument for updating the UI with sent messages
* @param command Command passed as an argument, e.g. "shutdown -r" for restarting computer
* @param ipNumber String retrieved from IpGetter class that is looking for ip number.
* @param listener Callback interface object
*/
public TCPClient(Handler mHandler, String command, String ipNumber, MessageCallback listener) {
this.listener = listener;
this.ipNumber = ipNumber;
this.command = command ;
this.mHandler = mHandler;
}
/**
* Public method for sending the message via OutputStream object.
* @param message Message passed as an argument and sent via OutputStream object.
*/
public void sendMessage(String message){
if (out != null && !out.checkError()) {
out.println(message);
out.flush();
mHandler.sendEmptyMessageDelayed(MainActivity.SENDING, 1000);
Log.d(TAG, "Sent Message: " + message);
}
}
/**
* Public method for stopping the TCPClient object ( and finalizing it after that ) from AsyncTask
*/
public void stopClient(){
Log.d(TAG, "Client stopped!");
mRun = false;
}
La magie se produit ici - dans la méthode "run()". Ici, nous utilisons les outils "try-catch" pour gérer les exceptions (serveur non activé, adresse IP non appropriée, etc.). Comme vous pouvez le voir ci-dessous, nous avons une boucle infinie while() pour écouter les messages entrants. Nous pouvons simplement l'arrêter et finaliser avec la méthode 'stopClient()' (utilisée dans la méthode 'onProgressUpdate' de ShutdownAsyncTask).
public void run() {
mRun = true;
try {
// Creating InetAddress object from ipNumber passed via constructor from IpGetter class.
InetAddress serverAddress = InetAddress.getByName(ipNumber);
Log.d(TAG, "Connecting...");
/**
* Sending empty message with static int value from MainActivity
* to update UI ( 'Connecting...' ).
*
* @see com.example.turnmeoff.MainActivity.CONNECTING
*/
mHandler.sendEmptyMessageDelayed(MainActivity.CONNECTING,1000);
/**
* Here the socket is created with hardcoded port.
* Also the port is given in IpGetter class.
*
* @see com.example.turnmeoff.IpGetter
*/
Socket socket = new Socket(serverAddress, 4444);
try {
// Create PrintWriter object for sending messages to server.
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
//Create BufferedReader object for receiving messages from server.
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
Log.d(TAG, "In/Out created");
//Sending message with command specified by AsyncTask
this.sendMessage(command);
//
mHandler.sendEmptyMessageDelayed(MainActivity.SENDING,2000);
//Listen for the incoming messages while mRun = true
while (mRun) {
incomingMessage = in.readLine();
if (incomingMessage != null && listener != null) {
/**
* Incoming message is passed to MessageCallback object.
* Next it is retrieved by AsyncTask and passed to onPublishProgress method.
*
*/
listener.callbackMessageReceiver(incomingMessage);
}
incomingMessage = null;
}
Log.d(TAG, "Received Message: " +incomingMessage);
} catch (Exception e) {
Log.d(TAG, "Error", e);
mHandler.sendEmptyMessageDelayed(MainActivity.ERROR, 2000);
} finally {
out.flush();
out.close();
in.close();
socket.close();
mHandler.sendEmptyMessageDelayed(MainActivity.SENT, 3000);
Log.d(TAG, "Socket Closed");
}
} catch (Exception e) {
Log.d(TAG, "Error", e);
mHandler.sendEmptyMessageDelayed(MainActivity.ERROR, 2000);
}
}
Le dernier élément du client est l'interface Callback. Nous l'avons dans la classe TCPClient à la fin :
/**
* Callback Interface for sending received messages to 'onPublishProgress' method in AsyncTask.
*
*/
public interface MessageCallback {
/**
* Method overriden in AsyncTask 'doInBackground' method while creating the TCPClient object.
* @param message Received message from server app.
*/
public void callbackMessageReceiver(String message);
}