Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/379.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Android-如何在服务重新启动时保留套接字连接_Java_Android_Sockets_Tcp_Connection - Fatal编程技术网

Java Android-如何在服务重新启动时保留套接字连接

Java Android-如何在服务重新启动时保留套接字连接,java,android,sockets,tcp,connection,Java,Android,Sockets,Tcp,Connection,我有一个服务,它创建一个套接字服务器,并有一个客户端连接到它。连接保持打开状态以传输数据。服务是START\u STICKY。因此,当用户通过从最近的任务中滑动应用程序来终止应用程序时,将再次调用onCreate和onStartCommand函数。我不想重新初始化套接字,而是保持它的状态,就像用户刷任务杀死它之前一样,并保持不间断地传输数据 public class SendTasksService extends Service { static Socket socket=null;

我有一个服务,它创建一个套接字服务器,并有一个客户端连接到它。连接保持打开状态以传输数据。服务是
START\u STICKY
。因此,当用户通过从最近的任务中滑动应用程序来终止应用程序时,将再次调用
onCreate
onStartCommand
函数。我不想重新初始化套接字,而是保持它的状态,就像用户刷任务杀死它之前一样,并保持不间断地传输数据

public class SendTasksService extends Service {
    static Socket socket=null;
    static boolean shouldRun=true;
    static final int port = PORT_NO;
    static ServerSocket listener = null;

    @Override
    public IBinder onBind(Intent intent) {
        System.out.println("Service onBind.");
        return null;
    }

    @Override
    public void onCreate() {
        System.out.println("Service onCreate.");
        shouldRun=true;
        try {
            if(socket==null){
                System.out.println("Starting Listening..");
                listener = new ServerSocket(port);
                System.out.println("Notification Started.");
            }else{
                System.out.println("Continuing With Old Socket..");
                /*
                    How to get the socket if the connection
                    was made before swipe killing the app from recent
                */
            }
        }catch(Exception ioe){
            System.out.println("Exception in listening.");
            ioe.printStackTrace();
        }
    }

    public void onDestroy() {
        System.out.println("Service onDestroy.");
        closeConnection();
    }

    public void closeConnection(){
        //Wind up work and close connection
        /*
            This should also remove any socket information saved anywhere
        */
    }

    public int onStartCommand(Intent intent, int flags, int startid) {
        System.out.println("Service onStartCommand.");
        try{
            new AsyncAction().execute();
        }catch (Exception e) {
            e.printStackTrace();
        }

        return START_STICKY;
    }

    private class AsyncAction extends AsyncTask<String, Void, String> {
        protected String doInBackground(String... args) {
            while(shouldRun) {
                try {
                    if(socket==null) {
                        socket = listener.accept();
                        /*
                            Socket connection established here.
                            Save this socket state or preserve it somehow
                            So that connection does not break on killing the app
                        */
                    }else{
                        /*
                            Continue with the old socket data, and resume connection
                        */
                    }
                    if(socket==null)
                        continue;
                }catch(Exception e){
                    System.out.println("Exception after Break");
                    e.printStackTrace();
                }
            }
            return null;
        }

        protected void onPostExecute(String result) {
        }
    }
}
  • 在启动服务的活动中创建一个
    静态
    保存套接字。服务恢复时它始终为空
  • 我不想重新初始化套接字,而是保持它的状态,就像用户刷任务杀死它之前一样,并保持不间断地传输数据

    public class SendTasksService extends Service {
        static Socket socket=null;
        static boolean shouldRun=true;
        static final int port = PORT_NO;
        static ServerSocket listener = null;
    
        @Override
        public IBinder onBind(Intent intent) {
            System.out.println("Service onBind.");
            return null;
        }
    
        @Override
        public void onCreate() {
            System.out.println("Service onCreate.");
            shouldRun=true;
            try {
                if(socket==null){
                    System.out.println("Starting Listening..");
                    listener = new ServerSocket(port);
                    System.out.println("Notification Started.");
                }else{
                    System.out.println("Continuing With Old Socket..");
                    /*
                        How to get the socket if the connection
                        was made before swipe killing the app from recent
                    */
                }
            }catch(Exception ioe){
                System.out.println("Exception in listening.");
                ioe.printStackTrace();
            }
        }
    
        public void onDestroy() {
            System.out.println("Service onDestroy.");
            closeConnection();
        }
    
        public void closeConnection(){
            //Wind up work and close connection
            /*
                This should also remove any socket information saved anywhere
            */
        }
    
        public int onStartCommand(Intent intent, int flags, int startid) {
            System.out.println("Service onStartCommand.");
            try{
                new AsyncAction().execute();
            }catch (Exception e) {
                e.printStackTrace();
            }
    
            return START_STICKY;
        }
    
        private class AsyncAction extends AsyncTask<String, Void, String> {
            protected String doInBackground(String... args) {
                while(shouldRun) {
                    try {
                        if(socket==null) {
                            socket = listener.accept();
                            /*
                                Socket connection established here.
                                Save this socket state or preserve it somehow
                                So that connection does not break on killing the app
                            */
                        }else{
                            /*
                                Continue with the old socket data, and resume connection
                            */
                        }
                        if(socket==null)
                            continue;
                    }catch(Exception e){
                        System.out.println("Exception after Break");
                        e.printStackTrace();
                    }
                }
                return null;
            }
    
            protected void onPostExecute(String result) {
            }
        }
    }
    
    根据定义,这是不可能的。您的进程已终止。当进程关闭时,套接字将关闭

    尝试在SharedReferences中使用gson将套接字另存为


    套接字无法持久化。您保存了
    套接字的
    toString()
    ,仅此而已。

    您可以通过创建一个扩展应用程序的类来修复它

    public class Engine extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        /* do something here */
    
    }
    }
    
    然后在清单中做一些类似的事情

    <manifest...>
    
    <application
        android:name=".[yourclassname]" //
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
    

    我又做了一些修补,但无法四处保存连接。所以我想如果我能在连接断开之前通知我的客户端我的服务器希望它重新连接,我就能自动重新连接。如果有人觉得这有用的话。 刚刚在manifest的服务标签中添加了
    android:stopWithTask=“false”
    ,并在服务中添加了rid
    onTaskRemoved
    。在
    onTaskRemoved
    中,我向客户端发送了重新连接到服务器的信号

    public void onTaskRemoved(Intent rootIntent) {
        System.out.println("Service onTaskRemoved.");
        try {
            PrintWriter out = new PrintWriter(socket.getOutputStream());
            out.print("RECONNECT\0");
            out.flush();
            out = null;
        }catch(Exception e) {
            System.out.println("Exception in closing connection.");
            e.printStackTrace();
        }
    }
    

    所以我不能保存我的连接不被破坏?另一个解决方案可能是使用数据报,但这也会涉及到更改我的客户机。@dumplingParadox:“所以我不能保存我的连接而不被破坏?”——正确。您不能假设您的流程将永远存在,即使有服务。一旦进程终止,系统可能需要一段时间才能重新启动它,即使是
    START\u STICKY
    。你需要将你的应用程序设计为支持任意时间段,在这些时间段内,你没有进程,也没有连接到服务器。我找到了一种解决方法,你没有保存状态是对的。标记为正确答案。:)自定义
    应用程序
    类不会阻止进程终止。但问题是保留套接字的状态?