android 预装第三方apk的方法(非system priv-app)

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

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

1 pm.jar包中添加preinstall命令[ 这一步可以省略 可以直接使用pm.jar包中的install 命令 ]

修改: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/xbin/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)
一般开机广播之后 执行成功的时间由apk的大小而定 如果比较大的 可能需要10多秒才能安装完成.

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

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

#!/system/xbin/busybox sh

BUSYBOX="/system/xbin/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。

此外,要使init 进程能够启动自定义的Service 需要将系统的SELINUX关闭

diff --git a/android/system/core/init/init.cpp b/android/system/core/init/init.cpp
index 05c0c05..d0920f6 100644
--- a/android/system/core/init/init.cpp
+++ b/android/system/core/init/init.cpp
@@ -982,6 +982,7 @@ static void selinux_initialize(bool in_kernel_domain) {
         }

         bool is_enforcing = selinux_is_enforcing();
+        is_enforcing = 0;
         security_setenforce(is_enforcing);

         if (write_file("/sys/fs/selinux/checkreqprot", "0") == -1) {

所以,要预装apk,还需要将预装的第三方apk拷贝到/system/preinstall目录下, Android.mk写法模板


LOCAL_PATH := $(call my-dir)


#########################
include $(CLEAR_VARS)
LOCAL_MODULE := YourApk
LOCAL_MODULE_TAGS := optional
LOCAL_DEX_PREOPT :=false
LOCAL_CERTIFICATE := PRESIGNED
LOCAL_MODULE_PATH := $(TARGET_OUT)/preinstall
LOCAL_MODULE_CLASS := APPS
LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
include $(BUILD_PREBUILT) 

Reference :http://blog.csdn.net/fe421504975/article/details/8272663#

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值