Хорошая практика для сервисов на Android - PullRequest
2 голосов
/ 01 декабря 2011

В настоящее время я использую 2 приложения в моем приложении:

1: LocationService , в основном пытается локализовать пользователя и стремится остаться в живых только тогда, когда приложение находится на переднем плане.

2: XmppService , который инициирует соединение с сервером xmpp, принимает сообщения, отправляет его, выходит из системы ... и стремится остаться в живых до выхода пользователя из системы.

Я читал довольно много документации, но просто не могу ее прояснить.

У меня утечки при попытке сохранить ссылку на LocationServiceBinder, который используется для вызова моих сервисных функций ( с использованием интерфейсов AIDL ). То же самое для Xmpp. Когда я отменяю привязку, я иногда получаю ANR (, которая выглядит как связанная с тем фактом, что мои привязки / отмены привязки сделаны странным образом, onResume, onRestart ... ).

Все система работает , но я уверен, что это неправильный способ сделать это, и, пожалуйста, я хотел бы следовать за опытными людьми, чтобы вернуться в правую часть силы! :)

Приветствия

UPDATE

Служба «Мое местоположение» привязана при запуске приложения, чтобы как можно быстрее получить позицию пользователя:

if(callConnectService == null) {
            callConnectService = new ServiceConnection() {
                public void onServiceConnected(ComponentName name, IBinder binder) {
                    locationServiceBinder = LocationServiceBinder.Stub.asInterface(binder);
                    try {
                        global.setLocationBinder(locationServiceBinder); 
                        global.getLocationBinder().startLocationListener();
                    } catch (Exception e){
                        Log.e(TAG, "Service binder ERROR");
                    }
                }

                public void onServiceDisconnected(ComponentName name) {
                    locationServiceBinder = null;
                }
            };
        }

        /* Launch Service */
        aimConServ =  new Intent(this, LocationService.class);
        boolean bound = bindService(aimConServ,callConnectService,BIND_AUTO_CREATE);

Моя служба Xmpp запускается, когда пользователь входит в систему:

callConnectService = new ServiceConnection () {

            public void onServiceConnected(ComponentName name, IBinder binder) {
                try {
                    Log.d(TAG, "[XMPP_INIT] Complete.");
                    global.setServiceBinder(ConnectionServiceBinder.Stub.asInterface(binder)); 
                    //Connect to XMPP chat
                    global.getServiceBinder().connect();
                } catch (Exception e){
                    Log.e(TAG, "Service binder ERROR ");
                    e.printStackTrace();
                }
            }

            public void onServiceDisconnected(ComponentName name) {
                Log.e(TAG, "Service binder disconnection ");
            }
        };

        /* Launch Service */
        Intent aimConServ =  new Intent(MMWelcomeProfile.this, XmppService.class);
        bound = bindService(aimConServ,callConnectService,Context.BIND_AUTO_CREATE);

и снимите привязку с каждого занятия:

if (callConnectService != null){
        unbindService(callConnectService);
        callConnectService = null;
    }

Ответы [ 3 ]

1 голос
/ 02 декабря 2011

Это не было хорошо документировано в официальном руководстве Google по разработке, Context.bindService () на самом деле является асинхронным вызовом. По этой причине ServiceConnection.onServiceConnected () используется в качестве метода обратного вызова, значит, это произошло не сразу.

public class MyActivity extends Activity {
  private MyServiceBinder myServiceBinder;

  protected ServiceConnection myServiceConnection = new ServiceConnection() {
    public void onServiceConnected(ComponentName className, IBinder service) {
      myServiceBinder = (MyServiceBinderImpl) service;
    }

    ... ...
  }

  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // bindService() is an asynchronous call. myServiceBinder is resoloved in onServiceConnected()
    bindService(new Intent(this, MyService.class),myServiceConnection, Context.BIND_AUTO_CREATE);
    // You will get a null point reference here, if you try to use MyServiceBinder immediately.
    MyServiceBinder.doSomething(); // <-- not yet resolved so Null point reference here
  }
}

Обходным решением является вызов MyServiceBinder.doSomething () в myServiceConnection.onServiceConnected () или выполнение MyServiceBinder.doSomething () при некотором взаимодействии с пользователем (например, при нажатии кнопки), как задержка после вызова bindService () и до того, как система получит Ссылка на myServiceBinder довольно скоро. до тех пор, пока вы не используете его немедленно, все будет в порядке.

Проверьте этот SO вопрос Ответ CommonsWare для более подробной информации.

0 голосов
/ 27 декабря 2012

если вы связываетесь со службой в Деятельности, вам также необходимо отсоединить ее:

@Override
protected void onResume() {

    Log.d("activity", "onResume");
    if (locationServiceBinder == null) {
        doBindLocationService();
    }
            super.onResume();
}

@Override
protected void onPause() {

    Log.d("activity", "onPause");
    if (locationServiceBinder  != null) {
        unbindService(callConnectService);
        locationServiceBinder = null;
    }
    super.onPause();
}

где doBindLocationService () :

public void doBindLocationService() {
    Log.d("doBindService","called");

    aimConServ =  new Intent(this, LocationService.class);
    // Create a new Messenger for the communication back
    // From the Service to the Activity
    bindService(aimConServ, callConnectService, Context.BIND_AUTO_CREATE);
}

Youнеобходимо выполнить эту практику для вашего XmppService , а также

0 голосов
/ 21 ноября 2012

эта ветка довольно старая, но я ее только что обнаружил.

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

В этом случае служба не будет уничтожена, когда вы открепите ее, она будет уничтожена, когда:

  • вы останавливаете его, и к нему никто не привязан
  • вы отсоединяете его и он был остановлен раньше.

Я сделал небольшое демонстрационное приложение Service Lifecycle на GitHub , и он также доступен в Google Play .

Надеюсь, это поможет;)

...