android 预装第三方apk的方法

本文详细解析了如何实现预装第三方apk的功能,包括在PM命令中添加preinstall命令,修改Pm.java文件,以及在init.rc中定义预安装服务。同时,通过执行preinstall.sh脚本,调用pmpreinstall命令完成预装过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        预装第三方apk,并不是装到/system/app下,而是装到/data/app/下,这两者是有区别是,

前者用户是不可以卸载的,后者用户可以卸载,我们现在实现的就是后者。

1 pm.jar包中添加preinstall命令

修改:frameworks/base/cmds/pm/src/com/android/commands/pm/pm.java

[java]  view plain copy
  1. --- a/cmds/pm/src/com/android/commands/pm/Pm.java  
  2. +++ b/cmds/pm/src/com/android/commands/pm/Pm.java  
  3. @@ -106,6 +106,10 @@ public final class Pm {  
  4.              runInstall();  
  5.              return;  
  6.          }  
  7. +        if ("preinstall".equals(op)) {  
  8. +               preInstall();  
  9. +                       return;  
  10. +        }  
  11.    
  12.          if ("uninstall".equals(op)) {  
  13.              runUninstall();  
  14. @@ -763,7 +767,50 @@ public final class Pm {  
  15.              System.err.println(PM_NOT_RUNNING_ERR);  
  16.          }  
  17.      }  
  18. -  
  19. +       private void preInstall() {  
  20. +                String path = nextArg();  
  21. +                int i;  
  22. +                  
  23. +                System.err.println("\t preInstall path: " + path);  
  24. +                if (path == null) {  
  25. +            System.err.println("Error: no package specified");  
  26. +            showUsage();  
  27. +            return;  
  28. +        }  
  29. +                                 
  30. +               File[] files = new File(path).listFiles();  
  31. +  
  32. +               for(File apkFilePath : files) {  
  33. +                       System.err.println("\tpkg: " + apkFilePath);  
  34. +                       PackageInstallObserver obs = new PackageInstallObserver();                        
  35. +                       try {  
  36. +               mPm.installPackage(Uri.fromFile(apkFilePath), obs, 0,null);  
  37. +               System.err.println("\t pkg----1------: ");  
  38. +                               synchronized (obs) {  
  39. +                       while (!obs.finished) {  
  40. +                       try {  
  41. +                               System.err.println("\t pkg----2------: ");  
  42. +                               obs.wait();  
  43. +                               System.err.println("\t pkg----3------: ");  
  44. +                       } catch (InterruptedException e) {  
  45. +                               System.err.println("\t pkg----4------: ");  
  46. +                       }  
  47. +                       }  
  48. +                       if (obs.result == PackageManager.INSTALL_SUCCEEDED) {  
  49. +                       System.out.println("Success");  
  50. +                               } else {  
  51. +                       System.err.println("Failure ["  
  52. +                            + installFailureToString(obs.result)  
  53. +                            + "]");  
  54. +                       }  
  55. +               }  
  56. +               } catch (RemoteException e) {  
  57. +               System.err.println(e.toString());  
  58. +               System.err.println(PM_NOT_RUNNING_ERR);  
  59. +               }  
  60. +               }  
  61. +               System.err.println("\t preInstall path: " + path + " ok");        
  62. +       }  
  63.      private void runInstall() {  
  64.          int installFlags = 0;  
  65.          String installerPackageName = null;  

2 在init.rc中定义一个preinstall服务

     该服务去执行一个脚本,在脚本里面调用pm preinstall命令。

[plain]  view plain copy
  1. service  preinstall  /system/bin/busybox  sh  /system/bin/preinstall.sh  
  2.   user root  
  3.   group root  
  4.   disabled  
  5.   oneshot  
  6. on property:sys.boot_completed=1  
  7.     start preinstall  
有了以上定义之后,当系统启动完成首,启动preinstall服务,该服务呢,

将要执行/system/bin/preinstall.sh脚本完成预装动作,这个服务只能执行一次(oneshot)

好了,下面看看执行pm preinstall命令的脚本

3 执行执行pm preinstall命令的脚本preinstall.sh

[plain]  view plain copy
  1. #!/system/bin/busybox sh  
  2.   
  3. BUSYBOX="/system/bin/busybox"  
  4.   
  5. if [ ! -e /data/system.notfirstrun ]; then    
  6.     echo "do preinstall job"      
  7.   
  8.     /system/bin/sh /system/bin/pm preinstall /system/preinstall   
  9.     $BUSYBOX touch /data/system.notfirstrun   
  10.     echo "preinstall ok"  
  11. fi  

将  /system/preinstall作为参数(其实就是预装apk的目录),传给pm,将该目录下的apk一次预装。

pm preinstall  最终将调用到frameworks/base/cmds/pm/src/com/android/commands/pm/pm.java

文件中,一次安装apk。

所以,要预装apk,还需要将预装的第三方apk拷贝到/system/preinstall目录下,这里就不多说了。

### 如何在Android设备上使用Shell命令处理第三方APK #### 使用ADB Shell安装和管理APK 对于在Android设备上通过Shell命令操作第三方APK,主要依赖于`adb shell`工具。此工具允许开发者向连接的Android设备发送各种指令。 可以利用`pm install`命令来安装APK文件: ```bash adb shell pm install /path/to/app.apk ``` 卸载应用程序则可以通过下面这条命令实现[^1]: ```bash adb shell pm uninstall com.example.app ``` 查询已安装的应用程序列表及其包名信息也十分简单: ```bash adb shell pm list packages -f | grep appname ``` 上述命令中的`grep appname`部分用于过滤特定名称的应用;如果不加这个条件,则会返回所有已知应用的信息。 #### 修改或替换现有APK 如果想要更新已经存在于系统中的某个预装APP版本,除了直接覆盖原路径下的`.apk`外,还可以先将其删除再重新部署新版本。需要注意的是,在某些情况下可能还需要重启设备才能使更改生效。 另外一种方式是借助`apktool`反编译并编辑资源文件后再打包回原状,最后按照前述方法进行重装[^2]。 #### 执行自定义脚本或命令 当涉及到更复杂的场景比如启动服务、传递参数给后台进程等动作时,可以在代码层面集成相应的逻辑,例如MTK平台上的做法是在合适的位置加入必要的shell语句以完成指定任务[^3]。 此外,也可以编写独立的sh脚本来封装一系列连续的操作步骤,从而简化日常维护工作量。不过这通常适用于拥有root权限的情况之下。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值