NOTE: attach of thread 'Binder_3' failed 的调试和解决

        近来一直还是在做Camera的应用调试,在调试过程中出现了这样一个问题:

        因为目前在做的Camera应用需要做到后台开启并保持录像的功能,因此所有的Camera操作都选择了在另外一个独立的Service中完成,包括Camera对象的初始化,拍照参数的设置,预览参数的设置,录像的参数设置等等都在Service中完成。之所以选择Service显而易见也是为了能保持后台录像的功能。那么说到Service的话就必须说到Service的开启和关闭了,一般的用法都会推荐 

                         context.startService(Intent)和stopService; 或者

                        context.bindService()和context.unbindService()

                       但是这两种方式分别会有各自的优点,恰好我所需要达到的目的是两者结合才能实现的,于是我的选择是两者结合来用。

                       我的调用顺序为先StartService,然后bindService。然后在退出Activity的同时去判断是否正在录像,如果正在录像则转为后台录像模式。否则直接finish Activity释放Service,按这个思路做完功能还算正常,但是出现一个问题。

                      首先讲下程序框架,首先是主Activity会有预览界面以及三个button分别为拍照,录像和文件预览。其中文件预览为单独的一个Activity来查看录像文件和拍照的图片文件。问题就出在录像过程中跳转到文化间预览的Activity然后再回退到主Activity,此时录像正常。接着我停止录像试图退出应用,然后问题出现了,我是直接操作的BACK键去退出应用,并且Back键的处理为释放服务finish程序。代码如下

                    

	                Intent exitIntent = new Intent(getApplicationContext(),CameraService.class);
			stopService(exitIntent);
                        unBindPlayerService();CameraActivity.this.finish();

 
                      开始看似没有什么问题,但是Activity在响应的时候却出现了回退到了停止录像前也就是刚从文件预览界面回来时的画面,并且画面不再刷新。紧接着我试图继续back来退出应用,同样失败了。最终看了很多遍log后,感觉从文件预览界面回退时的操作应该有问题,于是看代码,回退到主Activity的代码如下 

                                                           

 	public void toPreviewUI(){
		Intent intent = new Intent(this, CameraActivity.class);
		intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
		startActivity(intent);
		this.finish();
	       }
                       最后问题锁定在回退时的Flags设置,不应该采用FLAG_ACTIVITY_NEW_TASK,而是采用FLAG_ACTIVITY_CLEAR_TOP

                       简单的说明下两者的区别,

                      FLAG_ACTIVITY_NEW_TASK
                      设置此状态,记住以下原则,首先会查找是否存在和被启动的Activity具有相同的亲和性的任务栈(即taskAffinity,注意同一个应用程序中的activity的亲和性一样,所  以下面的a情况会在同一个栈中,前面这句话有点拗口,请多读几遍),如果有,刚直接把这个栈整体移动到前台,并保持栈中的状态不变,即栈中的activity顺序不变,如果没有,则新建一个栈来存放被启动的activity。

                      FLAG_ACTIVITY_CLEAR_TOP
                      我们知道Android的窗口类提供了历史栈,我们可以通过stack的原理来巧妙的实现,这里我们在D窗口打开A窗口时在Intent中直接加入标志Intent.FLAG_ACTIVITY_CLEAR_TOP,再次开启A时将会清除该进程空间的所有Activity。 

                     这样解释可能就可以说明问题了,我们开始的back是执行了回退到历史栈中的一个Activity状态了,所以界面不会再刷新,只有继续back才可能找到栈底的Activity并退出,但是问题又出现了。就是程序无法退出,找了好久log终于发现了这个地方

                    I/AndroidRuntime( 3808): NOTE: attach of thread 'Binder_3' failed

                     可以看到是以为内Service的bind操作出现了问题,导致Service无法正常释放,Acitivity无法finish。于是继续研究Service的启动和关闭相关的东西,期间查了不少资料也看过不少达人的blog最终找到了办法解决。

                    上述两种启动Servidce的方法如果混合用的话最好是保证两种方法操作的service对象统一,且均要进行停止service的操作才可以完整的释放service。同时bind的方法在所bind的Activity在finish的时候会自动的unbind释放service。
              此处在代码中有个差别是在启动的时候
          getApplicationContext().startService(service);
bindPlayerService();
             是首先startserice然后bind的,但是后面的finish操作却是如此
                stopService(exitIntent);
                unBindPlayerService();
              可以看到此处的调用直接是stopservice了,并未获取context对象,经过验证恰好是这个地方造成了后面service释放的异常。可能此处不会导致前面说的finish后回到之前正在录像的界面不刷新,但是造成了后面back键无响应程序无法退出的问题。 因此改为
getApplicationContext().stopService(exitIntent);
unBindPlayerService();
              跟开启服务的操作保持一致,此时服务释放异常解决。重点却是一个操作对象的不统一造成的,至于更深层次的原因现在暂时无法得知,只能等以后有能力再来做研究了。到此问题解决。耗了3天的问题终于搞定,着实不易。

               

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值