今天在編輯一個簡單的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"/>
現在為止我們就算是完整的就絕了遇到的問題了。最后感嘆下,文檔時個好東西啊。畢竟書里面不可能介紹的非常詳細。只有多讀文檔才是正道。
