como criar conexão de Socket no Android?

Tenho uma aplicação onde preciso de criar uma ligação de 'socket'. A minha exigência é que, assim que a minha ligação for estabelecida, tem de estar viva até eu a fechar pessoalmente. A cada 3 minutos tenho que enviar pacotes de dados para a outra extremidade. Alguém me pode dar uma amostra de código que me ajude a fazer isto?

Author: npanigrahy, 2011-09-12

3 answers

As ligações do 'Socket' no Android são as mesmas que no Java: http://www.oracle.com/technetwork/java/socket-140484.html

Coisas que precisas de saber:

  1. Se o telemóvel adormecer, a aplicação deixará de ser executada, por isso o 'socket' acabará por perder tempo. Pode evitar isto com wake lock. Isto vai comer a bateria de dispositivos tremendamente - eu sei que eu não usaria essa aplicação.
  2. Se fizer isto constantemente, mesmo quando a sua aplicação não estiver activa, então terá de usar Servico.
  3. As actividades e os Serviços podem ser eliminados pelo sistema operacional a qualquer momento, especialmente se fizerem parte de uma aplicação inactiva.

Dê uma olhada em {[[0]}, se precisar de execução programada do seu código.

Precisa de executar o seu código e receber dados, mesmo que o utilizador já não utilize a aplicação (ou seja, a aplicação está inactiva)?

 48
Author: Peter Knego, 2013-01-22 06:34:10

Aqui, neste post você vai encontrar o código detalhado para estabelecer o socket entre dispositivos ou entre duas aplicações no mesmo móvel.

Você tem que criar duas aplicações para testar abaixo do Código.

Em ambos os ficheiros de manifesto da aplicação , adicione abaixo a permissão

<uses-permission android:name="android.permission.INTERNET" />

1. o código da aplicação: 'Socket' do cliente

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();
    }
}

2 'Socket' Do Servidor De Código Da Aplicação

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;
        }
    }
}
 12
Author: Girish Bhalerao, 2017-05-04 09:51:39

Exemplo simples de aplicação do servidor de 'socket'

Já publiquei um exemplo de cliente em: https://stackoverflow.com/a/35971718/895245 então aqui vai um exemplo do servidor.

Este aplicativo de exemplo executa um servidor que devolve um cypher ROT-1 da entrada.

Teria então de adicionar um botão {[[2]} + alguns atrasos de sono, mas isto deve dar-lhe início.

Para brincar com ele:

Os soquetes Android são iguais aos de Java, só que temos de lidar com problemas de permissão.

Src/com / cirosantilli/android_cheat/socket

Precisamos de um Service ou outro método de fundo ou então: Como corrigir androide.o.A rede sobre a maior parte já está à vista?

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());
            }
        }
    }
}

AndroidManifest.xml

Deve adicionar: <uses-permission android:name="android.permission.INTERNET" /> ou então: Java socket IOException - permissão negada

<?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>

No GitHub com um build.xml: https://github.com/cirosantilli/android-cheat/tree/92de020d0b708549a444ebd9f881de7b240b3fbc/socket