cordova 插件 TCPSockets NetworkOnMainThreadException

cordova plugin TCPSockets NetworkOnMainThreadException

我正在尝试让 Habel 提供的 TCPSockets 插件与 Cordova 5.0 一起使用。这个插件可以找到 here。我可以安装该插件,但是当我使用它时出现异常 "android.on.NetworkOnMainThreadException"。我研究了这个错误,似乎有多种解决方法。创建新线程或使用 AsyncTask 的任何内容。我不太确定如何在现有 java 代码中实现它,希望有人能帮助解释。我也在 IOS 中将此插件用于同一应用程序,因此该解决方案需要支持 android 和 IOS。有人可以帮助我吗?

    package com.habel.sockets;

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.PrintWriter;

    import javax.net.ssl.SSLContext;
    import javax.net.ssl.SSLSession;
    import javax.net.ssl.SSLSocket;
    import javax.net.ssl.SSLSocketFactory;
    import java.net.Socket;
    import java.net.UnknownHostException;
    import javax.net.ssl.TrustManager;
    import javax.net.ssl.X509TrustManager;

    import java.security.KeyManagementException;
    import java.security.NoSuchAlgorithmException;
    import java.security.SecureRandom;
    import java.security.cert.X509Certificate;

    import org.json.JSONArray;
    import org.json.JSONException;

    import android.util.Log;

    import org.apache.cordova.CordovaPlugin;
    import org.apache.cordova.PluginResult;
    import org.apache.cordova.CallbackContext;

    public class TCPSockets extends CordovaPlugin { 
        public boolean execute(String action, JSONArray args, CallbackContext callbackContext) {
            PluginResult r = new PluginResult(PluginResult.Status.NO_RESULT);

    //      Log.d("TCPSockets", "Plugin Called");
            try {
                if (action.equals("sendMessage")) {

                    if (args != null) 
                    {
                        int port  = args.getInt(0);
                        String host = args.getString(1);
                        String message = args.getString(2);
                        int connectionTimeout = args.getInt(3);
                        boolean secureConnection = args.getBoolean(4);

                        r = sendMessage(port, host, message, connectionTimeout, secureConnection);
                        r.setKeepCallback(true);
                    } else {
    //                    return new PluginResult(PluginResult.Status.ERROR, "User did not specify host information");
                        callbackContext.error("User did not specify host information");
                        return true;
                    }
                } else {
    //                return new PluginResult(PluginResult.Status.INVALID_ACTION);
                    callbackContext.error("Invalid Action");
                    return true;
                }
            } 

            catch (JSONException e) {
                Log.d("TCPSockets", "JSONException: " + e.getMessage());
    //          return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
                callbackContext.error("JSON Exception");
                return true;
            }

    //        return r;
            callbackContext.sendPluginResult(r);
            return true;
        }

        public PluginResult sendMessage(int port, String host, String message, int connectionTimeout, boolean secureConnection)
        {
            String reply = "";

            try {           
                // If we don't want secure connections, then use Socket class
                if(!secureConnection)
                {
                    // Not SSL socket
                    Socket sock = new Socket(host, port);
                    Log.d("TCPSockets", "Socket created");
                    sock.setSoTimeout(connectionTimeout); // Time out all actions for 30 seconds

                    PrintWriter out = new PrintWriter(sock.getOutputStream(), true);
                    BufferedReader in = new BufferedReader(new InputStreamReader(sock.getInputStream()));

                    Log.d("TCPSockets", "Created reader/writer");
                    out.println(message);
                    Log.d("TCPSockets", "Sent message");

                    reply = in.readLine();
                    Log.d("TCPSockets", "Received message: " + reply);

                    out.flush();

                    out.close();
                    in.close();
                    sock.close();
                }
                else // If we want secure connections, then use SSLSocket class
                {               
                    // Create a trust manager that does not validate certificate chains
                    TrustManager[] trustAllCerts = new TrustManager[] {
                        new X509TrustManager() {
                            public X509Certificate[] getAcceptedIssuers() {
                                return null;
                            }

                            public void checkClientTrusted(X509Certificate[] certs, String authType) {
                                // Trust always
                            }

                            public void checkServerTrusted(X509Certificate[] certs, String authType) {
                                // Trust always
                            }
                        }
                    };

                    SSLContext sslContext;

                    try {
                        sslContext = SSLContext.getInstance("SSL");
                    } catch (NoSuchAlgorithmException e) {
                        Log.d("SSLTCPSockets", "No such algorithm");
                        return new PluginResult(PluginResult.Status.IO_EXCEPTION, "Cannot connect to server. Please, try again");
                    }

                    try {
                        sslContext.init(null, trustAllCerts, new SecureRandom());
                    } catch (KeyManagementException e) {
                        Log.d("SSLTCPSockets", "Key manager exception");
                        return new PluginResult(PluginResult.Status.IO_EXCEPTION, "Cannot connect to server. Please, try again");
                    }

                    SSLSocketFactory socketFactory = sslContext.getSocketFactory();
                    SSLSocket socket = (SSLSocket)socketFactory.createSocket(host, port);
                    socket.setSoTimeout(connectionTimeout);
                    socket.setUseClientMode(true);

                    Log.d("SSLTCPSockets", "Connected to status host");

                    SSLSession session = socket.getSession();

                    if (session.isValid())
                    {
                        Log.i(getClass().toString(), "Secure connection");
                        PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
                        BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

                        out.println(message);
                        Log.d("SSLTCPSockets", "Sent message");

                        reply = in.readLine();
                        Log.d("SSLTCPSockets", "Received message: " + reply);

                        out.flush();

                        out.close();
                        in.close();
                    }
                    else
                    {
                        Log.d("SSLTCPSockets", "Cannot create a secure connection");
                        return new PluginResult(PluginResult.Status.IO_EXCEPTION, "Cannot connect to server. Please, try again");
                    }

                    socket.close();
                }

                return new PluginResult(PluginResult.Status.OK, reply);
            } 

            catch (UnknownHostException e) {
                Log.d("TCPSockets", "Unknown Host");
                return new PluginResult(PluginResult.Status.IO_EXCEPTION, "Cannot connect to server. Please, try again");
            } 

            catch (java.net.SocketTimeoutException e) {
                Log.d("TCPSockets", "Connection timed out");
                return new PluginResult(PluginResult.Status.IO_EXCEPTION, "Connection timed out. Please, try again");
            }

            catch (IOException e) {
                Log.d("TCPSockets", "IOException");
                return new PluginResult(PluginResult.Status.IO_EXCEPTION, "Unexpected error. Please, try again");
            } 
        }
    }

以下代码解决了这个问题。希望它能帮助需要 secure/non-secure 在最新的 cordova 上建立 TCP 连接的其他人。

        public class TCPSockets extends CordovaPlugin { 
        @Override
        public boolean execute(String action, JSONArray args, final CallbackContext callbackContext) {      
    //      PluginResult result = new PluginResult(PluginResult.Status.NO_RESULT);
            final String callbackId = callbackContext.getCallbackId();      

    //      Log.d("TCPSockets", "Plugin Called");
            try {
                if (action.equals("sendMessage")) {

                    if (args != null) 
                    {
                        final int port  = args.getInt(0);
                        final String host = args.getString(1);
                        final String message = args.getString(2);
                        final int connectionTimeout = args.getInt(3);
                        final boolean secureConnection = args.getBoolean(4);

                        cordova.getThreadPool().execute(new Runnable() {
                            public void run() {
                                callbackContext.sendPluginResult(sendMessage(port, host, message, connectionTimeout, secureConnection));                            
                            }
                        });                                                                     
                    } else {
    //                    return new PluginResult(PluginResult.Status.ERROR, "User did not specify host information");
                        callbackContext.error("User did not specify host information");
                        return true;
                    }
                } else {
    //                return new PluginResult(PluginResult.Status.INVALID_ACTION);
                    callbackContext.error("Invalid Action");
                    return true;
                }
            } 

            catch (JSONException e) {
                Log.d("TCPSockets", "JSONException: " + e.getMessage());
    //          return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
                callbackContext.error("JSON Exception");
                return true;
            }

    //        return r;
    //      callbackContext.sendPluginResult(r);
            return true;
        }

        public PluginResult sendMessage(int port, String host, String message, int connectionTimeout, boolean secureConnection)
        {
            String reply = "";
            PluginResult result = new PluginResult(PluginResult.Status.NO_RESULT);

            try {           
                // If we don't want secure connections, then use Socket class
                if(!secureConnection)
                {
                    // Not SSL socket
                    Socket sock = new Socket(host, port);
                    Log.d("TCPSockets", "Socket created");
                    sock.setSoTimeout(connectionTimeout); // Time out all actions for 30 seconds

                    PrintWriter out = new PrintWriter(sock.getOutputStream(), true);
                    BufferedReader in = new BufferedReader(new InputStreamReader(sock.getInputStream()));

                    Log.d("TCPSockets", "Created reader/writer");
                    out.println(message);
                    Log.d("TCPSockets", "Sent message");

                    reply = in.readLine();
                    Log.d("TCPSockets", "Received message: " + reply);

                    out.flush();

                    out.close();
                    in.close();
                    sock.close();
                }
                else // If we want secure connections, then use SSLSocket class
                {               
                    // Create a trust manager that does not validate certificate chains
                    TrustManager[] trustAllCerts = new TrustManager[] {
                        new X509TrustManager() {
                            public X509Certificate[] getAcceptedIssuers() {
                                return null;                                    
                            }

                            public void checkClientTrusted(X509Certificate[] certs, String authType) {
                                // Trust always
                            }

                            public void checkServerTrusted(X509Certificate[] certs, String authType) {
                                // Trust always
                            }
                        }
                    };

                    SSLContext sslContext = null;

                    try {
                        sslContext = SSLContext.getInstance("SSL");
                    } catch (NoSuchAlgorithmException e) {
                        Log.d("SSLTCPSockets", "No such algorithm");
    //                          return new PluginResult(PluginResult.Status.IO_EXCEPTION, "Cannot connect to server. Please, try again");
                        result = new PluginResult(PluginResult.Status.IO_EXCEPTION, "Cannot connect to server. Please, try again");                 
                        return result;
                    }

                    try {
                        sslContext.init(null, trustAllCerts, new SecureRandom());
                    } catch (KeyManagementException e) {
                        Log.d("SSLTCPSockets", "Key manager exception");
    //                          return new PluginResult(PluginResult.Status.IO_EXCEPTION, "Cannot connect to server. Please, try again");
                        result = new PluginResult(PluginResult.Status.IO_EXCEPTION, "Cannot connect to server. Please, try again");
                        return result;
                    }

                    SSLSocketFactory socketFactory = sslContext.getSocketFactory();
                    SSLSocket socket = (SSLSocket)socketFactory.createSocket(host, port);
                    socket.setSoTimeout(connectionTimeout);
                    socket.setUseClientMode(true);

                    Log.d("SSLTCPSockets", "Connected to host");

                    SSLSession session = socket.getSession();

                    if (session.isValid())
                    {
                        Log.i(getClass().toString(), "Secure connection");
                        PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
                        BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

                        out.println(message);
                        Log.d("SSLTCPSockets", "Sent message");

                        reply = in.readLine();
                        Log.d("SSLTCPSockets", "Received message: " + reply);

                        out.flush();

                        out.close();
                        in.close();
                    }
                    else
                    {
                        Log.d("SSLTCPSockets", "Cannot create a secure connection");
    //                          return new PluginResult(PluginResult.Status.IO_EXCEPTION, "Cannot connect to server. Please, try again");
                        result = new PluginResult(PluginResult.Status.IO_EXCEPTION, "Cannot connect to server. Please, try again");
                        return result;
                    }

                    socket.close();
                }

                result = new PluginResult(PluginResult.Status.OK, reply);
                result.setKeepCallback(true);
                return result;                  
            } 

            catch (UnknownHostException e) {
                Log.d("TCPSockets", "Unknown Host");
    //                  return new PluginResult(PluginResult.Status.IO_EXCEPTION, "Cannot connect to server. Please, try again");
                result = new PluginResult(PluginResult.Status.IO_EXCEPTION, "Cannot connect to server. Please, try again");
                return result;
            } 

            catch (java.net.SocketTimeoutException e) {
                Log.d("TCPSockets", "Connection timed out");
    //                  return new PluginResult(PluginResult.Status.IO_EXCEPTION, "Connection timed out. Please, try again");
                result = new PluginResult(PluginResult.Status.IO_EXCEPTION, "Connection timed out. Please, try again");
                return result;
            }

            catch (IOException e) {
                Log.d("TCPSockets", "IOException");
    //                  return new PluginResult(PluginResult.Status.IO_EXCEPTION, "Unexpected error. Please, try again");
                result = new PluginResult(PluginResult.Status.IO_EXCEPTION, "Unexpected error. Please, try again");
                return result;
            }       
        }
    }