首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Android本地服务注册

Android本地服务注册
EN

Stack Overflow用户
提问于 2010-12-17 16:47:18
回答 2查看 2.3K关注 0票数 1

我都快疯了。我已经创建了一个本地服务来监控加速度计。服务有时有效,有时不起作用。该服务似乎一直在随机地注销自身。

在电话上移动到一定程度后,该服务会做出反应。问题是,如果我启动服务,我可以立即正确地结束它。然而,在我摇动电话(设置服务应该如何运行)之后,什么也没有发生,然后当我试图关闭服务时,我得到了一个错误。真正让我困惑的是,我在检测移动的代码中添加了中断代码,而在移动之后调用的代码甚至都没有执行。

任何帮助都将不胜感激。下面是我的服务及其管理器的代码。

代码语言:javascript
复制
public class AccelService extends Service {
    public static boolean listening = false;
    private static Context CONTEXT;
    private static Sensor sensor;
    private static SensorManager ASensorManager;

    private static SensorEventListener accelEventListener = new SensorEventListener() {

        private float x = 0;
        private float y = 0;
        private float z = 0;
        private double max = 0;
        private double force = 0;

        public void onAccuracyChanged(Sensor sensor, int accuracy) {}

        public void onSensorChanged(SensorEvent event) {

            x = event.values[0];
            y = event.values[1];
            z = event.values[2];
            force = Math.sqrt(x*x+y*y+z*z);
            if (force > max)
                max = force;

            if (force > AccelManager.dropValue)                
                AccelManager.onDrop(force);                
        } 
    };

private static void startListener() {
    ASensorManager = (SensorManager) CONTEXT.getSystemService(Context.SENSOR_SERVICE);
    List<Sensor> sensors = ASensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER);
    if (sensors.size() > 0) {
        sensor = sensors.get(0);
        listening = ASensorManager.registerListener(accelEventListener, sensor, SensorManager.SENSOR_DELAY_GAME);
        AccelManager.setListening(listening);
    }
} 

private final IBinder mBinder = new AccelBinder();

public class AccelBinder extends Binder {
    AccelService getService() {
        return AccelService.this;
    }
}

public void onCreate() {
    CONTEXT = this;
    startListener();
}

public boolean isListening() {
    return listening;
}

@Override
public void onStart(Intent intent, int startId){
    Log.i("LocalService", "Received start id " + startId + ": " + intent);
}

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i("LocalService", "Received start id " + startId + ": " + intent);
        return AccelService.START_STICKY;
    }

    @Override
    public void onDestroy() {
        if (listening)
        stopListening();
        super.onDestroy();
    }

    public static void stopListening() {  
        AccelManager.setListening(false);
        try {
            if (ASensorManager != null && accelEventListener != null)
                ASensorManager.unregisterListener(accelEventListener);            
        } catch (Exception e) {}     
    }

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

这是Manager类。

代码语言:javascript
复制
public class AccelManager extends Activity {

    public static Boolean isListening = false;
    private static Boolean callMade = false;
    public static Context ctxt;
    public static int dropValue = 100;
    private static Intent i;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    public void setContext(Context context) {
        ctxt = context;
        i = getIntent();
    }


    public void activateService(Boolean check) {
        if (check)
            doBindService();
        else {
            if (isListening) {
                if (AccelWatch != null) {
                    AccelWatch.stopSelf();
                    doUnbindService();
                }
            }
        }    
    }

    public static void onDrop(double force){
        if (!callMade) {
            Toast.makeText(ctxt, "Phone dropped: " + force, 5000).show();
            Intent i = new Intent(ctxt,DropDetected.class);
            AccelWatch.stopSelf();
            doUnbindService();
            callMade = true;
            ctxt.startActivity(i);
        }
    }

    private void doBindService() {
        if (!isListening) {
            i = new Intent(ctxt,AccelService.class);
            ctxt.bindService(i, AccelConnection, ctxt.BIND_AUTO_CREATE);
        }
    }

    private static void doUnbindService() {
        if (isListening)         
            ctxt.unbindService(AccelConnection);
    }    

    public void setDropValue(int drop) {
        dropValue = drop;
    }

    public boolean isRunning(){
        return AccelWatch.isListening();
    }

    public static void setListening(Boolean listen){
        isListening = listen;
    }

    private static AccelService AccelWatch;

    private static ServiceConnection AccelConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder service)     {
            AccelWatch = ((AccelService.AccelBinder)service).getService();
            AccelWatch.startService(i);

            Toast.makeText(ctxt, "The service is binded.",Toast.LENGTH_SHORT).show();
        }

        public void onServiceDisconnected(ComponentName className) {
            AccelWatch = null;
            Toast.makeText(ctxt, "The service was disconnected.",Toast.LENGTH_SHORT).show();
        }
    };
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-12-19 17:27:05

首先,如果您正在考虑尝试创建一个永远运行的服务,那么您应该考虑不这样做。一直运行的服务对电池寿命非常不利。

抛开这个不谈,我建议去掉

代码语言:javascript
复制
    AccelWatch.startService(i); 

onServiceConnected()中。

当您绑定到服务时,该服务将自动启动,onServiceConnected()是您获得的异步回调。因此,您可能实际上是在尝试使用该线路重新启动服务。

永远不要这样做

代码语言:javascript
复制
    private static Context CONTEXT;

然后,

代码语言:javascript
复制
    CONTEXT = this;

你已经保证了你会泄露你的服务(以及你在那里做的活动),因为静态引用存在于应用程序的生命周期--而不是服务的生命周期。如果需要上下文,只需使用"this“即可。您已经在您的服务/活动中。

另一个泄露你的服务的来源是这里...

代码语言:javascript
复制
public class AccelBinder extends Binder {
     AccelService getService() {
         return AccelService.this;
     }
 }

这个内部类不是静态的。在java中,这意味着内部类具有对外部类的引用。Android中有一个bug (问题6426),这意味着系统总是会泄露你的活页夹。如果您的绑定器有一个对服务的引用(就像非静态内部类一样),那么您也会泄漏该服务。

从版本5(Android1.6)开始,ServiceonStart()就被弃用了,因为只有不到7%的设备在使用这个版本,我建议至少在你的服务正常工作之前放弃它--这样你就不必考虑它了。

看看你是怎么做的。坚持使用服务它们非常简单-只需要在第一次(生命周期等)进行一点调整

由于这些问题很常见-我决定在这里写一个博客来提供一些指导

http://www.ozdroid.com/#!BLOG/2010/12/19/How_to_make_a_local_Service_and_bind_to_it_in_Android

这个例子使用的是绑定方法,使用服务而不是onStart() --但我已经试着为初学者提供了一些上下文。

票数 4
EN

Stack Overflow用户

发布于 2010-12-17 17:15:26

您可以添加一些日志来查看导致该服务注销的原因,并可以在logcat视图中查看该服务是否存在异常。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4468893

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档