Android原生是有應(yīng)用程序權(quán)限管理的,即是AppOps,只是Google把它默認(rèn)隱藏了。
本文對AppOps機制做一簡要的分析和描述。
1.AppOps簡介
AppOps全稱是Application Operations,類似我們平時常說的應(yīng)用程序的操作(權(quán)限)管理。AppOps是Google原生Android包含的功能,但是Google在每次版本更新時都會隱藏掉AppOps的入口。
在今年的Google IO大會上,Google透露Android M ( Android 6.0 )會加入Application Permission Manage的功能,該功能應(yīng)該就是基于AppOps實現(xiàn)的。
注意:AppOps雖然涵蓋了App的權(quán)限管理,但是Google原生的設(shè)計并不僅僅是對“權(quán)限”的管理,而是對App的“動作”的管理。我們平時講的權(quán)限管理多是針對具體的權(quán)限(App開發(fā)者在Manifest里申請的權(quán)限),而AppOps所管理的是所有可能涉及用戶隱私和安全的操作,包括access notification, keep weak lock,? activate vpn, display toast等等,有些操作是不需要Manifest里申請權(quán)限的。
2.功能效果
Setting UI:
AppOps的權(quán)限設(shè)置是在系統(tǒng)的Settings App里, Settings -> Security -> AppOps.
點擊某一app,可以查看該app的權(quán)限管理詳情


如前面所說,這一入口默認(rèn)已經(jīng)被google屏蔽了,而且屏蔽的手段越來越嚴(yán)格,很多輔助打開工具已經(jīng)不好用了~
但也有個別廠商重新打開了入口,也可能改了名字~
使用效果:
AppOps默認(rèn)給用戶提供了兩個設(shè)置選項:
允許該項權(quán)限/禁止該項權(quán)限
而其實代碼邏輯里,有三種可選項:
允許/禁止/提示
用戶選擇“提示”選項,則該app在執(zhí)行這一操作時,系統(tǒng)會給用戶相應(yīng)的提示,待用戶選擇后app繼續(xù)執(zhí)行。
我修改源碼把appops的“提示”設(shè)置項重新打開后,效果如下:
(禁止百度地圖的定位權(quán)限)

3.AppOps總體概覽
核心服務(wù):AppOpsService
系統(tǒng)服務(wù),系統(tǒng)啟動時該服務(wù)會啟動運行。
參考以下ActivityManagerService.java,ActivityManagerService啟動過程中:

配置文件:appops.xml? appops_policy.xml
Appops.xml位于/data/system/目錄下,存儲各個app的權(quán)限設(shè)置和操作信息。
Appops_policy.xml位于/system/etc/目錄下,該文件只在appops strict mode enable時才會存在和使用。(根據(jù)源碼的描述是這樣的,還沒有具體分析內(nèi)容)
API接口:AppOpsManager
AppOpsService實現(xiàn)了大部分的核心功能邏輯,但它不能被其他模塊直接調(diào)用訪問,而是通過AppOpsManager提供訪問接口。
UI層:AppOpsSummary,AppOpsCategory等
上傳UI顯示以及基本邏輯處理。
4.結(jié)構(gòu)圖
AppOps整體的工作框架基本如下:

Setting UI通過AppOpsManager與AppOpsService交互,給用戶提供入口管理各個app的操作。
AppOpsService具體處理用戶的各項設(shè)置,用戶的設(shè)置項存儲在/data/system/appops.xml文件中。
AppOpsService也會被注入到各個相關(guān)的系統(tǒng)服務(wù)中,進(jìn)行權(quán)限操作的檢驗。
各個權(quán)限操作對應(yīng)的系統(tǒng)服務(wù)(比如定位相關(guān)的Location Service,Audio相關(guān)的Audio Service等)中注入AppOpsService的判斷。如果用戶做了相應(yīng)的設(shè)置,那么這些系統(tǒng)服務(wù)就要做出相應(yīng)的處理。
(比如,LocationManagerSerivce的定位相關(guān)接口在實現(xiàn)時,會有判斷調(diào)用該接口的app是否被用戶設(shè)置成禁止該操作,如果有該設(shè)置,就不會繼續(xù)進(jìn)行定位。)
5.相關(guān)API接口
盡管在Android SDK里能夠看到部分AppOps的API接口,但是Google對此解釋的很清楚:
This API is not generally intended for third party application developers; most features are only available to system applications. Obtain an instance of it throughContext.getSystemServicewithContext.APP_OPS_SERVICE.
即是說,這些API不是讓第三方app使用的,而是供系統(tǒng)應(yīng)用調(diào)用的。
使用Android SDK開發(fā)應(yīng)用,如果要調(diào)用這些api的話,也會編譯不通過。
但是想使用的話,可以嘗試把Android源碼里AppOpsManager.java打包一下,把jar包導(dǎo)入自己的工程,就可以使用了。
部分重要的API接口如下:
int
checkOp(Stringop, int uid,StringpackageName)
Op對應(yīng)一個權(quán)限操作,該接口來檢測應(yīng)用是否具有該項操作權(quán)限。
int
noteOp(Stringop, int uid,StringpackageName)
和checkOp基本相同,但是在檢驗后會做記錄。
int
checkOpNoThrow(Stringop, int uid,StringpackageName)
和checkOp類似,但是權(quán)限錯誤,不會拋出SecurityException,而是返回AppOpsManager.MODE_ERRORED.
int
noteOpNoThrow(Stringop, int uid,StringpackageName)
類似noteOp,但不會拋出SecurityException。
void setMode( int code, int uid, String packageName, int mode)
這個是我們最需要的方法,改變app的權(quán)限設(shè)置,但偏偏被google隱藏了。
code代表具體的操作權(quán)限,mode代表要更改成的類型(允許/禁止/提示)
正常情況下(如果OEM廠商沒有做特殊處理),把AppOpsManager.java打包,引入jar包到工程內(nèi),是可以使用上述API接口的,
也即是可以自行設(shè)計UI,提供入口來改變app權(quán)限。
具體權(quán)限對應(yīng)的code,可以查看AppOpsManager.java源碼里的描述。
后續(xù)我也會對AppOps進(jìn)行更加詳細(xì)的分析和demo實現(xiàn)。