android 预装第三方apk的方法

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

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

1 pm.jar包中添加preinstall命令

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

--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -106,6 +106,10 @@ public final class Pm {
             runInstall();
             return;
         }
+        if ("preinstall".equals(op)) {
+               preInstall();
+                       return;
+        }
 
         if ("uninstall".equals(op)) {
             runUninstall();
@@ -763,7 +767,50 @@ public final class Pm {
             System.err.println(PM_NOT_RUNNING_ERR);
         }
     }
-
+       private void preInstall() {
+                String path = nextArg();
+                int i;
+                
+                System.err.println("\t preInstall path: " + path);
+                if (path == null) {
+            System.err.println("Error: no package specified");
+            showUsage();
+            return;
+        }
+                               
+               File[] files = new File(path).listFiles();
+
+               for(File apkFilePath : files) {
+                       System.err.println("\tpkg: " + apkFilePath);
+                       PackageInstallObserver obs = new PackageInstallObserver();                      
+                       try {
+               mPm.installPackage(Uri.fromFile(apkFilePath), obs, 0,null);
+               System.err.println("\t pkg----1------: ");
+                               synchronized (obs) {
+                       while (!obs.finished) {
+                       try {
+                               System.err.println("\t pkg----2------: ");
+                               obs.wait();
+                               System.err.println("\t pkg----3------: ");
+                       } catch (InterruptedException e) {
+                               System.err.println("\t pkg----4------: ");
+                       }
+                       }
+                       if (obs.result == PackageManager.INSTALL_SUCCEEDED) {
+                       System.out.println("Success");
+                               } else {
+                       System.err.println("Failure ["
+                            + installFailureToString(obs.result)
+                            + "]");
+                       }
+               }
+               } catch (RemoteException e) {
+               System.err.println(e.toString());
+               System.err.println(PM_NOT_RUNNING_ERR);
+               }
+               }
+               System.err.println("\t preInstall path: " + path + " ok");      
+       }
     private void runInstall() {
         int installFlags = 0;
         String installerPackageName = null;

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

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

service  preinstall  /system/bin/busybox  sh  /system/bin/preinstall.sh
  user root
  group root
  disabled
  oneshot
on property:sys.boot_completed=1
    start preinstall
有了以上定义之后,当系统启动完成首,启动preinstall服务,该服务呢,

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

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

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

#!/system/bin/busybox sh

BUSYBOX="/system/bin/busybox"

if [ ! -e /data/system.notfirstrun ]; then	
    echo "do preinstall job"	

    /system/bin/sh /system/bin/pm preinstall /system/preinstall	
    $BUSYBOX touch /data/system.notfirstrun	
    echo "preinstall ok"
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)