J'ai une application dans laquelle j'ai besoin de créer une connexion socket. Mon exigence est la suivante: une fois ma connexion de socket établie, elle doit être active jusqu'à ce que je la ferme personnellement. Et toutes les 3 minutes, je dois envoyer des paquets de données à l’autre bout. Quelqu'un peut-il me fournir des exemples de code qui m'aideront à le faire?
Les connexions de socket dans Android sont identiques à celles de Java: http://www.Oracle.com/technetwork/Java/socket-140484.html
Les choses que vous devez savoir:
Jetez un coup d'œil à AlarmManager
, si vous avez besoin d'une exécution programmée de votre code.
Devez-vous exécuter votre code et recevoir des données même si l’utilisateur n’utilise plus l’application (c’est-à-dire que l’application est inactive)?
Ici, dans cet article, vous trouverez le code détaillé permettant d’établir une connexion entre des appareils ou entre deux applications d’un même mobile.
Vous devez créer deux applications pour tester le code ci-dessous.
Dans les deux applications fichier manifeste, ajoutez l'autorisation ci-dessous.
<uses-permission Android:name="Android.permission.INTERNET" />
1er code de l'application: socket client
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="match_parent">
<TableRow
Android:id="@+id/tr_send_message"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:gravity="center"
Android:layout_alignParentLeft="true"
Android:layout_alignParentStart="true"
Android:layout_alignParentTop="true"
Android:layout_marginTop="11dp">
<EditText
Android:id="@+id/edt_send_message"
Android:layout_width="0dp"
Android:layout_height="wrap_content"
Android:layout_weight="1"
Android:layout_marginRight="10dp"
Android:layout_marginLeft="10dp"
Android:hint="Enter message"
Android:inputType="text" />
<Button
Android:id="@+id/btn_send"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_marginRight="10dp"
Android:text="Send" />
</TableRow>
<ScrollView
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:layout_alignParentLeft="true"
Android:layout_alignParentStart="true"
Android:layout_below="@+id/tr_send_message"
Android:layout_marginTop="25dp"
Android:id="@+id/scrollView2">
<TextView
Android:id="@+id/tv_reply_from_server"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:orientation="vertical" />
</ScrollView>
</RelativeLayout>
MainActivity.Java
import Android.os.Bundle;
import Android.os.Handler;
import Android.support.v7.app.AppCompatActivity;
import Android.view.View;
import Android.widget.Button;
import Android.widget.EditText;
import Android.widget.TextView;
import Java.io.BufferedReader;
import Java.io.IOException;
import Java.io.InputStreamReader;
import Java.io.OutputStream;
import Java.io.PrintWriter;
import Java.net.Socket;
/**
* Created by Girish Bhalerao on 5/4/2017.
*/
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private TextView mTextViewReplyFromServer;
private EditText mEditTextSendMessage;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button buttonSend = (Button) findViewById(R.id.btn_send);
mEditTextSendMessage = (EditText) findViewById(R.id.edt_send_message);
mTextViewReplyFromServer = (TextView) findViewById(R.id.tv_reply_from_server);
buttonSend.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_send:
sendMessage(mEditTextSendMessage.getText().toString());
break;
}
}
private void sendMessage(final String msg) {
final Handler handler = new Handler();
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
//Replace below IP with the IP of that device in which server socket open.
//If you change port then change the port number in the server side code also.
Socket s = new Socket("xxx.xxx.xxx.xxx", 9002);
OutputStream out = s.getOutputStream();
PrintWriter output = new PrintWriter(out);
output.println(msg);
output.flush();
BufferedReader input = new BufferedReader(new InputStreamReader(s.getInputStream()));
final String st = input.readLine();
handler.post(new Runnable() {
@Override
public void run() {
String s = mTextViewReplyFromServer.getText().toString();
if (st.trim().length() != 0)
mTextViewReplyFromServer.setText(s + "\nFrom Server : " + st);
}
});
output.close();
out.close();
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
thread.start();
}
}
2nd App Code - Server Socket
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="match_parent">
<Button
Android:id="@+id/btn_stop_receiving"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:text="STOP Receiving data"
Android:layout_alignParentTop="true"
Android:enabled="false"
Android:layout_centerHorizontal="true"
Android:layout_marginTop="89dp" />
<ScrollView
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:layout_below="@+id/btn_stop_receiving"
Android:layout_marginTop="35dp"
Android:layout_alignParentLeft="true"
Android:layout_alignParentStart="true">
<TextView
Android:id="@+id/tv_data_from_client"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:orientation="vertical" />
</ScrollView>
<Button
Android:id="@+id/btn_start_receiving"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:text="START Receiving data"
Android:layout_alignParentTop="true"
Android:layout_centerHorizontal="true"
Android:layout_marginTop="14dp" />
</RelativeLayout>
MainActivity.Java
import Android.os.Bundle;
import Android.os.Handler;
import Android.support.v7.app.AppCompatActivity;
import Android.view.View;
import Android.widget.Button;
import Android.widget.TextView;
import Java.io.BufferedReader;
import Java.io.IOException;
import Java.io.InputStreamReader;
import Java.io.PrintWriter;
import Java.net.ServerSocket;
import Java.net.Socket;
/**
* Created by Girish Bhalerao on 5/4/2017.
*/
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
final Handler handler = new Handler();
private Button buttonStartReceiving;
private Button buttonStopReceiving;
private TextView textViewDataFromClient;
private boolean end = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
buttonStartReceiving = (Button) findViewById(R.id.btn_start_receiving);
buttonStopReceiving = (Button) findViewById(R.id.btn_stop_receiving);
textViewDataFromClient = (TextView) findViewById(R.id.tv_data_from_client);
buttonStartReceiving.setOnClickListener(this);
buttonStopReceiving.setOnClickListener(this);
}
private void startServerSocket() {
Thread thread = new Thread(new Runnable() {
private String stringData = null;
@Override
public void run() {
try {
ServerSocket ss = new ServerSocket(9002);
while (!end) {
//Server is waiting for client here, if needed
Socket s = ss.accept();
BufferedReader input = new BufferedReader(new InputStreamReader(s.getInputStream()));
PrintWriter output = new PrintWriter(s.getOutputStream());
stringData = input.readLine();
output.println("FROM SERVER - " + stringData.toUpperCase());
output.flush();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
updateUI(stringData);
if (stringData.equalsIgnoreCase("STOP")) {
end = true;
output.close();
s.close();
break;
}
output.close();
s.close();
}
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
thread.start();
}
private void updateUI(final String stringData) {
handler.post(new Runnable() {
@Override
public void run() {
String s = textViewDataFromClient.getText().toString();
if (stringData.trim().length() != 0)
textViewDataFromClient.setText(s + "\n" + "From Client : " + stringData);
}
});
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_start_receiving:
startServerSocket();
buttonStartReceiving.setEnabled(false);
buttonStopReceiving.setEnabled(true);
break;
case R.id.btn_stop_receiving:
//stopping server socket logic you can add yourself
buttonStartReceiving.setEnabled(true);
buttonStopReceiving.setEnabled(false);
break;
}
}
}
Exemple d'application de serveur de socket simple
J'ai déjà posté un exemple de client à l'adresse suivante: https://stackoverflow.com/a/35971718/895245 , voici donc un exemple de serveur.
Cet exemple d'application exécute un serveur qui renvoie un chiffrement ROT-1 de l'entrée.
Vous devrez ensuite ajouter un bouton Exit
ainsi que des délais d'attente, mais cela devrait vous aider à démarrer.
Pour jouer avec:
netcat $PHONE_IP 12345
Les sockets Android sont les mêmes que ceux de Java, sauf que nous avons des problèmes d'autorisation.
src/com/cirosantilli/Android_cheat/socket/Main.Java
package com.cirosantilli.Android_cheat.socket;
import Android.app.Activity;
import Android.app.IntentService;
import Android.content.Intent;
import Android.os.Bundle;
import Android.util.Log;
import Java.io.BufferedReader;
import Java.io.IOException;
import Java.io.InputStreamReader;
import Java.io.PrintStream;
import Java.net.ServerSocket;
import Java.net.Socket;
public class Main extends Activity {
static final String TAG = "AndroidCheatSocket";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(Main.TAG, "onCreate");
Main.this.startService(new Intent(Main.this, MyService.class));
}
public static class MyService extends IntentService {
public MyService() {
super("MyService");
}
@Override
protected void onHandleIntent(Intent intent) {
Log.d(Main.TAG, "onHandleIntent");
final int port = 12345;
ServerSocket listener = null;
try {
listener = new ServerSocket(port);
Log.d(Main.TAG, String.format("listening on port = %d", port));
while (true) {
Log.d(Main.TAG, "waiting for client");
Socket socket = listener.accept();
Log.d(Main.TAG, String.format("client connected from: %s", socket.getRemoteSocketAddress().toString()));
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintStream out = new PrintStream(socket.getOutputStream());
for (String inputLine; (inputLine = in.readLine()) != null;) {
Log.d(Main.TAG, "received");
Log.d(Main.TAG, inputLine);
StringBuilder outputStringBuilder = new StringBuilder("");
char inputLineChars[] = inputLine.toCharArray();
for (char c : inputLineChars)
outputStringBuilder.append(Character.toChars(c + 1));
out.println(outputStringBuilder);
}
}
} catch(IOException e) {
Log.d(Main.TAG, e.toString());
}
}
}
}
Nous avons besoin de Service
ou d’une autre méthode d’arrière-plan, sinon: Comment puis-je réparer Android.os.NetworkOnMainThreadException?
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:Android="http://schemas.Android.com/apk/res/Android"
package="com.cirosantilli.Android_cheat.socket"
Android:versionCode="1"
Android:versionName="1.0">
<uses-sdk Android:minSdkVersion="22" />
<uses-permission Android:name="Android.permission.INTERNET" />
<application Android:label="AndroidCheatsocket">
<activity Android:name="Main">
<intent-filter>
<action Android:name="Android.intent.action.MAIN" />
<category Android:name="Android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service Android:name=".Main$MyService" />
</application>
</manifest>
Il faut ajouter: <uses-permission Android:name="Android.permission.INTERNET" />
ou sinon: exception Java socket IOException - permission refusée
Sur GitHub avec un build.xml
: https://github.com/cirosantilli/Android-cheat/tree/92de020d0b708549a444ebd9f881de7b240b3fbc/socket