本文主要介绍程序如何安装apk,包括普通模式安装和系统权限静默安装。
如果是非系统应用请直接查看:Android常用代码之APK root权限静默安装,查看更完美的解决方案。
1、普通模式安装,调用系统Intent,代码如下:
1 2 3 4 5 6 |
public static void install(Context context, String filePath) { Intent i = new Intent(Intent.ACTION_VIEW); i.setDataAndType(Uri.parse("file://" + filePath), "application/vnd.android.package-archive"); i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(i); } |
2、静默安装
如果是非系统应用请移步:Android常用代码之APK root权限静默安装,查看更完美的解决方案。
分为如下三步
(1)、静默安装需要系统应用安装权限,需要在AndroidManifest.xml中添加
1 |
<uses-permission android:name="android.permission.INSTALL_PACKAGES" /> |
(2)、实现代码
静默安装代码如下,实际是通过pm install -r 命令安装。
注意:该函数最好在新建的线程中运行并通过handler发送安装结果给主线程,否则安装时间较长会导致ANR。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
/** * install slient * * @param context * @param filePath * @return 0 means normal, 1 means file not exist, 2 means other exception error */ public static int installSlient(Context context, String filePath) { File file = new File(filePath); if (filePath == null || filePath.length() == 0 || (file = new File(filePath)) == null || file.length() <= 0 || !file.exists() || !file.isFile()) { return 1; } String[] args = { "pm", "install", "-r", filePath }; ProcessBuilder processBuilder = new ProcessBuilder(args); Process process = null; BufferedReader successResult = null; BufferedReader errorResult = null; StringBuilder successMsg = new StringBuilder(); StringBuilder errorMsg = new StringBuilder(); int result; try { process = processBuilder.start(); successResult = new BufferedReader(new InputStreamReader(process.getInputStream())); errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream())); String s; while ((s = successResult.readLine()) != null) { successMsg.append(s); } while ((s = errorResult.readLine()) != null) { errorMsg.append(s); } } catch (IOException e) { e.printStackTrace(); result = 2; } catch (Exception e) { e.printStackTrace(); result = 2; } finally { try { if (successResult != null) { successResult.close(); } if (errorResult != null) { errorResult.close(); } } catch (IOException e) { e.printStackTrace(); } if (process != null) { process.destroy(); } } // TODO should add memory is not enough here if (successMsg.toString().contains("Success") || successMsg.toString().contains("success")) { result = 0; } else { result = 2; } Log.d("installSlient", "successMsg:" + successMsg + ", ErrorMsg:" + errorMsg); return result; } |
返回值0表示安装成功,1表示文件不存在,2表示其他错误。需要更丰富的安装失败信息(内存不足、解析包出错)可直接使用PackageUtils.installSlient。
(3) 、获取系统权限
完成了上面两步后,普通方式安装我们的应用仍然无法静默安装。需要我们的应用获得系统权限,编译应用并通过
adb push <your_apk_path> /system/app/
命令实现安装,即可拥有系统权限。
大神。。有没有介绍service和alamanager的文档?
什么意思,是service这个类,还是系统service
lz,那么请问我用普通方式如何得到安装成功与否的结果呢?我想知道用户是点击了确定还是取消,点击确定的话是否成功安装了呢?
没办法区分取消还是确定的,你只能通过监听android.intent.action.PACKAGE_ADDED这个action判断是否安装成功,还不精准,因为如果你取消了,同时另外一个程序安装了该apk,你也会收到PACKAGE_ADDED这个action
不错,高手
您好,又是我,我有个问题想请教您,希望您有空的话帮我解答一下。就是我在sdcard下有个文件夹,里面有一些文件夹,然后文件夹下有一些文件或文件夹,我想通过命令修改这个文件夹下所有文件和文件夹的权限,然后我想用您的代码,就是用 ShellUtils.execCommand 方法,然后我是这么写的
ShellUtils.execCommand”chmod 666 /mnt/sdcard/” + fileName + ” -R”,false); 可是我就是没能成功修改,请问我应该怎么写才对呢?
两个方法:
1、adb shell中运行该命令看是否成功
2、debug看返回结果
恩,谢谢您啦
您好,我有个问题想请教你,就是我现在可以在 sdcard下实现静默安装,可是我能不能有什么办法把apk装到 /system/app/ 下面啊?就是用代码实现的方式,不是在终端用adb 命令 push 进去的那种。因为我发现我虽然机器是root的,可是我在代码里想用File这个类创建一个文件夹就抛出错误说 permission denied.
装到/system/app/下面我都是adb push的,代码没实现过,不过原理就是获得root权限,挂在system,然后将apk拷贝到/system/app/下面,用ShellUtils.execCommand方法,第一个参数为new String[] { “mount -o rw,remount /system”, “cp /mnt/sdcard/xx.apk /system/app/” },表示挂在/system,然后拷贝apk到/system/app下面;第二个参数为true表示root执行。
嘿嘿,谢谢您的指点,我成功把apk从sdcard拷贝到/system/app/ 下面啦。无比感谢。不过我还是有个小问题要麻烦你,就是那个装在/system/app/ 下的apk, 它安装后的文件夹在哪里啊?为什么我找了半天没找到呢。谢谢你啊
跟一般应用一样在/data/data/${packageName}下面
好的,谢谢您
不好意思,又来了,我刚才又试了试,我这次没有直接引入全部您的仓,而是只用了您那两个需要的静默安装的类,然后这次可以成功安装了。实在太谢谢您了,这代码对我来说太有用了。我都被这个问题困扰了好久了,网上也搜寻了无数帖子,可是要不就异常麻烦,我实现不了,要不就根本不工作。您辛苦了
对了,ps:我已经把helloworld.apk放入了/mnt/sdcard/ 里了
您好,我试过,我下载了您的那个库,然后按照您给的方法,右键点击项目,选择properties,然后加入您给的library,然后在Activity的onCreate()里直接写
PackageUtils.installSilent(this, “/mnt/sdcard/helloworld.apk”);.但是似乎程序找不到PackageUtils这个类啊。总是报错。请问我是不是哪个地方写得不对啊
你加班很猛啊,哈哈,android公共库的添加和一般jar包添加方式不一样,你可以参考添加Android Common Lib添加及Google Code和Github如何拉取代码
安装不了啊
https://code.google.com/p/trinea-android-common/source/browse/trunk/src/com/trinea/android/common/utils/PackageUtils.java 可以用里面的installSilent函数
还可以通过参照Android源码,然后再以编译package的方式打包apk,实现静默安装。如果手机厂商没有修改过APK安装的代码,几乎都可以成功安装(像小米似乎修改过,没有成功)。而且,无需root权限!
非常感谢,回头我试试