启动新活动后,Android服务连接泄露

时间:2010-12-21 07:22:46

标签: android android-service

我试图找出我的服务从我的应用程序泄漏的原因。

我得到的官方错误是该服务不再注册。

这是有效的: 我创建了一个创建监听器的服务,当监听器被触发意图启动另一个活动的服务集时。新活动开始并做到了。

问题: 当我回到主屏幕,让我可以选择关闭服务时,我得到了我之前说过的错误,导致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;
}

}

1 个答案:

答案 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的本质,如果它仍在运行,你每次绑定时都会得到相同的服务。依靠您的服务在某个时间点被操作系统杀死。编写您的服务,以便在重新启动时完成它的工作。

这足以猜测一天。