预装第三方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目录下,这里就不多说了。

更多相关文章

  1. Android(安卓)P wakeup 亮屏流程
  2. 使用cocos compile -p android -m release 报错
  3. 〖Android〗代理与正常网络分开同步CyangenMod源码
  4. android异步操作类----AsyncTask
  5. Android在真机调试的设置方法
  6. Gradle Android最新自动化编译脚本教程
  7. WakeLock & WifiLock的实现
  8. 编译Android源码制作ROM,烧录
  9. Android学习【3】Android开发问题记录

随机推荐

  1. Android(安卓)Resource的使用和介绍
  2. Android 7.0新特性
  3. Android对话框Dialog,PopupWindow,Toast的
  4. Android 拨打电话功能
  5. Android获取点击屏幕的位置坐标
  6. imageView中图片各种比例类型的显示方式
  7. Android原生方法和Web JS互相调用-两种写
  8. Android:系统信息(内存、cpu、sd卡、电量、
  9. 【Android】android studio ndk使用例子
  10. Android 页面跳转(无/含有返回结果)