Android应用的静默安装

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


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


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

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

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

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

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

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

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

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


0 0
原创粉丝点击