我试图找出我的服务从我的应用程序泄漏的原因。
我得到的官方错误是该服务不再注册。
这是有效的: 我创建了一个创建监听器的服务,当监听器被触发意图启动另一个活动的服务集时。新活动开始并做到了。
问题: 当我回到主屏幕,让我可以选择关闭服务时,我得到了我之前说过的错误,导致IllegalArgumentException(当我尝试解除绑定未注册的服务时)。
非常感谢任何帮助。这是我服务的代码。这就是我所包含的所有内容,因为这似乎是问题所在,但如果您需要更多,请告诉我。
先谢谢,这是代码。
import java.lang.ref.WeakReference;
import java.util.List;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
public class AccelService extends Service
{
public static boolean listening = false;
public boolean callMade = false;
private static Sensor sensor;
private static SensorManager ASensorManager;
private SensorEventListener EventListener =
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);
Log.i("LocalService", "Event happened: " + force);
if (force > Main.dropValue)
{
onDrop(force);
}
}
};
public void startListener()
{
ASensorManager = (SensorManager) this.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);
}
}
public class AccelBinder<S> extends Binder
{
private WeakReference<S> mService;
public AccelBinder (S service)
{
mService = new WeakReference<S>(service);
}
public S getService()
{
return mService.get();
}
}
public IBinder mBinder;
@Override
public void onCreate()
{
startListener();
mBinder = new AccelBinder<AccelService>(this);
}
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();
mBinder = null;
super.onDestroy();
}
public void onDrop(double force)
{
if (!callMade)
{
Toast.makeText(this, "Phone dropped: " + force, 5000).show();
Intent i = new Intent(this,Next.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
callMade = true;
//stopListening();
//onDestroy();
//SafetyNet.ctxt.unbindService(SafetyNet.AccelWatch);
this.startActivity(i);
}
}
public void stopListening()
{
listening = false;
try {
if (ASensorManager != null && accelEventListener != null)
{
ASensorManager.unregisterListener(accelEventListener);
}
} catch (Exception e) {}
}
@Override
public IBinder onBind(Intent intent)
{
return mBinder;
}
}
答案 0 :(得分:7)
我对传感器了解不多,但您的服务看起来很不错。
如果AccelBinder是您服务的内部类,则使其成为一个静态内部类,或者像我通常那样,一个单独的类。静态内部类没有对外部类的引用。记住你会泄漏你的活页夹。如果您的Binder是一个非静态的内部类,它会引用您的服务,这样也会泄漏。
我猜测 - 就像疯狂猜测一样 - 在没有任何代码的情况下,您的Activity生命周期管理存在问题以及如何处理Binder对象。
要记住的事情......
不要对Binder对象保持静态引用 - 它们是一次性的 - 每次绑定时都会获得一个新引用。
使您的Binding在您的Activity生命周期中保持对称。如果你在onCreate()中绑定,则在onDestroy()中取消绑定(或者如果是isFinishing()则取消on),等等。如果你不明白带有Sensor的手机的物理旋转会破坏你的Activity,从头开始重新创建它,这一点尤为重要。
你似乎完全喜欢“静态”类变量。在Android静态中,事物往往会导致内存泄漏 - 如果你泄漏的内容有上下文 - 事情会变得很糟糕。如果要在同一个类的实例之间保持状态,请考虑使用“首选项”。
例如,
private static Sensor sensor;
private static SensorManager ASensorManager;
在使用之间扔掉它们。
请确保您在活动中未特别保留对服务的静态引用。服务是Android的本质,如果它仍在运行,你每次绑定时都会得到相同的服务。依靠您的服务在某个时间点被操作系统杀死。编写您的服务,以便在重新启动时完成它的工作。
这足以猜测一天。