Android之Lollipop DevicePolicyManager学习(上)
Android 5.0(lollipop)發(fā)布之后,看特性文檔增加了不少有趣的東西。
最近花了一些時間,研究了下其中Managed Profile的概念,簡稱MP,記錄下來作為一些經(jīng)驗,有需要的同學(xué)請參考。
?
簡介
Managed Profile,簡稱被管理者賬戶。這個概念并不是什么新東西,因為早在4.2版本中,Android就引入了多用戶機制來解決平板使用上的問題。而如今5.0新加入的這個被管理者賬戶功能,可以理解成為是為了解決用戶本人對于應(yīng)用進(jìn)行分類的需求問題而做的細(xì)化吧。
?
存在于被管理者賬戶中的應(yīng)用受制于主賬戶,也就是仍然處于機主本人的控制之下。但這些應(yīng)用的存儲空間,以及應(yīng)用的userID和PID都不同于主賬戶的同名應(yīng)用。
?
這些在被管理者賬戶中的應(yīng)用可以由機主進(jìn)行各方面的限制,比如說控制這些應(yīng)用不能訪問攝像頭——所有涉及到拍照部分的功能都開啟不了,再比如說控制某些特定應(yīng)用的功能——比如說讓chrome的歷史記錄功能禁止使用。而所有的這些應(yīng)用都與主賬戶中的應(yīng)用隔離,這就意味著原本可能會被無故喚起的某些應(yīng)用放到這里之后,它也再也不會被另一些流氓應(yīng)用給后臺喚醒了。
?
前提條件
首先,你需要一臺安裝Android5.0及以上版本的手機,親兒子系列最好,因為不知道第三方ROM是否會將“加密”功能給閹割了。
開啟手機加密的方法為:
設(shè)置——安全——加密手機
?
一般來說,手機出廠設(shè)置是不默認(rèn)加密的,需要用戶自己啟動才行。當(dāng)然,也可以通過代碼來啟動該功能,具體如下:
private voidregisterPovisionManagerProfile() { if (null== this) { return; } Intentintent = new Intent(ACTION_PROVISION_MANAGED_PROFILE); intent.putExtra(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME, this.getApplicationContext().getPackageName()); if(intent.resolveActivity(this.getPackageManager()) != null) { startActivityForResult(intent, REQUEST_PROVISION_MANAGED_PROFILE); this.finish(); } else { Toast.makeText(this, "Device provisioning is not enabled.Stopping.", Toast.LENGTH_SHORT).show(); } } @Override public voidonActivityResult(int requestCode, int resultCode, Intent data) { if(requestCode == REQUEST_PROVISION_MANAGED_PROFILE) { if(resultCode == Activity.RESULT_OK) { Toast.makeText(getApplicationContext(), "Provisioning done.",Toast.LENGTH_SHORT).show(); }else { Toast.makeText(getApplicationContext(), "Provisioningfailed.", Toast.LENGTH_SHORT).show(); } return; } super.onActivityResult(requestCode, resultCode, data); }之后根據(jù)引導(dǎo)窗口則可以完成加密手機并設(shè)置Managed Profile的流程。
具體模塊設(shè)計相關(guān)
對手機加密完成,并生成Managed Profile賬戶之后,我考慮了以下幾個問題。
1.??????啟動MP賬戶的流程
在google給出的官方樣例中,啟動一個ManagedProfile已經(jīng)有了一套成熟的方案。
具體如下:
a)????????判斷當(dāng)前應(yīng)用是否已經(jīng)注冊為當(dāng)前賬戶的賬戶所有者(profile owner)——可以理解是擁有某些高級權(quán)限,類似admin用戶。
b)????????如果不是,則參考加密的流程,發(fā)一個系統(tǒng)的intent啟動加密流程。
c)????????如果是,那么恭喜你,你已經(jīng)處于一個MP中,并且擁有這個MP下的類管理者權(quán)限了。
?
參考google的官方樣例BasicManagedProfile即可。
為了方便后續(xù)描述,當(dāng)前應(yīng)用我簡稱為AdminApp好了。
?
2.??????如何添加現(xiàn)有應(yīng)用至MP賬戶中。
一般來說,查詢當(dāng)前系統(tǒng)中安裝的應(yīng)用狀態(tài)Android已經(jīng)有了非常方便的方式,通過PackageManager可以查到系統(tǒng)中安裝的各個包的信息總合,也可以指定特定的包名來查詢對應(yīng)信息。
但是,這個在MP賬戶中是做不到的。
?
比如常見的getInstalledPackages(intflag)方法,雖然平時調(diào)用時僅使用參數(shù)flags。但從源碼來看,真實的被調(diào)用者其實是被隱藏的方法getInstalledPackages(int flags,int userId),暴露給我們的方法中,userId已經(jīng)固定為當(dāng)前的用戶ID。
再看一下PackageManager服務(wù)進(jìn)程就能知道,真正在查詢安裝包信息時,該方法需要將userID作為校驗條件之一。通常一個Profile下對應(yīng)的所有應(yīng)用都有一個相同的userID,所以跨了Profile后就無法查詢主賬戶下的應(yīng)用信息了。
所以在默認(rèn)的MP賬戶中操作getInstalledPackages(),如果指明返回非系統(tǒng)應(yīng)用,則只會返回當(dāng)前應(yīng)用本身,其他的三方應(yīng)用是無法找到的。同樣,查找系統(tǒng)應(yīng)用也只能查找到在MP賬戶中注冊的系統(tǒng)應(yīng)用,沒有注冊的同樣也找不到。
?
因此,如果要添加相關(guān)應(yīng)用至MP賬戶中,無法通過輪詢當(dāng)前被管理者賬戶下所有的應(yīng)用名稱來一一添加。目前可行的有兩種方法,一種是用包名字串來激活,另一種是從主賬戶AP來獲取包名激活。
?
其中,谷歌的官方demo BasicManagedProfile使用的第一種方法,這里先進(jìn)行介紹這種方法。如何從主賬戶來獲取留在后面介紹。
?
還是以Chrome應(yīng)用為例。
Chrome的包名是:com.android.chrome
?
通過isApplicationEnabled方法可以判斷當(dāng)前這個應(yīng)用并沒有在MP賬戶中。具體的原理就是剛才所說的userID隔離后的查詢的結(jié)果。
/** * Checks if the application is availablein this profile. * * @param packageName The package name * @return True if the application isavailable in this profile. */ private boolean isApplicationEnabled(String packageName) { … }Android對已知包名的系統(tǒng)應(yīng)用,提供了將其重新安裝到被管理者賬戶中的方法供AdminApp來調(diào)用。即public void enableSystemApp (ComponentName admin, StringpackageName)。
???????? 具體的使用流程可以參考demo中的代碼段:
/** * Enables or disables the specified app in this profile. * * @param packageName The package name of the target app. * @param enabled Pass true toenable the app. */ private voidsetAppEnabled(String packageName, boolean enabled) { }需要注明的一點是,這個方法只針對擁有INSTALL_PACKAGES權(quán)限的系統(tǒng)應(yīng)用有效,如果你傳入的第三方應(yīng)用包名,那么肯定會拋出IllegalArgumentException:Only system apps canbe enabled this way異常。
即使通過反射直接調(diào)用PackageManager服務(wù)的installExistingPackageAsUser(packageName,userID)方法,也會因為權(quán)限的問題而失敗。
?
所以,手動添加第三方應(yīng)用到MP中目前我是沒有找到更好的方法,只能在建立MP之后重新安裝指定的第三方應(yīng)用,此時,MP中會同樣安裝一份拷貝版本。
?
通過AdminApp調(diào)用enableSystemApp使能的系統(tǒng)應(yīng)用會出現(xiàn)在被管理者賬戶中,作為Launch的圖標(biāo)顯示出來。
:
同樣,如果不希望該應(yīng)用顯示在MP中,可以用AdminApp調(diào)用publicboolean setApplicationHidden (ComponentName admin, String packageName, booleanhidden)來隱藏。
簡而言之,通過上述的操作,可以將一個系統(tǒng)應(yīng)用重新安裝到被管理者賬戶中。之后,你可以對這個被管理者賬戶中的應(yīng)用進(jìn)行限制操作了。
總結(jié)
以上是生活随笔為你收集整理的Android之Lollipop DevicePolicyManager学习(上)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: RC4加密解密java算法
- 下一篇: Android之Lollipop Dev