Android应用的静默安装

最近需要实现Android应用的静默安装,在网上看了不少帖子,最后在root权限下实现对应用的静默安装和卸载,现在就整个实现的过程做一个总结。
一.第一种方案
第一种方案参考了源码中/packages/apps/PackageInstaller的实现方式,实现的主要代码如下:
001 import java.io.File;
002 import java.io.FileNotFoundException;
003 import java.io.FileOutputStream;
004 import java.io.IOException;
005 import android.content.Context;
006 import android.content.Intent;
007 import android.content.pm.PackageInfo;
008 import android.content.pm.PackageManager;
009 import android.content.pm.IPackageInstallObserver;
010 import android.content.pm.PackageManager.NameNotFoundException;
011 import android.content.pm.PackageParser;
012 import android.net.Uri;
013 import android.os.Handler;
014 import android.os.Message;
015 import android.util.DisplayMetrics;
016 import android.util.Log;
017 import android.os.FileUtils;
018  
019 public class MyPackageInstaller {
020 private static final String PACKAGE_NAME = "test.installservice";
021 private final int INSTALL_COMPLETE = 1;
022 private Context context;
023 Uri mPackageURI;
024 private PackageParser.Package mPkgInfo;
025  
026 private Handler mHandler = new Handler() {
027 public void handleMessage(Message msg) {
028 switch (msg.what) {
029 case INSTALL_COMPLETE:
030 // finish the activity posting result
031 //setResultAndFinish(msg.arg1);
032 break;
033 default:
034 break;
035 }
036 }
037 };
038  
039 void setResultAndFinish(int retCode) {
040 // Intent data = new Intent();
041 // setResult(retCode);
042 // finish();
043 }
044  
045 public MyPackageInstaller(Context c) {
046 this.context = c;
047 }
048  
049 public void installPackage() {
050 int installFlags = 0;
051 PackageManager pm = context.getPackageManager();
052 try {
053 PackageInfo pi = pm.getPackageInfo(
054 mPkgInfo.applicationInfo.packageName,
055 PackageManager.GET_UNINSTALLED_PACKAGES);
056 if (pi != null) {
057 // installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
058 installFlags |= 2;
059 }
060 } catch (NameNotFoundException e) {
061 }
062  
063 String array[] = null;
064 try {
065 Runtime.getRuntime().exec("chmod 777 /data/data/" + PACKAGE_NAME);
066 Runtime.getRuntime().exec(
067 "chmod 777 /data/data/" + PACKAGE_NAME + "/files");
068 array = this.mPackageURI.toString().split("/");
069 System.out.println("array[last]->" + array[array.length - 1]);
070 Runtime.getRuntime().exec(
071 "chmod 777 /data/data/" + PACKAGE_NAME + "/files/"
072 + array[array.length - 1]);
073 } catch (IOException e) {
074 // TODO Auto-generated catch block
075 e.printStackTrace();
076 }
077  
078 PackageInstallObserver observer = new PackageInstallObserver();
079 pm.installPackage(mPackageURI, observer, installFlags, null);
080 // context.deleteFile(array[array.length-1]);
081 }
082  
083 class PackageInstallObserver extends IPackageInstallObserver.Stub {
084 public void packageInstalled(String packageName, int returnCode) {
085 Message msg = mHandler.obtainMessage(INSTALL_COMPLETE);
086 msg.arg1 = returnCode;
087 mHandler.sendMessage(msg);
088 }
089 }
090  
091 private File createTempPackageFile(String filePath) {
092 File tmpPackageFile;
093 int i = filePath.lastIndexOf("/");
094 String tmpFileName;
095 if (i != -1) {
096 tmpFileName = filePath.substring(i + 1);
097 } else {
098 tmpFileName = filePath;
099 }
100 FileOutputStream fos;
101 try {
102 // MODE_WORLD_READABLE=1
103 fos = context.openFileOutput(tmpFileName, 1);
104 } catch (FileNotFoundException e1) {
105 Log.e("Installer", "Error opening file " + tmpFileName);
106 return null;
107 }
108 try {
109 fos.close();
110 } catch (IOException e) {
111 Log.e("Installer", "Error opening file " + tmpFileName);
112 return null;
113 }
114 tmpPackageFile = context.getFileStreamPath(tmpFileName);
115 File srcPackageFile = new File(filePath);
116 if (!FileUtils.copyFile(srcPackageFile, tmpPackageFile)) {
117 return null;
118 }
119 return tmpPackageFile;
120 }
121  
122 public void makeTempCopyAndInstall(Uri mPackageURI) {
123 mPkgInfo = getPackageInfo(mPackageURI);
124 System.out.println("package=" + mPkgInfo.applicationInfo.packageName);
125 System.out.println("copy file=" + mPackageURI.getPath());
126 File mTmpFile = createTempPackageFile(mPackageURI.getPath());
127 if (mTmpFile == null) {
128 // display a dialog
129 Log.e("Installer",
130 "Error copying file locally. Failed Installation");
131 // showDialogInner(DLG_OUT_OF_SPACE);
132 return;
133 }
134 this.mPackageURI = Uri.parse("file://" + mTmpFile.getPath());
135 }
136  
137 public PackageParser.Package getPackageInfo(Uri packageURI) {
138 final String archiveFilePath = packageURI.getPath();
139 PackageParser packageParser = new PackageParser(archiveFilePath);
140 File sourceFile = new File(archiveFilePath);
141 DisplayMetrics metrics = new DisplayMetrics();
142 metrics.setToDefaults();
143 return packageParser.parsePackage(sourceFile, archiveFilePath, metrics,
144 0);
145 }
146 }


在程序中的调用方式:this为Context,path为安装包的绝对路径
1 MyPackageInstaller mpi = new MyPackageInstaller(this);
2 mpi.makeTempCopyAndInstall(Uri.parse(path));
3 mpi.installPackage();


这种方式需要在源码下面编译apk,并将apk放入/system/app目录下面。

二.通过shell命令实现
首先,在java中实现安装和卸载apk的命令
01 public class PackageInstaller {
02  
03 public void unInstallApp(String packageName){
04 try {
05 Runtime.getRuntime().exec("pm uninstall "+packageName);
06 } catch (IOException e) {
07 e.printStackTrace();
08 }
09 }
10  
11 public void installApp(String appPath){
12 try {
13 Runtime.getRuntime().exec("pm install "+appPath);
14 } catch (IOException e) {
15 e.printStackTrace();
16 }
17 }
18  
19 public void reInstallApp(String appPath){
20 try {
21 Runtime.getRuntime().exec("pm install -r "+appPath);
22 } catch (IOException e) {
23 e.printStackTrace();
24 }
25 }
26  
27 }

01 public class StartMain {
02  
03 private static final String INSTALL_ACTION_LABEL = "install";
04 private static final String REINSTALL_ACTION_LABEL = "reinstall";
05 private static final String UNINSTALL_ACTION_LABEL = "uninstall";
06  
07 public static void main(String args[]){
08 if(args==null||args.length<2) return;
09 PackageInstaller pi=new PackageInstaller();
10 if(args[0].equals(INSTALL_ACTION_LABEL)){
11 pi.installApp(args[1]);
12 }
13 if(args[0].equals(REINSTALL_ACTION_LABEL)){
14 pi.reInstallApp(args[1]);
15 }
16 else if(args[0].equals(UNINSTALL_ACTION_LABEL)){
17 pi.unInstallApp(args[1]);
18 }
19 }
20  
21 }

然后再源码环境下将该java程序编译为jar包
2.将编译好的jar包放入程序的assets目录下面,通过以下代码在程序中将该jar文件拷贝到/data/data/package/files/目录下面
01 try {
02 AssetManager assetManager = context.getResources().getAssets();
03 InputStream in = assetManager.open(JAR_NAME);
04 if (in == null) {
05 return;
06 }
07 int length = in.available();
08 byte fileByte[] = new byte[length];
09 in.read(fileByte, 0, fileByte.length);
10 in.close();
11 OutputStream out = context.openFileOutput(JAR_NAME,
12 Context.MODE_WORLD_READABLE | Context.MODE_WORLD_WRITEABLE);
13 out.write(fileByte);
14 out.close();
15 } catch (Exception e) {
16 e.printStackTrace();
17 }

在有root权限的情况下,可以在shell中执行该jar包来进行安装和卸载:
1 String exportClassPath = "export CLASSPATH=/data/data/"
2 + context.getPackageName() + "/files/installpackagejar.jar";

1 String INSTALL_ACTION_CMD = " exec app_process /system/bin packageName.StartMain install ";

01 public boolean installApp(String path) {
02 File temp = new File(path);
03 if (!temp.exists())
04 return false;
05 String cmd[] = { exportClassPath, INSTALL_ACTION_CMD + path };
06 try {
07 consoleExec(cmd);
08 } catch (IOException e) {
09 e.printStackTrace();
10 return false;
11 }
12 return true;
13 }

01 private void consoleExec(String[] cmd) throws IOException {
02 Process process = Runtime.getRuntime().exec("su");
03 DataOutputStream os = new DataOutputStream(process.getOutputStream());
04 for (int i = 0; i < cmd.length; i++) {
05 os.writeBytes(cmd<i> + "\n");
06 }
07 os.writeBytes("exit\n");
08 os.flush();
09 os.close();
10 }


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值