Example: Android bi-directional network socket using AsyncTask

后端 未结 3 2077
醉酒成梦
醉酒成梦 2020-11-27 11:48

Most of the network socket examples I found for Android were one directional only. I needed a solution for a bi-directional data stream. I eventually learned of the AsyncTas

3条回答
  •  醉话见心
    2020-11-27 12:27

    More interactive example

    Similar to the OP's, but you can control host, port and message + there is a popup error notification if the connection failed.

    Usage 1:

    • get Android and a Linux desktop on a LAN
    • find the IP of the desktop with ifconfig
    • run netcat -l 12345 on a terminal
    • on Android, fill in the IP of the desktop
    • click contact server
    • on the terminal, type the reply, and hit Ctrl + D
    • it appears on the output: section

    Usage 2:

    • hostname google.com
    • port 80
    • Message: "GET / HTTP/1.1\r\nHost: google.com\r\n\r\n"

    Note that some HTTP servers won't close after the reply expecting further requests, and the application will hang until they timeout. Such servers expect you to parse the Content-Width header and close yourself.

    If the connection fails, an alert message is shown to the user on a dialog.

    Code

    Add to AndroidManifest.xml:

    
    

    And the main activity is:

    import android.app.Activity;
    import android.app.AlertDialog;
    import android.app.IntentService;
    import android.content.DialogInterface;
    import android.content.Intent;
    import android.os.AsyncTask;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.LinearLayout;
    import android.widget.ScrollView;
    import android.widget.TextView;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.Socket;
    
    public class Main extends Activity {
        final static String TAG = "AndroidCheatSocket";
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            final LinearLayout linearLayout = new LinearLayout(this);
            linearLayout.setOrientation(LinearLayout.VERTICAL);
            TextView textView;
    
            final String defaultHostname = "192.168.0.";
            textView = new TextView(this);
            textView.setText("hostname / IP:");
            linearLayout.addView(textView);
            final EditText hostnameEditText = new EditText(this);
            hostnameEditText.setText(defaultHostname);
            hostnameEditText.setSingleLine(true);
            linearLayout.addView(hostnameEditText);
    
            textView = new TextView(this);
            textView.setText("port:");
            linearLayout.addView(textView);
            final EditText portEditText = new EditText(this);
            portEditText.setText("12345");
            portEditText.setSingleLine(true);
            linearLayout.addView(portEditText);
    
            textView = new TextView(this);
            textView.setText("data to send:");
            linearLayout.addView(textView);
            final EditText dataEditText = new EditText(this);
            dataEditText.setText(String.format("GET / HTTP/1.1\r\nHost: %s\r\n\r\n", defaultHostname));
            linearLayout.addView(dataEditText);
    
            final TextView replyTextView = new TextView(this);
            final ScrollView replyTextScrollView = new ScrollView(this);
            replyTextScrollView.addView(replyTextView);
    
            final Button button = new Button(this);
            button.setText("contact server");
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    button.setEnabled(false);
                    new MyAsyncTask(Main.this, replyTextView, button).execute(
                            hostnameEditText.getText().toString(),
                            portEditText.getText().toString(),
                            dataEditText.getText().toString());
    
                }
            });
            linearLayout.addView(button);
    
            textView = new TextView(this);
            textView.setText("output:");
            linearLayout.addView(textView);
            linearLayout.addView(replyTextScrollView);
    
            this.setContentView(linearLayout);
        }
    
        private class MyAsyncTask extends AsyncTask {
            Activity activity;
            Button button;
            TextView textView;
            IOException ioException;
            MyAsyncTask(Activity activity, TextView textView, Button button) {
                super();
                this.activity = activity;
                this.textView = textView;
                this.button = button;
                this.ioException = null;
            }
            @Override
            protected String doInBackground(String... params) {
                StringBuilder sb = new StringBuilder();
                try {
                    Socket socket = new Socket(
                            params[0],
                            Integer.parseInt(params[1]));
                    OutputStream out = socket.getOutputStream();
                    out.write(params[2].getBytes());
                    InputStream in = socket.getInputStream();
                    byte buf[] = new byte[1024];
                    int nbytes;
                    while ((nbytes = in.read(buf)) != -1) {
                        sb.append(new String(buf, 0, nbytes));
                    }
                    socket.close();
                } catch(IOException e) {
                    this.ioException = e;
                    return "error";
                }
                return sb.toString();
            }
            @Override
            protected void onPostExecute(String result) {
                if (this.ioException != null) {
                    new AlertDialog.Builder(this.activity)
                        .setTitle("An error occurrsed")
                        .setMessage(this.ioException.toString())
                        .setIcon(android.R.drawable.ic_dialog_alert)
                        .show();
                } else {
                    this.textView.setText(result);
                }
                this.button.setEnabled(true);
            }
        }
    }
    

    On GitHub with build boilerplate.

    I've also posted an Android server example at: https://stackoverflow.com/a/35745834/895245

    Tested on Android 5.1.1, Sony Xperia 3 D6643.

提交回复
热议问题