预装第三方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  oneshoton 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 shBUSYBOX="/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.cppindex 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 := YourApkLOCAL_MODULE_TAGS := optionalLOCAL_DEX_PREOPT :=falseLOCAL_CERTIFICATE := PRESIGNEDLOCAL_MODULE_PATH := $(TARGET_OUT)/preinstallLOCAL_MODULE_CLASS := APPSLOCAL_SRC_FILES := $(LOCAL_MODULE).apkinclude $(BUILD_PREBUILT) 

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

更多相关文章

  1. Android(安卓)adb的使用略解
  2. Android基于Linux Eclipse开发环境配置
  3. [Android]使用原生Menu的一些小Tip
  4. android自定义menu,PopUpWindow弹出菜单
  5. 替换Android控件默认样式 (例子:自定义进度条)
  6. adb:) adb push、pull、logcat and etc
  7. 静默安装实现方法
  8. Android(安卓)ADB详解
  9. Android(安卓)ScrollView 中放入 ImageView 的出现上下空白

随机推荐

  1. SQL查询语句行转列横向显示实例解析
  2. Ubuntu 14.04下mysql安装配置教程
  3. SQL Server阻止保存修改表结构的解决方法
  4. SQL恢复master数据库方法 只有mdf文件的
  5. Oracle、MySQL和SqlServe三种数据库分页
  6. Windows2012配置SQLServer2014AlwaysOn的
  7. SQLServer中的触发器基本语法与作用
  8. SQLserver2014(ForAlwaysOn)安装图文教程
  9. sqlserver 因为选定的用户拥有对象,所以无
  10. SQL Server删除表及删除表中数据的方法