bindService:进程间绑定失败(魅族手机)

最近打算重新认识一下 Binder ,所以第一步就是熟练使用 AIDL 进行跨进程通信(简单来说就是远程 Service )。之后呢,当然是开始写 Demo ,然而巧了我用的测试手机是魅族手机,之后就尴尬了,每每客户端在绑定服务的时候就崩溃,一度怀疑自己的能力,找 log 发现还没有,没有。。。迫不得已之下,换了一台测试机,发现莫名其妙的通了,于是问了问度娘,度娘说:“魅族手机呀,你需要这样这样在那样。”
于是这篇文章就被你们看到了,,,
这里关于 AIDL 的代码我就不在叙述了,文末会留下链接,供大家下载。
在客户端绑定时的代码:

/**
* 这样写在 vivo,三星,一加,锤子(我就测了这么多机型)都是没问题的
* 但是在魅族手机上就会绑定失败,导致崩溃。
*/
Bundle args = new Bundle();
Intent intent = new Intent();
intent.setAction("MyService");
intent.setPackage("com.example.randy.observerdemo");
intent.putExtras(args);
bindService(intent, mServiceConnection, BIND_AUTO_CREATE);

之后改成了下面这段代码就OK了

// 项目名称,都是之前写Demo的时候建的,这次借用了一下,哈哈
Intent intent = new Intent();
ComponentName componentName = new ComponentName("com.example.randy.observerdemo", "com.example.randy.observerdemo.MyService");
intent.setComponent(componentName);
intent.setAction("MyService");
bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);

在这里用到了 ComponentName,顾名思义,就是组建名称,通过调用 Intent 中的 setComponent 方法,我们可以打开另外一个应用中的 Activity 或者服务。
实例化一个 ComponentName 需要两个参数,第一个参数是要启动应用的包名称,这个包名称是指 AndroidManifest 文件中列出的应用的包名称,如下图:

bindService:进程间绑定失败(魅族手机)_第1张图片
image.png

第二个参数是你要启动的 Activity 或者 Service 的全称(包名+类名),代码如上述第二段代码块。

注意:

如果你要的启动的其他应用的 Activity 不是该应用的入口 Activity,那么在清单文件中,该 Activity 节点一定要加上 android:exported="true",表示允许其他应用打开,对于所有的 Service,如果想从其他应用打开,也都要加上这个属性:

bindService:进程间绑定失败(魅族手机)_第2张图片
image.png

对于除了入口 Activity 之外的其他组件,如果不加这个属性,都会抛出 “java.lang.SecurityException: Permission Denial.....” 异常。
那么为什么入口 Activity 不用添加这个属性就可以被其他应用启动呢?我们来看一段入口 Activity 的注册代码:

        
            
                
 
                
            
        

入口 Activity 和普通 Activity 唯一不同的地方就是入口 Activity 多了一个过滤器,对于包含了过滤器的组件,意味着该组件可以提供给外部的其他应用来使用,它的 exported 属性默认为 true,相反,如果一个组件不包含任何过滤器,那么意味着该组件只能通过指定明确的类名来调用,也就是说该组件只能在应用程序的内部使用,在这种情况下,exported 属性的默认值是 false

最后,参考链接及项目地址:

关于ComponentName的使用
项目地址:
客户端代码
服务端代码

你可能感兴趣的:(bindService:进程间绑定失败(魅族手机))