7.0以上安装APK,请自行配置FileProvider,具体不多说

android:name="androidx.core.content.FileProvider"

android:authorities="${applicationId}.fileprovider"

android:exported="false"

android:grantUriPermissions="true">

android:name="android.support.FILE_PROVIDER_PATHS"

android:resource="@xml/filepaths" />

xml/filepaths.xml如下

name="newApk"

path="newApk0/" /> #我是放在私有目录的files/newApk0下的,请根据自身要求修改

7.0以下安装APK,经常会遇到“安装包找不到”或“解析包失败等原因”,直接上代码了

分析原因:因为我下载的APK是保存在私有目录data/data/{packageName}/files/{自定义文件夹}内的,Android的安装程序在加载安装包的时候,没有访问这个目录的权限,所以要给这个目录修改下访问权限。

public static void install(Context context, File apkFile) {

if (context == null || apkFile == null || !apkFile.exists()) {

return;

}

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {

openInstallPage(context, FileProvider.getUriForFile(context, context.getPackageName() + ".fileprovider", apkFile));

} else {

// 这一步很重要,android 6.0 及以下,需要获取文件全路径的文件权限

chmodFullFile(context, apkFile);

}

}

/**

* 修改file全路径的读写权限

*

* @param file

*/

private static void chmodFullFile(final Context context, final File file) {

if (file == null) {

return;

}

ArrayList commands = new ArrayList<>();

getAllCommand(commands, file);

if (commands.size() > 0) {

String[] c = new String[commands.size()];

for (int i = 0; i < commands.size(); i++) {

c[i] = commands.get(i);

System.out.println(commands.get(i));

}

ProcessUtils.executeProcess(c, null, 5000, new ProcessUtils.ProcessListener() {

@Override

public void finish() {

openInstallPage(context, Uri.fromFile(file));

}

});

}

}

private static void getAllCommand(ArrayList command, File file) {

if (file == null) {

return;

}

command.add("chmod 777 " + file.getAbsolutePath());

getAllCommand(command, file.getParentFile());

}

/**

* 打开apk安装界面

*

* @param context

* @param apkUri

*/

private static void openInstallPage(Context context, Uri apkUri) {

Intent intent = new Intent();

intent.setDataAndType(apkUri, "application/vnd.android.package-archive");

intent.setAction(Intent.ACTION_VIEW);

intent.addCategory("android.intent.category.DEFAULT");

intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

context.startActivity(intent);

}

ProcessUtils工具类如下:

public class ProcessUtils {

interface ProcessListener {

void finish();

}

/**

* 执行Process命令 cmd

*

* @param command 指令

* @param o

* @param timeout 超时时间

* @param processListener 回调

* @desc 注意:回调没有切换线程

*/

public static void executeProcess(final String[] command, Object o, final long timeout, final ProcessListener processListener) {

new Thread(new Runnable() {

@Override

public void run() {

for (String cmd : command) {

exec(cmd, timeout);

}

processListener.finish();

}

}).start();

}

private static void exec(String command, long timeout) {

Process process = null;

Worker worker = null;

try {

process = Runtime.getRuntime().exec(command);

worker = new Worker(process);

worker.start();

worker.join(timeout);

} catch (InterruptedException | IOException ex) {

if (worker != null) {

worker.interrupt();

}

Thread.currentThread().interrupt();

ex.printStackTrace();

} finally {

if (process != null) {

process.destroy();

}

}

}

private static class Worker extends Thread {

private final Process process;

private Worker(Process process) {

this.process = process;

}

@Override

public void run() {

InputStream errorStream = null;

InputStream inputStream = null;

try {

errorStream = process.getErrorStream();

inputStream = process.getInputStream();

readStreamInfo(errorStream, inputStream);

process.waitFor();

process.destroy();

} catch (InterruptedException ignore) {

}

}

}

/**

* 读取RunTime.exec运行子进程的输入流 和 异常流

*

* @param inputStreams 输入流

*/

private static void readStreamInfo(InputStream... inputStreams) {

ExecutorService executorService = Executors.newFixedThreadPool(inputStreams.length);

for (InputStream in : inputStreams) {

executorService.execute(new CacheConsumer(in));

}

executorService.shutdown();

}

/**

* Process缓存消费者

*/

private static class CacheConsumer implements Runnable {

private InputStream in;

CacheConsumer(InputStream in) {

this.in = in;

}

@Override

public void run() {

try {

BufferedReader br = new BufferedReader(new InputStreamReader(in, "GBK"));

StringBuilder result = new StringBuilder();

String line;

while ((line = br.readLine()) != null) {

result.append(line).append("\n");

}

if (result.length() > 0) {

Log.i("ProcessCacheConsumer", "==> " + result.toString());

}

} catch (IOException e) {

e.printStackTrace();

} finally {

try {

in.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

}

相关日志

I/System.out: chmod 777 /data/user/0/com.tencent.tmgp.xxx/files/newApk0/appCode.apk

I/System.out: chmod 777 /data/user/0/com.tencent.tmgp.xxx/files/newApk0

I/System.out: chmod 777 /data/user/0/com.tencent.tmgp.xxx/files

I/System.out: chmod 777 /data/user/0/com.tencent.tmgp.xxx

I/System.out: chmod 777 /data/user/0

I/System.out: chmod 777 /data/user

I/System.out: chmod 777 /data

I/System.out: chmod 777 /

I/ProcessCacheConsumer: ==> chmod: chmod '/data/user/0' to 120777: Permission denied

I/ProcessCacheConsumer: ==> chmod: chmod '/data/user' to 40777: Permission denied

I/ProcessCacheConsumer: ==> chmod: chmod '/data' to 40777: Permission denied

I/ProcessCacheConsumer: ==> chmod: chmod '/' to 40777: Read-only file system

android apk安装代码,Android安装APK相关推荐

  1. android增删功能代码,Android Studio开发实战 之 增删改查

    增删改查是一个应用最基础的操作,增删改查的流程走通了,下面的路程也就顺利多了.现在使用Android Studio开发一个简单的应用,该应用就实现了增删改查的操作,看似简单,到底简不简单呢,下面开始操 ...

  2. android调频收音机代码,android 收音机 FM 驱动 hal层 框架层以及应用层代码

    [实例简介] android 收音机 FM 驱动 hal层 框架层以及应用层代码 方法一 不需要framework部分 1.fm放到 \hardware\rk2x 2.FmRadio 放到 packa ...

  3. android确认密码代码,Android自定义View实现验证码or密码输入框

    前言 最近项目中有支付功能,用户输入密码时要类似微信支付密码输入框的样式,本想直接copy网上的,但设计姐姐总是对样式挑三拣四,抽空自己自定义了一个,无奈之下抽空自定义了个,并把它贴到GitHub上供 ...

  4. android 进度条 代码,Android 进度条使用详解及示例代码

    在这里,总结一下loading进度条的使用简单总结一下. 一.说起进度条,必须说说条形进度条,经常都会使用到嘛,特别是下载文件进度等等,还有像腾讯QQ安装进度条一样,有个进度总给人良好的用户体验. 先 ...

  5. android小球移动代码,Android中如何绘制一个跟随手指移动的小球

    Android中如何绘制一个跟随手指移动的小球 发布时间:2020-11-07 16:22:43 来源:亿速云 阅读:82 作者:Leah 本篇文章为大家展示了Android中如何绘制一个跟随手指移动 ...

  6. android 小白点代码,Android实现小圆点显示未读功能

    ####前言 以前我们实现这个功能都是用 BadgeView.java,大体就是将这个java类复制到自己的项目中,然后在项目中使用,今天讲的也是一款BadgeView,我将其封装称工具类Badget ...

  7. android qq 分享代码,Android将内容分享到QQ和微信实例代码

    具体代码如下所示: package dmpte.sharewechat; import android.annotation.SuppressLint; import android.app.Acti ...

  8. android清除缓存 代码,Android应用开发之Android应用清除缓存一般清理目录和代码的教程...

    本文将带你了解Android应用开发Android应用清除缓存一般清理目录和代码的教程,希望本文对大家学Android有所帮助. 一个应用安装完成,会有缓存,缓存一般分为内部存储的和外置的,内存中路径 ...

  9. android 检测广告代码,Android – Admob显示测试广告,但不是真正的广告

    我正在使用admob来显示 Android广告.测试广告正常工作,但不会显示真实的广告.此外,对于真正的插页式广告,我们没有任何问题.只有真正的横幅广告没有显示.我的java代码是 private I ...

最新文章

  1. python简单代码input-【python系统学习05】input函数——实现人机交互
  2. tensorflow学习(4.loss函数以及正则化的使用 )
  3. SQL各种join用法
  4. nodejs path.parse()
  5. 语言怎么绘画人物肖像_国画里的新年,看看古人是怎么过年的!
  6. 瓜子二手车发12月二手车价格:汉兰达奥德赛CR-V保值率居首
  7. NFS双机热备探究实验
  8. Docker(一):Docker入门
  9. 2011年国家统计局省市代码、城市代码、省份代码表数据
  10. 计算机二级公共基础知识点整理
  11. 登录不了WPS国际版,密码正确,在网页能够正常登录,在WPS不行,求解答,版本号是10.2.0.7646已刷语言包
  12. 全国计算机联合考试广西二级c语言近五年试题,计算机二级c语言试题
  13. JS逆向-易班登录password参数(RSA加密)
  14. 红包达人app是真的吗,红包达人怎么玩?红包达人官方下载最新最全教程
  15. CSS-浏览器缩放使边框大小改变,导致布局改变的问题
  16. ACM学习:例题完成总结与期中心得
  17. video.js 实现视频只能后退,不能快进
  18. 易语言编译和c语言,易语言独立编译的EXE文件问题
  19. 【JavaSE】JavaSE之控制逻辑
  20. 聊聊做码农的这些年,时光飞逝岁月无痕

热门文章

  1. kail2.0下hping3的安装和使用
  2. 15、青年歌手大赛_评委打分
  3. 用来测试的在线视频url地址
  4. 超详细彻底卸载Anaconda详细教程
  5. 2000-2022年逐年归一化植被指数(NDVI)数据(全国/分省/分市)
  6. FET场效应晶体管扫盲
  7. jacob打印word
  8. 商用密码应用与安全性评估要点笔记(密码算法ZUC)
  9. 万能遥控器 Privacy Policy
  10. python2.7.3怎么安装_Linux系统如何编译安装python 2.7.3 - Python - 服务器之家