Exported service does not require permission问题。
今天在编辑一个简单的aidl的例子的时候遇到的一个小问题。本来编辑完后准备运行,无意中看到AndroidManifest.xml有个警告,内容为“Exported service does not require permission”.配置文件代码如下:
1 <service android:name=".AidlService"> 2 <intent-filter > 3 <action android:name="com.example.myaidldemo.action.AIDL_SERVICE"/> 4 </intent-filter> 5 </service>
警告“Exported service does not require permission”的意思是“外部的service不需要权限”。既然不需要权限那么为什么还会有警告呢???在网上搜了一些此类问题,也没说为什么。不过倒是按照他们的方法解决了问题。那就是直接在service中设置exported属性为“false”,限制外界访问。问题就解决了。如下:
1 <service android:name=".AidlService" 2 android:exported="false"> 3 <intent-filter > 4 <action android:name="com.example.myaidldemo.action.AIDL_SERVICE"/> 5 </intent-filter> 6 </service>
其实回过头来想想,其实只是自己犯了个很弱智的问题,因为自己和很多遇到这种问题的人一样,那就是:理解错误!因为以前学习大家遇到的通常都是没有加权限而导致的问题,所以自然而然的想到没加权限会报错,无法访问之类的。但是这次遇到的是“外部的service不需要权限”,其意思是:外部的其他service根本不需要添加权限就能够轻易地访问我们编写的这个aidl,或者说这个service。这是出于安全性的考虑而给我们的警告。而不是告诉我们缺少相应的权限。自己傻傻的还想require这个单词是不是还有其他意思,会不会有“需要”的意思,查有道,没有。翻牛津。还是没有。最后甚至想是不是编辑文档的人写错了,把acquire错写成了require?最后才发现只是理解错了,习惯性思维犯的错。
那么,问题又来了,android:exported="false" 这句不是系统默认的吗?怎么还要自己手动加上?难道系统的默认值是“true”?api文档中这么说的:
android:exported Whether or not components of other applications can invoke the service or interact with it — " true" if they can, and " false" if not. When the value is " false", only components of the same application or applications with the same user ID can start the service or bind to it. The default value depends on whether the service contains intent filters. The absence of any filters means that it can be invoked only by specifying its exact class name. This implies that the service is intended only for application-internal use (since others would not know the class name). So in this case, the default value is "false". On the other hand, the presence of at least one filter implies that the service is intended for external use, so the default value is "true". This attribute is not the only way to limit the exposure of a service to other applications. You can also use a permission to limit the external entities that can interact with the service (see the permission attribute).
关键的一句是:
The default value depends on whether the service contains intent filters.
就是说默认值取决于该service是否包含intent过滤器filter。如果没有<intent-filter>,那只能通过指定其准确的类名访问。这意味着该service打算只在该应用内部使用(因为其他应用可能根本不知道这个类的名字)。在这种情况下,默认值是“false”,另一方面,当存在至少一个filter时,就表明该service打算供外部来使用,因此默认值是“true”。写到这里相信大家知道问什么了吧。原来api里面写的清清楚楚,看来api文档才是最好的资料这句话一点没错。是真正的宗。
其实还有一种解决的办法。那就是我们在这里自己定义一个权限。既然外部的其他service不需权限就能访问我们的service,那么我们自己定义权限,然后在需要调用该service的应用的配置文件里面声明调用该service的所需要的权限不就可以了吗?代码更改为:
1 <service android:name=".AidlService" 2 android:permission="com.exmaple.myaidldemo.myaidlservice"> 3 <intent-filter > 4 <action android:name="com.example.myaidldemo.action.AIDL_SERVICE"/> 5 </intent-filter> 6 </service>
然后在我们需要调用该service的其他应用的配置文件中加入下面这行代码:
<uses-permission android:name="com.exmaple.myaidldemo.myaidlservice"/>
现在为止我们就算是完整的就绝了遇到的问题了。最后感叹下,文档时个好东西啊。毕竟书里面不可能介绍的非常详细。只有多读文档才是正道。