1, PM命令
命令格式:
pm <command>
命令列表:
命令
功能
實現方法
list packages
列舉app包信息
PMS.getInstalledPackages
install [options] <PATH>
安裝應用
PMS.installPackageAsUser
uninstall [options]<package>
卸載應用
IPackageInstaller.uninstall
enable <包名或組件名>
enable
PMS.setEnabledSetting
disable <包名或組件名>
disable
PMS.setEnabledSetting
hide <package>
隱藏應用
PMS.setApplicationHiddenSettingAsUser
unhide <package>
顯示應用
PMS.setApplicationHiddenSettingAsUser
get-install-location
獲取安裝位置
PMS.getInstallLocation
set-install-location
設置安裝位置
PMS.setInstallLocation
path <package>
查看App路徑
PMS.getPackageInfo
clear <package>
清空App數據
AMS.clearApplicationUserData
get-max-users
最大用戶數
UserManager.getMaxSupportedUsers
force-dex-opt <package>
dex優化
PMS.forceDexOpt
dump <package>
dump信息
AM.dumpPackageStateStatic
trim-caches <目標size>
緊縮cache目標大小
PMS.freeStorageAndNotify
2, 詳細參數
2.1 list packages
查看所有的package
list packages [options] <FILTER>
其中[options]參數:
-f: 顯示包名所關聯的文件;
-d: 只顯示disabled包名;
-e: 只顯示enabled包名;
-s: 只顯示系統包名;
-3: 只顯示第3方應用的包名;
-i: 包名所相應的installer;
-u: 包含uninstalled包名.
規律: disabled + enabled = 總應用個數; 系統 + 第三方 = 總應用個數。
比如:查看第3方應用:
pm list packages -3
又比如,查看已經被禁用的包名。(國內的廠商一般把google的服務禁用了)
pm list packages -d
<FILTER>參數:
當FILTER爲不爲空時,則只會輸出包名帶有FILTER字段的應用;當FILTER爲空時,則默認顯示所有滿足條件的應用。
比如,查看包名帶google字段的包名
pm list packages google
2.2 pm install
安裝應用
pm install [options] <PATH>
其中[options]參數:
-r: 覆蓋安裝已存在Apk,並保持原有數據;
-d: 運行安裝低版本Apk;
-t: 運行安裝測試Apk
-i : 指定Apk的安裝器;
-s: 安裝apk到共享快存儲,比如sdcard;
-f: 安裝apk到內部系統內存;
-l: 安裝過程,持有轉發鎖
-g: 准許Apk manifest中的所有權限;
<PATH>參數:
該參數是必須的,是指需要安裝的apk所在的路徑。
2.3 其他參數
pm list users //查看當前手機用戶
pm list libraries //查看當前設備所支持的庫
pm list features //查看系統所有的features
pm list instrumentation //所有測試包的信息
pm list permission-groups //查看所有的權限組
pm list permissions [options]<group> 查看權限
-g: 以組形式組織;
-f: 打印所有信息;
-s: 簡要信息;
-d: 只列舉危險權限;
-u: 只列舉用戶可見的權限。
3, 詳細流程
所有adb命令的pm方法最後都會通過Pm.java執行,然後大都會調用PMS的方法完成,至於android系統中的adb原理在此就不論述了。
PM的main方法如下,
public static void main(String[] args) {
int exitCode = 1;
try {
exitCode = new Pm().run(args);
} catch (Exception e) {
Log.e(TAG, "Error", e);
System.err.println("Error: " + e);
if (e instanceof RemoteException) {
System.err.println(PM_NOT_RUNNING_ERR);
}
}
System.exit(exitCode);
}
直接調用run方法,
public int run(String[] args) throws IOException, RemoteException {
boolean validCommand = false;
if (args.length < 1) {
return showUsage();
}
mUm = IUserManager.Stub.asInterface(ServiceManager.getService("user"));
mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
// 獲取PMS對象
if (mPm == null) {
System.err.println(PM_NOT_RUNNING_ERR);
return 1;
}
mInstaller = mPm.getPackageInstaller();
mArgs = args;
String op = args[0]; // 獲取指令
mNextArg = 1;
•••
if ("install".equals(op)) {
return runInstall();
}
•••
不同的指令分別對應不同的方法,例如,install命令會調用runInstall方法, runInstall方法如下,
private int runInstall() {
int installFlags = 0;
int userId = UserHandle.USER_ALL;
String installerPackageName = null;
String opt;
String originatingUriString = null;
String referrer = null;
String abi = null;
while ((opt=nextOption()) != null) {
if (opt.equals("-l")) {
installFlags |= PackageManager.INSTALL_FORWARD_LOCK;
} else if (opt.equals("-r")) {
installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
} else if (opt.equals("-i")) {
•••
LocalPackageInstallObserver obs = new LocalPackageInstallObserver();
try {
VerificationParams verificationParams = new VerificationParams(verificationURI,
originatingURI, referrerURI, VerificationParams.NO_UID, null);
mPm.installPackageAsUser(apkFilePath, obs.getBinder(), installFlags,
installerPackageName, verificationParams, abi, userId);
synchronized (obs) {
while (!obs.finished) {
try {
obs.wait();
} catch (InterruptedException e) {
}
}
if (obs.result == PackageManager.INSTALL_SUCCEEDED) {
System.out.println("Success");
return 0;
} else {
System.err.println("Failure ["
+ installFailureToString(obs)
+ "]");
return 1;
}
}
} catch (RemoteException e) {
System.err.println(e.toString());
System.err.println(PM_NOT_RUNNING_ERR);
return 1;
}
}
無論是哪一個install命令,最後都是調用PMS的installPackageAsUser方法進行apk的安裝。