这让我发疯了。我创建了一个监控加速度计的本地服务。有时服务有效,有时却没有。似乎该服务只是随意取消注册。
服务在手机上的一定程度的移动后作出反应。问题是如果我启动服务,我可以立即正确地结束它。然而,在我摇动手机(启动服务应如何行动)后没有任何反应,然后当我尝试关闭服务时,我收到错误。让我感到困惑的是,我在我的代码中放置了中断代码来检测移动,并且在移动后调用的代码甚至没有被执行。
任何帮助都会非常感激。这是我的服务代码及其经理。
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类。
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();
}
};
}
答案 0 :(得分:4)
首先,如果您正在考虑尝试创建一个永远运行的服务,您应该考虑不要这样做。一直运行的服务对电池寿命来说真的很糟糕。
除此之外,我建议摆脱
AccelWatch.startService(i);
onServiceConnected()
中的。
绑定到服务时,服务会自动启动,onServiceConnected()
是您获得的异步回调。因此,您可以有效地尝试使用该行重新启动服务。
不要这样做
private static Context CONTEXT;
然后,
CONTEXT = this;
您刚刚保证会泄漏您的服务(以及您在那里执行的活动),因为应用程序的生命周期中存在静态引用 - 而不是服务的生命周期。如果您需要上下文,只需使用“this”。您已进入服务/活动。
泄漏服务的另一个原因是......
public class AccelBinder extends Binder {
AccelService getService() {
return AccelService.this;
}
}
这个内部类不是静态的。在java中,这意味着内部类具有对外部类的引用。 Android中存在一个错误(问题6426),这意味着系统将始终泄漏您的活页夹。如果您的活页夹有对服务的引用(作为非静态内部类),那么您也会泄漏服务。
自版本5(Android 1.6)以来, ServiceonStart()
已被弃用,因为使用此版本的设备不到7%我建议至少在您使用本服务之前将其删除 - 这样您就没有想一想。
了解你如何继续这样做。坚持服务他们很容易 - 第一次只需要一点调整(生命周期等)
由于这些问题很常见 - 我决定在这里写一篇博客来提供一些指导
http://www.ozdroid.com/#!BLOG/2010/12/19/How_to_make_a_local_Service_and_bind_to_it_in_Android
该示例使用的是使用服务而不是onStart()
的绑定方法 - 但我尝试将内容放在上下文中,以供初学者使用。
答案 1 :(得分:0)
您可以添加一些日志以查看导致服务取消注册的情况,并且您可以在logcat视图中检查服务是否存在异常。