Android之Lollipop DevicePolicyManager学习(上)
Android 5.0(lollipop)發布之后,看特性文檔增加了不少有趣的東西。
最近花了一些時間,研究了下其中Managed Profile的概念,簡稱MP,記錄下來作為一些經驗,有需要的同學請參考。
?
簡介
Managed Profile,簡稱被管理者賬戶。這個概念并不是什么新東西,因為早在4.2版本中,Android就引入了多用戶機制來解決平板使用上的問題。而如今5.0新加入的這個被管理者賬戶功能,可以理解成為是為了解決用戶本人對于應用進行分類的需求問題而做的細化吧。
?
存在于被管理者賬戶中的應用受制于主賬戶,也就是仍然處于機主本人的控制之下。但這些應用的存儲空間,以及應用的userID和PID都不同于主賬戶的同名應用。
?
這些在被管理者賬戶中的應用可以由機主進行各方面的限制,比如說控制這些應用不能訪問攝像頭——所有涉及到拍照部分的功能都開啟不了,再比如說控制某些特定應用的功能——比如說讓chrome的歷史記錄功能禁止使用。而所有的這些應用都與主賬戶中的應用隔離,這就意味著原本可能會被無故喚起的某些應用放到這里之后,它也再也不會被另一些流氓應用給后臺喚醒了。
?
前提條件
首先,你需要一臺安裝Android5.0及以上版本的手機,親兒子系列最好,因為不知道第三方ROM是否會將“加密”功能給閹割了。
開啟手機加密的方法為:
設置——安全——加密手機
?
一般來說,手機出廠設置是不默認加密的,需要用戶自己啟動才行。當然,也可以通過代碼來啟動該功能,具體如下:
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); }之后根據引導窗口則可以完成加密手機并設置Managed Profile的流程。
具體模塊設計相關
對手機加密完成,并生成Managed Profile賬戶之后,我考慮了以下幾個問題。
1.??????啟動MP賬戶的流程
在google給出的官方樣例中,啟動一個ManagedProfile已經有了一套成熟的方案。
具體如下:
a)????????判斷當前應用是否已經注冊為當前賬戶的賬戶所有者(profile owner)——可以理解是擁有某些高級權限,類似admin用戶。
b)????????如果不是,則參考加密的流程,發一個系統的intent啟動加密流程。
c)????????如果是,那么恭喜你,你已經處于一個MP中,并且擁有這個MP下的類管理者權限了。
?
參考google的官方樣例BasicManagedProfile即可。
為了方便后續描述,當前應用我簡稱為AdminApp好了。
?
2.??????如何添加現有應用至MP賬戶中。
一般來說,查詢當前系統中安裝的應用狀態Android已經有了非常方便的方式,通過PackageManager可以查到系統中安裝的各個包的信息總合,也可以指定特定的包名來查詢對應信息。
但是,這個在MP賬戶中是做不到的。
?
比如常見的getInstalledPackages(intflag)方法,雖然平時調用時僅使用參數flags。但從源碼來看,真實的被調用者其實是被隱藏的方法getInstalledPackages(int flags,int userId),暴露給我們的方法中,userId已經固定為當前的用戶ID。
再看一下PackageManager服務進程就能知道,真正在查詢安裝包信息時,該方法需要將userID作為校驗條件之一。通常一個Profile下對應的所有應用都有一個相同的userID,所以跨了Profile后就無法查詢主賬戶下的應用信息了。
所以在默認的MP賬戶中操作getInstalledPackages(),如果指明返回非系統應用,則只會返回當前應用本身,其他的三方應用是無法找到的。同樣,查找系統應用也只能查找到在MP賬戶中注冊的系統應用,沒有注冊的同樣也找不到。
?
因此,如果要添加相關應用至MP賬戶中,無法通過輪詢當前被管理者賬戶下所有的應用名稱來一一添加。目前可行的有兩種方法,一種是用包名字串來激活,另一種是從主賬戶AP來獲取包名激活。
?
其中,谷歌的官方demo BasicManagedProfile使用的第一種方法,這里先進行介紹這種方法。如何從主賬戶來獲取留在后面介紹。
?
還是以Chrome應用為例。
Chrome的包名是:com.android.chrome
?
通過isApplicationEnabled方法可以判斷當前這個應用并沒有在MP賬戶中。具體的原理就是剛才所說的userID隔離后的查詢的結果。
/** * 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對已知包名的系統應用,提供了將其重新安裝到被管理者賬戶中的方法供AdminApp來調用。即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權限的系統應用有效,如果你傳入的第三方應用包名,那么肯定會拋出IllegalArgumentException:Only system apps canbe enabled this way異常。
即使通過反射直接調用PackageManager服務的installExistingPackageAsUser(packageName,userID)方法,也會因為權限的問題而失敗。
?
所以,手動添加第三方應用到MP中目前我是沒有找到更好的方法,只能在建立MP之后重新安裝指定的第三方應用,此時,MP中會同樣安裝一份拷貝版本。
?
通過AdminApp調用enableSystemApp使能的系統應用會出現在被管理者賬戶中,作為Launch的圖標顯示出來。
:
同樣,如果不希望該應用顯示在MP中,可以用AdminApp調用publicboolean setApplicationHidden (ComponentName admin, String packageName, booleanhidden)來隱藏。
簡而言之,通過上述的操作,可以將一個系統應用重新安裝到被管理者賬戶中。之后,你可以對這個被管理者賬戶中的應用進行限制操作了。
總結
以上是生活随笔為你收集整理的Android之Lollipop DevicePolicyManager学习(上)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: RC4加密解密java算法
- 下一篇: Android之Lollipop Dev