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

Kev*_*vin 2 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;
}

}
Run Code Online (Sandbox Code Playgroud)

小智 7

我对传感器了解不多,但您的服务看起来很不错.

如果AccelBinder是你的服务的内部类,那么它就是一个静态的内部类,或者像我通常那样,完全是一个单独的类.静态内部类没有对外部类的引用.记住你会泄漏你的活页夹.如果您的Binder是非静态内部类,它会引用您的服务,以便泄漏.

我猜 - 就像真的疯狂猜测 - 在没有任何代码的情况下,你的Activity生命周期管理有问题,以及你如何处理你的Binder对象.

要记住的事情....

不要对Binder对象保持静态引用 - 它们是一次性的 - 每次绑定时都会获得一个新的引用.

保持你的Binding在你的Activity生命周期中是对称的.如果你在onCreate()中绑定,则在onDestroy()中取消绑定(或者如果isFinishing()则取消on),等等.如果你不明白带有传感器的手机的物理旋转会破坏你的活动从头开始重新创建它,这一点尤其重要. .

你似乎完全喜欢"静态"类变量.在Android静态中,事物往往会导致内存泄漏 - 如果你泄漏的内容有上下文 - 事情会变得很糟糕.如果要在同一类的实例之间保持状态,请考虑使用"首选项".

例如,

private static Sensor sensor;
private static SensorManager ASensorManager;
Run Code Online (Sandbox Code Playgroud)

在使用之间扔掉它们.

确保您特别没有在活动中保留对服务的静态引用.服务是Android的本质,如果它仍在运行,你每次绑定时都会得到相同的服务.依靠您的服务在某个时间点被操作系统杀死.编写您的服务,以便在重新启动时完成它的工作.

这足以猜测一天了.