android绑定服务,退出activity报错" has leaked ServiceConnection"

结论现行:关闭activity的时候,需要解绑服务

1.应该重写onDestroy方法,取消绑定,这样就ok了。

2.可以通过广播机制。

Android】关于Activity Crash后,其调用绑定的Service依然在后台运行的问题????
我的Activity里同时使用了bindService和startService,调用了startService 之后就只能代码里调用stopService才能将其停掉,这样的后果就是一旦Activity崩溃(出错被系统kill等),Service还在后台运行,即便Crash了也会自动重启,曾尝试在Activity的OnDestroy方法里面调stopService,但是由于项目里Activity的退出逻辑比较复杂,不能在Activity的OnDestroy里这样做。于是,我的问题就来了:如何在Service里监听我绑定调用这个Service的Activity是被系统干掉还是我自己主动干掉的??有这样的监听方法吗???如果有的话,那么我就可以在Service里面通过该监听类的方法主动停掉自己,这样就不会导致我Activity被kill了后Service还在运行进而导致再次进入app的时候造成逻辑混乱。
问题可以总结为: 如何检测Activity是Crashed还是自己主动退出的?? Crash Detector谁做过。

采用广播的方法

在Service中动态注册广播registerReceiver(receiver, filter);

receiver = new InnerReceiver();
IntentFilter filter=new IntentFilter();
 filter.addAction(GlobalConsts.ACTION_PLAY);
registerReceiver(receiver, filter);

Service中自定义一个动态的内部的广播接收器InnerReceiver继承BroadcastReceiver
重写 onReceive方法,处理广播
String action=intent.getAction();
if(GlobalConsts.ACTION_STOP.equals(action)){
//销毁
stopSelf();}

Activity中OnDestroy发送广播 Intent intent
=new Intent(GlobalConsts.ACTION_STOP); sendBroadcast(intent); http://www.cnblogs.com/draem0507/archive/2013/05/25/3099461.html 这里有详细一点的说明 追问 OnDestroy是任何情况下Crash确定一定以及肯定会掉调用的吗? 比如因为系统内存不足被kill掉,或者死在加载的jni库中时都会调用OnDestroy吗? 就是Java层和c层都要保证的方法才行。 本回答由提问者推荐 抢首赞 评论 分享 举报 匿名用户 2014-01-10 也许你可以试试LocalService。 Local Service: Service is running in the same process as other components (i.e. activity that bound to it) from the same application, when this single application-scoped process has crashed or been killed, it is very likely that all components in this process (include the activity that bound to this service) are also destroyed. 收起追问追答� 追问 good suggestion, 但是我还是想知道怎样检测Activity的Crash. 追答 用UncaughtExceptionHandler来检测就好。 追问 不知道UncaughtExceptionHandler这个是否能检测任何情况下的crash? 它能检测JNI调用的C层出现的异常吗,还有由于内存泄露导致的内存不足而使程序挂掉的情况这个也能检测到吗?

问题出自

1.http://blog.sina.com.cn/s/blog_439f80c40101jkpr.html

2:https://www.runoob.com/w3cnote/android-tutorial-service-1.html

TestService2.java:

public class TestService2 extends Service {  
    private final String TAG = "TestService2";  
    private int count;  
    private boolean quit;  
      
    //定义onBinder方法所返回的对象  
    private MyBinder binder = new MyBinder();  
    public class MyBinder extends Binder  
    {  
        public int getCount()  
        {  
            return count;  
        }  
    }  
      
    //必须实现的方法,绑定改Service时回调该方法  
    @Override  
    public IBinder onBind(Intent intent) {  
        Log.i(TAG, "onBind方法被调用!");  
        return binder;  
    }  
  
    //Service被创建时回调  
    @Override  
    public void onCreate() {  
        super.onCreate();  
        Log.i(TAG, "onCreate方法被调用!");  
        //创建一个线程动态地修改count的值  
        new Thread()  
        {  
            public void run()   
            {  
                while(!quit)  
                {  
                    try  
                    {  
                        Thread.sleep(1000);  
                    }catch(InterruptedException e){e.printStackTrace();}  
                    count++;  
                }  
            };  
        }.start();  
          
    }  
      
    //Service断开连接时回调  
    @Override  
    public boolean onUnbind(Intent intent) {  
        Log.i(TAG, "onUnbind方法被调用!");  
        return true;  
    }  
      
    //Service被关闭前回调  
    @Override  
    public void onDestroy() {  
        super.onDestroy();  
        this.quit = true;  
        Log.i(TAG, "onDestroyed方法被调用!");  
    }  
      
    @Override  
    public void onRebind(Intent intent) {  
        Log.i(TAG, "onRebind方法被调用!");  
        super.onRebind(intent);  
    }  
}

在AndroidManifest.xml中对Service组件进行注册:

<service android:name=".TestService2" android:exported="false">  
        <intent-filter>  
            <action android:name="com.jay.example.service.TEST_SERVICE2"/>  
        </intent-filter>  
</service>

MainActivity.java:

public class MainActivity extends Activity {  
  
    private Button btnbind;  
    private Button btncancel;  
    private Button btnstatus;  
      
    //保持所启动的Service的IBinder对象,同时定义一个ServiceConnection对象  
    TestService2.MyBinder binder;  
    private ServiceConnection conn = new ServiceConnection() {  
          
        //Activity与Service断开连接时回调该方法  
        @Override  
        public void onServiceDisconnected(ComponentName name) {  
            System.out.println("------Service DisConnected-------");  
        }  
          
        //Activity与Service连接成功时回调该方法  
        @Override  
        public void onServiceConnected(ComponentName name, IBinder service) {  
            System.out.println("------Service Connected-------");  
            binder = (TestService2.MyBinder) service;  
        }  
    };  
      
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
        btnbind = (Button) findViewById(R.id.btnbind);  
        btncancel = (Button) findViewById(R.id.btncancel);  
        btnstatus  = (Button) findViewById(R.id.btnstatus);  
        final Intent intent = new Intent();  
        intent.setAction("com.jay.example.service.TEST_SERVICE2");  
        btnbind.setOnClickListener(new OnClickListener() {            
            @Override  
            public void onClick(View v) {  
                //绑定service  
                bindService(intent, conn, Service.BIND_AUTO_CREATE);                  
            }  
        });  
          
        btncancel.setOnClickListener(new OnClickListener() {  
            @Override  
            public void onClick(View v) {  
                //解除service绑定  
                unbindService(conn);                  
            }  
        });  
          
        btnstatus.setOnClickListener(new OnClickListener() {  
            @Override  
            public void onClick(View v) {  
                Toast.makeText(getApplicationContext(), "Service的count的值为:"  
                        + binder.getCount(), Toast.LENGTH_SHORT).show();  
            }  
        });  
    }  
}

运行截图:

点击锁定Service:

继续点击锁定:没任何变化

获取当前Service的状态:

解除绑定:

如果我们再绑定后直接关掉Activity的话会报错, 然后会自动调用onUnbind和onDestory方法!

 。。。 

从上面的运行结果验证了生命周期图中的:

使用BindService绑定Service,依次调用onCreate(),onBind()方法, 我们可以在onBind()方法中返回自定义的IBinder对象;再接着调用的是 ServiceConnection的onServiceConnected()方法该方法中可以获得 IBinder对象,从而进行相关操作;当Service解除绑定后会自动调用 onUnbind和onDestroyed方法,当然绑定多客户端情况需要解除所有 的绑定才会调用onDestoryed方法进行销毁哦!

原文地址:https://www.cnblogs.com/sunupo/p/15505557.html