2

我试图弄清楚为什么我的服务从我的应用程序中泄漏。

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

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

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

}
4

1 回答 1

7

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

如果 AccelBinder 是您服务的内部类,则使其成为静态内部类,或者像我通常所做的那样,完全是一个单独的类。静态内部类没有对外部类的引用。记住你会泄露你的活页夹。如果您的 Binder 是一个非静态内部类,它具有对您的 Service 的引用,因此也会泄漏。

我在猜测 - 就像非常疯狂地猜测一样 - 在没有任何代码的情况下,您的 Activity 生命周期的管理以及您如何处理您的 Binder 对象存在问题。

要记住的事情......

不要保留对 Binder 对象的静态引用——它们是一次性的——每次绑定时都要获取一个新的。

保持 Binding 与 Activity 生命周期对称。如果您在 onCreate() 中绑定,在 onDestroy() 中取消绑定(如果 isFinishing() 则为 onPause)等。如果您不了解带有传感器的手机的物理旋转会破坏您的 Activity 并从头开始重新创建它,这一点尤其重要.

您似乎太喜欢“静态”类变量了。在 Android 中,静态的东西往往会导致内存泄漏——如果你泄漏的东西有一个上下文——事情会变得很糟糕。如果您想在同一类的实例之间保持状态,请考虑改用 Preferences。

例如,

private static Sensor sensor;
private static SensorManager ASensorManager;

在使用之间扔掉这些。

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

这足以猜测一天。

于 2010-12-21T10:07:55.570 回答