处理Third App

一、安装预置应用方法

这里提供一个思路,把预留应用放在system/third-app下,然后在第一次开机的时候把这些应用copy到data/app下,当然要在PKMS扫描data/app之前,这样第一次开机的时候就能安装上这些应用了。因为应用在data/app下也能删除。因为应用在system/third-app中也有,而恢复出厂设置的时候system的目录不会清空。在恢复出厂设置后,还会把这些应用copy到data/app下(恢复出厂设置开机等于第一次开机),下面我们看下如何实现。

先看下apk的编译时放在了third_app下,

  1. include $(CLEAR_VARS)  
  2. LOCAL_MODULE_PATH := $(TARGET_OUT)/third_app  
  3. LOCAL_MODULE :MobileMusic  
  4. LOCAL_MODULE_TAGS :optional  
  5. LOCAL_MODULE_CLASS :APPS  
  6. LOCAL_SRC_FILES := $(LOCAL_MODULE).apk  
  7. LOCAL_CERTIFICATE :PRESIGNED  
  8. include $(BUILD_PREBUILT)  

功能如下,就是把system/third-app下面的apk复制到data/app, 但是在哪里调用这个函数呢?

  1. //install the third apps when system is first boot  
  2. private void installThirdApps(){  
  3.     //the source directory not exists  
  4.     File storeDir = new File("/system/third_app");  
  5.     if(!storeDir.exists()){  
  6.         Log.e(TAG,"/system/third_app is not exist");  
  7.         return;  
  8.     }  
  9.   
  10.     //get the apk files in /system/third_app  
  11.     String apkFilesNames[] = storeDir.list();  
  12.     if(apkFilesNames == null){  
  13.         Log.e(TAG,"apk file name is null");  
  14.         return;  
  15.     }  
  16.   
  17.     //copy the apk files to /data/app  
  18.     boolean installSucc = false;  
  19.     for(int i = 0; i < apkFilesNames.length; i++){  
  20.         //Uri srcFileUri = Uri.parse(storeDir+"/"+apkFilesNames[i]);  
  21.         File srcFile = new File("/system/third_app",apkFilesNames[i]);  
  22.         Log.e(TAG,"srcFile="+srcFile);  
  23.         File destFile = new File("/data/app",apkFilesNames[i]);  
  24.         Log.e(TAG,"destFile="+destFile.toString());  
  25.         boolean installResult = copyThirdApps(srcFile,destFile);  
  26.         if(!installResult){  
  27.             Log.d(TAG,"install failed");  
  28.             return;  
  29.         }  
  30.     }  
  31. }  
  32.   
  33. /** 
  34.  * File copy function. 
  35.  * It will be used when installThirdApps 
  36.  * @param srcFile  just like '/system/third_app/***.apk' 
  37.  * @param destDir  just like '/data/app/***.apk' 
  38.  * @return 
  39.  */  
  40. private boolean copyThirdApps(File srcFile, File destDir) {  
  41.     //do some check actions  
  42.     if (srcFile == null || destDir == null || !srcFile.exists()) {  
  43.         Log.e(TAG, "invalid arguments for movePreinstallApkFile()");  
  44.         Log.e(TAG, "move " + srcFile + " to " + destDir + " failed");  
  45.         return false;  
  46.     }  
  47.   
  48.     //create new file  
  49.     try{  
  50.         destDir.createNewFile();  
  51.     }catch(Exception e){  
  52.         Log.e(TAG, "create file faild! due to:" + e);  
  53.         return false;  
  54.     }  
  55.   
  56.     //set permission  
  57.     try{  
  58.         Runtime.getRuntime().exec("chmod 644 "+destDir.getAbsolutePath());  
  59.     }catch(Exception e){  
  60.         Log.e(TAG, "chmod file faild! due to:"+e);  
  61.     }  
  62.   
  63.     //do copy  
  64.     try{  
  65.         boolean ret = FileUtils.copyFile(srcFile,destDir);  
  66.         if(!ret){  
  67.             Log.e(TAG,"copy file faild!");  
  68.             return false;  
  69.         }  
  70.     }catch(Exception e){  
  71.         Log.e(TAG, "copy file faild! due to:"+e);  
  72.     }  
  73.   
  74.     return true && destDir.exists();  
  75. }  

在PKMS的构造函数,开始处理非系统应用的时候,但是一定要在扫描data/app之前,这样才能后面扫描到data/app这些复制进去的app,才会第一次开机安装成功。

  1. if (!mOnlyCore) {  
  2.     EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,  
  3.             SystemClock.uptimeMillis());  
  4.     if(isFirstBoot()){//判断第一次开机  
  5.         Log.i(TAG, "It's first boot, install the third apps");  
  6.         installThirdApps();//安装三方应用(copy到data/app下)  
  7.     }                          
  8.     scanDirLI(mAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);  
  9.   
  10.     scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK,  
  11.             scanFlags | SCAN_REQUIRE_KNOWN, 0);  


二、adb install处理

下面几个问题,我们知道PKMS会在开机的时候扫描data/app,所以一般我们把一个apk push到data/app下的时候,再把手机重启也会安装应用。但是一定要重启。


那adb install又是如何做到安装应用的,我们来看下代码,下面这段代码是pc侧的

  1. else if (!strcmp(argv[0], "install")) {  
  2.     if (argc < 2) return usage();  
  3.     return install_app(ttype, serial, argc, argv);  
  4. }  

我们来看下install_app这个函数,也是把apk文件push到/data/local/tmp下,然后调用了pm命令安装应用。

  1. static int install_app(transport_type transport, const char* serial, int argc,  
  2.                        const char** argv)  
  3. {  
  4.     static const char *const DATA_DEST = "/data/local/tmp/%s";  
  5.     static const char *const SD_DEST = "/sdcard/tmp/%s";  
  6.     const char* where = DATA_DEST;  
  7.     int i;  
  8.     struct stat sb;  
  9.   
  10.     for (i = 1; i < argc; i++) {  
  11.         if (!strcmp(argv[i], "-s")) {  
  12.             where = SD_DEST;  
  13.         }  
  14.     }  
  15.   
  16.     // Find last APK argument.  
  17.     // All other arguments passed through verbatim.  
  18.     int last_apk = -1;  
  19.     for (i = argc - 1; i >= 0; i--) {  
  20.         const char* file = argv[i];  
  21.         char* dot = strrchr(file, '.');  
  22.         if (dot && !strcasecmp(dot, ".apk")) {  
  23.             if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {  
  24.                 fprintf(stderr, "Invalid APK file: %s\n", file);  
  25.                 return -1;  
  26.             }  
  27.   
  28.             last_apk = i;  
  29.             break;  
  30.         }  
  31.     }  
  32.   
  33.     if (last_apk == -1) {  
  34.         fprintf(stderr, "Missing APK file\n");  
  35.         return -1;  
  36.     }  
  37.   
  38.     const char* apk_file = argv[last_apk];  
  39.     char apk_dest[PATH_MAX];  
  40.     snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));  
  41.     int err = do_sync_push(apk_file, apk_dest, 0 /* no show progress */);//把apk文件push到/data/local/tmp/目录下  
  42.     if (err) {  
  43.         goto cleanup_apk;  
  44.     } else {  
  45.         argv[last_apk] = apk_dest; /* destination name, not source location */  
  46.     }  
  47.   
  48.     err = pm_command(transport, serial, argc, argv);//调用了pm命令  
  49.   
  50. cleanup_apk:  
  51.     delete_file(transport, serial, apk_dest);  
  52.     return err;  
  53. }  

看下pm_command函数,是调用了pm install命令来安装应用。

  1. static int pm_command(transport_type transport, const char* serial,  
  2.                       int argc, const char** argv)  
  3. {  
  4.     std::string cmd = "shell:pm";  
  5.   
  6.     while (argc-- > 0) {  
  7.         cmd += " " + escape_arg(*argv++);  
  8.     }  
  9.   
  10.     return send_shell_command(transport, serial, cmd);  
  11. }  
我们来看下pm install的处理,调用了runInstall函数
  1. if ("install".equals(op)) {  
  2.     return runInstall();  
  3. }  
在runInstall函数会调用PKMS的installPackageAsUser函数安装应用
  1. VerificationParams verificationParams = new VerificationParams(verificationURI,  
  2.         originatingURI, referrerURI, VerificationParams.NO_UID, null);  
  3.   
  4. mPm.installPackageAsUser(apkFilePath, obs.getBinder(), installFlags,  
  5.         installerPackageName, verificationParams, abi, userId);  


三、注意

上面PKMS中把system/third_app下面的apk放在data/app有点问题,原因是android6.0 编译apk文件,会自动生成一个目录,所以代码需要修改一下。

主要是下面这个函数,system/third_app目录下多了一层目录。

  1. private void installThirdApps(){  
  2.     //the source directory not exists  
  3.     File storeDir = new File("/system/third_app");  
  4.     if(!storeDir.exists()){  
  5.         Log.e(TAG,"/system/third_app is not exist");  
  6.         return;  
  7.     }  
  8.   
  9.     //get the apk files in /system/third_app  
  10.     String apkDirFilesNames[] = storeDir.list();  
  11.     if(apkDirFilesNames == null){  
  12.         Log.e(TAG,"apk file name is null");  
  13.         return;  
  14.     }  
  15.   
  16.     //copy the apk files to /data/app  
  17.     boolean installSucc = false;  
  18.     for(int i = 0; i < apkDirFilesNames.length; i++){  
  19.         File srcFileDir = new File("/system/third_app", apkDirFilesNames[i]);  
  20.         Log.e(TAG,"srcFile=" + srcFileDir);  
  21.         String srcFileNames[] = srcFileDir.list();  
  22.         for(int j = 0; j < srcFileNames.length; j++) {  
  23.             File srcFile = new File(srcFileDir, srcFileNames[j]);  
  24.             File destFile = new File("/data/app", srcFileNames[j]);  
  25.             boolean installResult = copyThirdApps(srcFile, destFile);  
  26.             if(!installResult){  
  27.                 Log.d(TAG,"install failed");  
  28.                 return;  
  29.             }  
  30.         }  
  31.     }  
  32. }  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值