2016-12-09 7 views
2

У меня есть служба, которая создает сервер сокета, и клиент подключается к нему. Соединение поддерживается открытым для передачи данных. Услуга - START_STICKY. Поэтому, когда пользователь убивает приложение, выталкивая его из последних задач, снова вызываются функции onCreate и onStartCommand. Я не хочу повторно инициализировать сокет и вместо этого сохранить его состояние, как это было до того, как пользователь выполнил задачу, чтобы убить его и продолжать передачу данных без прерывания.Android - Как сохранить соединение сокета при перезапуске службы

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) { 
     } 
    } 
} 

Что я пробовал?

  1. Попробуйте сохранить сокет с помощью gson в SharedPreferences. Не удалось вернуть объект сокета обратно.

    SharedPreferences pref = getApplicationContext(). 
            getSharedPreferences("MyPref", MODE_PRIVATE); 
    SharedPreferences.Editor editor = pref.edit(); 
    editor.putBoolean("onGoingConnection",false); 
    Gson gson = new Gson(); 
    String json = gson.toJson(socket); 
    editor.putString("ExistingSocket",json); 
    editor.apply() 
    
  2. Содержит static Сокет в той деятельности, в которой началась служба. Он всегда был нулевым для возобновления службы.

ответ

0

Я сделал еще несколько попыток, и не мог обойти, чтобы сохранить связь. Поэтому я подумал, могу ли я уведомить своего клиента о том, что мой сервер хочет, чтобы он снова подключился до того, как соединение опустится, я могу подключиться автоматически. Если кто-нибудь найдет это полезным. Просто добавлен android:stopWithTask="false" в сервисный тег манифеста и над ним 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(); 
    } 
} 
0

Я не хочу, чтобы повторно инициализировать сокет и вместо того, чтобы сохранить это состояние, как это было до того, как пользователь наотмашь задачу, чтобы убить его и держать передачу данных без перерывов.

По определению это невозможно. Ваш процесс был прерван. Ваш сокет уходит, когда ваш процесс.

Попробуйте сохранить сокет как с помощью gson в SharedPreferences.

Разъем не может быть сохранен. Вы сохранили toString()Socket, не более того.

+0

Так что я не могу спасти свое соединение от разрушения? Другим решением может быть использование дейтаграммы, но это также связано с изменением моего клиента. – dumplingParadox

+0

@dumplingParadox: «Значит, я не могу спасти мою связь от разрушения?» -- верный. Вы не можете предположить, что ваш процесс будет навсегда, даже с сервисом. Как только ваш процесс будет завершен, может потребоваться некоторое время, прежде чем система перезапустит его, даже с помощью START_STICKY. Вы должны проектировать свое приложение для поддержки произвольного количества времени, когда у вас нет процесса и нет подключения к серверу. – CommonsWare

+0

Я подумал об этом, вы были правы в том, что не смогли сохранить состояние. Отмечено как правильный ответ. :)) – dumplingParadox

0

Вы можете это исправить, сделав класс расширяет приложению

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"> 
+0

Пользовательский класс 'Application' не останавливает процесс от завершения. – CommonsWare

+0

, но вопрос в том, чтобы сохранить состояние гнезда? – 1shubhamjoshi1