在Android服务的良好做法 [英] Good practices for services on Android

查看:149
本文介绍了在Android服务的良好做法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在使用我的应用程序2服务:

1:LocationService ,基本上是试图本地化的用户,其目的是维持生命,只有当应用程序是在前景

2:XmppService ,它初始化与XMPP服务器的连接,接收邮件,发送,注销......其目的是维持生命,直到用户注销

我一直在阅读了很多资料,但我不能说清楚。

我在 泄漏当我尝试存储LocationServiceBinder,它用来调用我的服务功能(参考的使用的AIDL接口的)。相同的XMPP。当我取消绑定,我得到有时ANR(这一下喜欢的事实,我绑定/解除绑定的古怪完成,onResume,onRestart ... 的链接)。

所有的系统工作,但我敢肯定,这是不正确的方式做到这一点,并请我很想跟着有经验的人回来右侧的力量! :)

干杯

更新

我的位置服务是绑定在应用程序启动以获得尽可能快地站在用户的立场:

 如果(callConnectService == NULL){
            callConnectService =新ServiceConnection(){
                公共无效onServiceConnected(组件名的名字,粘合剂的IBinder){
                    locationServiceBinder = LocationServiceBinder.Stub.asInterface(粘合剂);
                    尝试 {
                        global.setLocationBinder(locationServiceBinder);
                        。global.getLocationBinder()startLocationListener();
                    }赶上(例外五){
                        Log.e(TAG,服务粘结剂ERROR);
                    }
                }

                公共无效onServiceDisconnected(组件名名){
                    locationServiceBinder = NULL;
                }
            };
        }

        / *卫星发射服务的* /
        aimConServ =新的意图(这一点,LocationService.class);
        布尔约束= bindService(aimConServ,callConnectService,BIND_AUTO_CREATE);
 

我的XMPP服务启动时,用户登录:

callConnectService =新ServiceConnection(){

 公共无效onServiceConnected(组件名的名字,粘合剂的IBinder){
                尝试 {
                    Log.d(TAG,[XMPP_INIT]完成。);
                    global.setServiceBinder(ConnectionServiceBinder.Stub.asInterface(粘合剂));
                    //连接到XMPP聊天
                    global.getServiceBinder()连接()。
                }赶上(例外五){
                    Log.e(TAG,服务粘结剂ERROR);
                    e.printStackTrace();
                }
            }

            公共无效onServiceDisconnected(组件名名){
                Log.e(TAG,服务粘结剂断开);
            }
        };

        / *卫星发射服务的* /
        意图aimConServ =新的意图(MMWelcomeProfile.this,XmppService.class);
        势必= bindService(aimConServ,callConnectService,Context.BIND_AUTO_CREATE);
 

和解除每个活动:

 如果(callConnectService!= NULL){
        unbindService(callConnectService);
        callConnectService = NULL;
    }
 

解决方案

这还没有得到很好的记录在谷歌的官方开发指南,Context.bindService()实际上是一个异步调用。这就是为什么ServiceConnection.onServiceConnected()被用作一个回调方法的原因,装置无法立即发生。

 公共类MyActivity延伸活动{
  私人MyServiceBinder myServiceBinder;

  保护ServiceConnection myServiceConnection =新ServiceConnection(){
    公共无效onServiceConnected(组件名的className,服务的IBinder){
      myServiceBinder =(MyServiceBinderImpl)服务;
    }

    ......
  }

  公共无效的onCreate(包savedInstanceState){
    super.onCreate(savedInstanceState);
    // bindService()是一个异步调用。 myServiceBinder是resoloved在onServiceConnected()
    bindService(新意图(这一点,MyService.class),myServiceConnection,Context.BIND_AUTO_CREATE);
    //你会得到一个空点参考这里,如果你试图立即使用MyServiceBinder。
    MyServiceBinder.doSomething(); //<  - 尚未解决,使零点参考这里
  }
}
 

一个解决方法是调用MyServiceBinder.doSomething()的myServiceConnection.onServiceConnected(),或者通过一些用户交互执行MyServiceBinder.doSomething()(如点击按钮),您拨打bindService(后延迟)和系统之前获得myServiceBinder的基准是相当很快。只要你不马上使用它,你应该就好了。

看看这太问题<一href="http://stackoverflow.com/questions/3358230/how-to-bind-to-running-android-service">CommonsWare's回答更多的细节。

I am currently using 2 services in my app:

1: LocationService, basically trying to localize the user, and aims to stay alive only when the app is on foreground.

2: XmppService, which init the connection with the xmpp server, receive messages, send it, logout ... and aims to stay alive until the user logout.

I've been reading quite a lot of documentation, but I just can't make it clear.

I'm having Leaks when I try to store reference of LocationServiceBinder, which is used to call my service functions (using AIDL interfaces). Same for Xmpp. When I unbind, I get sometimes ANR (which look like to be linked with the fact that my bind/unbind are weirdly done, onResume, onRestart ...).

All the system is working, but I'm sure it is not the right way to do it, and please I would love to follow experienced people to come back in the right side of the force ! :)

Cheers

UPDATE

My Location Service is bind at the app launch to get as fast as possible the user's position :

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);

My Xmpp Service is launched when the user log in :

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);

and unbind on each Activity :

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

解决方案

It hasn't been well-documented in Google's official dev guide, Context.bindService() is actually an asynchronous call. This is the reason why ServiceConnection.onServiceConnected() is used as a callback method, means not happened immediately.

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

A workaround is call MyServiceBinder.doSomething() in myServiceConnection.onServiceConnected(), or perform MyServiceBinder.doSomething() by some user interaction (e.g. button click), as the lag after you call bindService() and before system get a reference of myServiceBinder is quite soon. as long as you are not using it immediately, you should be just fine.

Check out this SO question CommonsWare's answer for more details.

这篇关于在Android服务的良好做法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆