android 预装第三方apk的方法(非system priv-app)
16lz
2021-01-24
预装第三方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#
更多相关文章
- Android(安卓)adb的使用略解
- Android基于Linux Eclipse开发环境配置
- [Android]使用原生Menu的一些小Tip
- android自定义menu,PopUpWindow弹出菜单
- 替换Android控件默认样式 (例子:自定义进度条)
- adb:) adb push、pull、logcat and etc
- 静默安装实现方法
- Android(安卓)ADB详解
- Android(安卓)ScrollView 中放入 ImageView 的出现上下空白