在开始新的活动后的And​​r​​oid服务连接泄露 [英] Android service connection leaked after starting new activity

查看:99
本文介绍了在开始新的活动后的And​​r​​oid服务连接泄露的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图找出为什么我的服务是从我的应用程序泄漏。

该负责人的错误我得到的是,该服务没有注册任何更长的时间。

下面是什么在起作用: 我创建它创建了一个监听器,当监听器被触发的意图,开始另一个活动的服务组的服务。新的活动开始,并做它的事。

问题: 当我回到主屏幕,让我关闭该服务的选项,我得到我说previously这将导致一个IllegalArgumentException(当我试图解除未注册的服务)的错误。

任何帮助将是很大的AP preciated。这里是code为我服务。这是所有我包括在内,因为这似乎是问题的所在,但如果您需要任何更多的让我知道。

在此先感谢,这里是code。

 进口java.lang.ref.WeakReference;
进口的java.util.List;

进口android.app.Service;
进口android.content.Context;
进口android.content.Intent;
进口android.hardware.Sensor;
进口android.hardware.SensorEvent;
进口android.hardware.SensorEventListener;
进口android.hardware.SensorManager;
进口android.os.Binder;
进口android.os.IBinder;
进口android.util.Log;
进口android.widget.Toast;


公共类AccelService扩展服务
{
公共静态布尔收听= FALSE;
公共布尔callMade = FALSE;
私有静态传感器传感器;
私有静态的SensorManager ASensorManager;


私人SensorEventListener事件监听=
    新SensorEventListener(){

    私人浮X = 0;
    私人持股量Y = 0;
    私人持股量Z = 0;
    私人双人最大= 0;
    私人双力= 0;

    公共无效onAccuracyChanged(传感器传感器,诠释精度){}

    公共无效onSensorChanged(SensorEvent事件)
    {

        X = event.values​​ [0];
        Y = event.values​​ [1];
        Z = event.values​​ [2];
        力=的Math.sqrt(X * X + Y * Y + Z * Z);
        Log.i(本地服务,事件发生了:+力);


        如果(力> Main.dropValue)
        {
            onDrop(力);
        }
    }
};

公共无效startListener()
{
    ASensorManager =(的SensorManager)this.getSystemService(Context.SENSOR_SERVICE);
    名单<传感器>传感器= ASensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER);
    如果(sensors.size()大于0)
    {
        传感器= sensors.get(0);
        听= ASensorManager.registerListener(accelEventListener,传感器,SensorManager.SENSOR_DELAY_GAME);

    }
}


公共类AccelBinder< S>扩展粘合剂
{
    私人的WeakReference< S> MSERVICE;

    公共AccelBinder(S服务)
    {
        MSERVICE =新的WeakReference< S>(服务);
    }

    公共小号的getService()
    {
        返回mService.get();
    }
}

公众的IBinder mBinder;

@覆盖
公共无效的onCreate()
{
    startListener();

    mBinder =新AccelBinder< AccelService>(本);
}

公共布尔isListening()
{
    返回听;
}

/ * @覆盖
公共无效ONSTART(意向意图,诠释startId)
{
    Log.i(本地服务,收到的起始ID+ startId +:+意图);
} * /

@覆盖
公众诠释onStartCommand(意向意图,诠释标志,INT startId)
{
    Log.i(本地服务,收到的起始ID+ startId +:+意图);
    返回AccelService.START_STICKY;
}

@覆盖
公共无效的onDestroy()
{
    如果(听)
        的stopListening();
    mBinder = NULL;

    super.onDestroy();
}

公共无效onDrop(双力)
{
    如果(!callMade)
    {
        Toast.makeText(这一点,电话下降:+力,5000).show();
        意图I =新的意图(这一点,Next.class);
        i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        callMade =真;
        //的stopListening();
        //的onDestroy();
        //SafetyNet.ctxt.unbindService(SafetyNet.AccelWatch);
        this.startActivity(ⅰ);
    }
}

公共无效的stopListening()
{

    听= FALSE;
    尝试 {
        如果(ASensorManager = NULL和放大器;!&安培;!accelEventListener = NULL)
        {
            ASensorManager.unregisterListener(accelEventListener);
        }
    }赶上(例外五){}
}

@覆盖
公众的IBinder onBind(意向意图)
{
    返回mBinder;
}

}
 

解决方案

我不知道很多关于传感器,但你的服务是寻找pretty的好。

如果AccelBinder是一个内部类的服务使静态内部类,或者如我一般做的,一个单独的类干脆。静态内部类没有引用外部类。记住,你会泄漏你的活页夹。如果你的活页夹是一个非静态内部类,它有一个引用您的服务,这样会泄露也是如此。

我猜 - 就像真正的疯狂猜测 - 在没有任何code,有什么问题你的Activity生命周期的管理,你如何处理你的活页夹对象

事情要记住......

不要让一个静态引用您的Binder对象 - 他们是一次性的 - 每次你绑定时获得一个新的

请您结合对称的问候你的活动的生命周期。如果您的onCreate()绑定,解除绑定中的onDestroy()(或在onPause如果isFinishing())等,这是特别重要的,如果你不明白,与传感器手机的物理旋转破坏你的活动从头开始重新创建

您好像一共太喜欢了静态类变量。在Android中一成不变的东西往往会导致内存泄漏 - 如果你泄露什么都有上下文 - 事情就变得肮脏。如果你想保持相同的类的实例之间的状态,可以考虑使用preferences代替。

例如,

 私有静态传感器传感器;
私有静态的SensorManager ASensorManager;
 

扔掉这些东西拿走用途之间。

请确保你尤其不能保持一个静态引用您的服务在你的活动。服务是单身的Andr​​oid系统本身的性质,如果它仍在运行,你每次绑定时会得到同样的服务。指望你的服务在某个时间点被杀害的操作系统。写下您的服务,以便它是工作,如果它被重新启动。

这足以猜测一天。

I am trying to figure out why my service is leaking from my application.

The official error I am getting is that the Service is not registered any longer.

Here's what works: I create a service which creates a listener, when the listener is triggered the service sets of an intent to start another activity. The new activity begins and does its thing.

The problem: When I get back to a main screen which gives me the option to turn off the service, I get the error which I stated previously which causes an IllegalArgumentException (when I try to unbind the service which is not registered).

Any help would be greatly appreciated. Here is the code for my service. It is all I've included because this seems to be where the problem is, but if you need any more let me know.

Thanks in advance, here is the code.

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;
}

}

解决方案

I don't know much about Sensors, but your Service is looking pretty good.

IF AccelBinder is an inner class of your service make it a static inner class or, as I generally do, a separate class altogether. Static inner classes don't have a reference to the outer class. Remember you WILL leak your Binder. If your Binder is a non-static inner class, it has a reference to your Service so that will leak as well.

I am guessing - like really wildly guessing - in the absence of any code that there is something wrong with the management of your Activity life-cycle and how you handle your Binder objects.

Things to keep in mind....

Don't keep a static reference to your Binder object - they are disposable - get a new one each time you bind.

Keep your Binding symmetrical with regards to your Activity life-cycle. If you bind in onCreate(), unbind in onDestroy() ( or onPause if isFinishing() ) etc. This is particularly important if you don't understand that a physical rotation of a phone with Sensor destroys your Activity the recreates it from scratch.

You seem altogether too fond of "static" class variables. In Android static things tend to lead to memory leaks - and if what you leak has a Context - things get nasty. If you want to keep state between instances of the same class, consider using Preferences instead.

For example,

private static Sensor sensor;
private static SensorManager ASensorManager;

Throw these away between uses.

Make sure you especially are not keeping a static reference to your Service in your Activity. Services are singletons by the very nature of the Android, if it is still running you will get the same Service each time you bind. Count on your Service being killed by the OS at some point in time. Write your Service so that it does it's job if it is restarted afresh.

That's enough guessing for one day.

这篇关于在开始新的活动后的And​​r​​oid服务连接泄露的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆