Служба в классе приложения, выполняющая сбой соединения через веб-сокет

Я создаю приложение чата, которое использует веб-сокет. Я написал сервис, который называется в классе приложения. Проблема в том, что иногда mConnection становится нулевым, когда я просто запускаю приложение после сбоя. Я думаю, что это происходит из-за того, что служба запускается в фоновом режиме, даже когда я закрываю приложение, и когда я снова запускаю его, он не может создать новый сервис и связать его с ним. Мои вопросы: это хороший способ написания кода? И есть ли способ остановить сервис на уничтожение приложения?

public class MyApplication extends Application{
  private final AtomicInteger refCount = new AtomicInteger();
    public ConnectionService mConnectionService;
    private ServiceConnection mConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder binder) {
            ConnectionService.MyBinder b = (ConnectionService.MyBinder) binder;
            mConnectionService = b.getService();
            Log.d("MyApplication", "MyApplication has been bounded");
        }

        public void onServiceDisconnected(ComponentName className) {
            mConnectionService = null;
            Log.d("MyApplication", "MyApplication has been unbounded");
        }
    };

    @Override
    public void onCreate() {
        Intent intent = new Intent(this, ConnectionService.class);
        getApplicationContext().bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    }

    public ConnectionService getConnectionService() {
        refCount.incrementAndGet();
        Log.d("MyApplication", "getConnectionService, current: "+refCount);
        return mConnectionService;
    }

    public void releaseConnectionService() {

        if (refCount.get() == 0 || refCount.decrementAndGet() == 0) {
            mConnectionService.stopSelf();
            Log.d("MyApplication", "MyApplication has been stopped ");
        }
        Log.d("MyApplication", "releaseConnectionService, current: "+refCount);
    }

}

А другой класс выглядит примерно так:

    public class LobbyActivity extends Activity{
    ListView lvContacts;
    Gson gson;
    LoginData mLoginData;
    MyReceiver receiver;
    ArrayList<User> users;
    LobbyAdapter lobbyAdapter;
    @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    gson = new Gson();
    Intent intent = getIntent();
    String loginDataJson = intent.getStringExtra("LoginData");
    mLoginData = gson.fromJson(loginDataJson, LoginData.class);
    getActionBar().setTitle(mLoginData.getUsername());
    setContentView(R.layout.activity_lobby);    
    users = new ArrayList<User>();

    lvContacts = (ListView)findViewById(R.id.lvContacts);
    lobbyAdapter=new LobbyAdapter(users, this);
    lvContacts.setAdapter(lobbyAdapter);

    Commands cmd = new Commands(getApplicationContext());
    cmd.sendCommand(Commands.COMMAND_GET_MANAGER_LIST);
    cmd.sendCommand(Commands.COMMAND_GET_USER_LIST);

    receiver = new MyReceiver(new Handler()) {
        @Override
        public void onReceive(Context context, Intent intent) {
            String message = intent.getStringExtra(ConnectionService.MESSAGE);
            String notification = intent.getStringExtra(ConnectionService.NOTIFICATION);
            if (message!=null){
                try {
                    switch (Utils.getCommand(message)) {
                    case Commands.COMMAND_GET_USER_LIST:
                        ArrayList<User> user = new ArrayList<User>();
                        user  = (gson.fromJson(message, UserList.class)).users;
                        users.addAll(user);
                        lobbyAdapter.notifyDataSetChanged();

                        break;

                    default:
                        break;
                    }



                } catch (JSONException e) {
                    e.printStackTrace();
                }

            }
        }
    };
    LocalBroadcastManager.getInstance(this).registerReceiver(receiver,
            new IntentFilter(MainActivity.BROADCAST_ACTION));

}
    class UserList{
        String cmd;
        ArrayList<User> users; 
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        ((MyApplication)getApplicationContext()).releaseConnectionService();
    }

}

Причина, по которой я помещаю сервис в класс Application, заключается в том, что я хочу, чтобы он работал, пока приложение работает; и также это должно быть доступно всем действиям.

1 ответ

Решение

Это хороший способ написания кода?

Я бы сказал, что это плохая практика программирования - запускать такие компоненты приложения Android, как Service или же Activity от Application учебный класс. Вы должны начать обслуживание с Activity или же BroadcastReceiver составная часть. В конце кода внутри Application onCreate запускается потому, что новый процесс создается для вашего приложения при запуске. Это произойдет, если вы запустите приложение из панели запуска и основной Activity начинается или BroadcastReceiver был дан вызов. В этот момент вы можете начать Service от любого из них.

И есть ли способ остановить сервис на уничтожение приложения?

Вы можете остановиться Service от деятельности onDestroy(), Если вы не хотите останавливать Сервис при каждом изменении конфигурации (например, поворот экрана), вы можете проверить onDestory метод, будь то уничтожение или перезагрузка только через isChangingConfigurations метод Activity и решили остановиться или нет Service основываясь на этом знании.

Другие вопросы по тегам