一、在AndroidR 的机器上运行,看demo代码的架构

 二、详细源码

1、在清单文件AndroidManifest.xml 添加权限和provider。如果是androidR或者更高版本还得加<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />,不然安装的过程会提示"There was a problem parsing the package"解析错误。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.topdon.installapkdemo"><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/Theme.InstallApkDemo"><activity android:name=".MainActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><providerandroid:name="androidx.core.content.FileProvider"android:authorities="com.topdon.installapkdemo.fileProvider"android:grantUriPermissions="true"android:exported="false"><meta-dataandroid:name="android.support.FILE_PROVIDER_PATHS"android:resource="@xml/file_paths" /></provider></application><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
</manifest>

2、布局文件 src\main\res\layout\activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Hello World!"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent" /><Buttonandroid:id="@+id/confirm"android:layout_width="match_parent"android:layout_height="100dp"android:layout_alignParentBottom ="true"android:background="#00BCD4"android:textSize="35dp"android:text="confirm" />
</androidx.constraintlayout.widget.ConstraintLayout>

3、在xml包下创建一个xml文件 src\main\res\xml\file_paths.xml

<?xml version="1.0" encoding="utf-8"?><paths><external-pathname="external"path="." /><external-files-pathname="external_files"path="." /><cache-pathname="cache"path="." /><external-cache-pathname="external_cache"path="." /><files-pathname="files"path="." /></paths>

4、file_paths文件简单解析

(1)files-path:
对应物理路径:getFilesDir(
对应具体路径:/data/user/0/包名/files
(2)cache-path:
对应物理路径:getCacheDir()
对应具体路径:/data/user/0/包名/cache
(3)external-path:
对应物理路径:Environment.getExternalStorageDirectory()
对应具体路径:/storage/emulated/0
(4)external-files-path:
对应物理路径:getExternalFilesDir("名字")
对应具体路径:/storage/emulated/0/Android/data/包名/files/名字
(5)external-cache-path:
对应物理路径:getExternalCacheDir()
对应具体路径:/storage/emulated/0/Android/data/包名/cache

5、执行的部分在src\main\java\com\topdon\installapkdemo\MainActivity.java

package com.topdon.installapkdemo;import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.FileProvider;
import androidx.fragment.app.FragmentActivity;import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.Settings;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;public class MainActivity extends AppCompatActivity implements  View.OnClickListener{private String TAG = "MainActivity";private static String mUrl;private static Context mContext;private   Button  btnConfirm;private static final int REQUEST_CODE = 1024;public Boolean checkPermission() {boolean isGranted = true;if (android.os.Build.VERSION.SDK_INT >= 23) {if (this.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {isGranted = false;}if (this.checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) !=PackageManager.PERMISSION_GRANTED) {isGranted = false;}Log.i("读写权限获取"," : "+isGranted);if (!isGranted) {this.requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION,Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE},102);}}return isGranted;}/** 检查Android 11或更高版本的文件权限 */private void  checkAndroid11FilePermission() {// Android 11 (Api 30)或更高版本的写文件权限需要特殊申请,需要动态申请管理所有文件的权限if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {if (Environment.isExternalStorageManager()) {// Log.i("ABCD","此手机是Android 11或更高的版本,且已获得访问所有文件权限")Toast.makeText(this, "Android VERSION  R OR ABOVE,HAVE MANAGE_EXTERNAL_STORAGE GRANTED!", Toast.LENGTH_LONG).show();// TODO requestOtherPermissions() 申请其他的权限} else {Toast.makeText(this, "Android VERSION  R OR ABOVE,NO MANAGE_EXTERNAL_STORAGE GRANTED!", Toast.LENGTH_LONG).show();// showDialog(activity, """本应用需要获取"访问所有文件"权限,请给予此权限,否则无法使用本应用""") {// launcher.launch(Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION))}} else {Log.i("ABCD","此手机版本小于Android 11,版本为:API ${Build.VERSION.SDK_INT},不需要申请文件管理权限");// TODO requestOtherPermissions() 申请其他的权限}}private void requestmanageexternalstorage_Permission() {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {// 先判断有没有权限if (Environment.isExternalStorageManager()) {Toast.makeText(this, "Android VERSION  R OR ABOVE,HAVE MANAGE_EXTERNAL_STORAGE GRANTED!", Toast.LENGTH_LONG).show();} else {Toast.makeText(this, "Android VERSION  R OR ABOVE,NO MANAGE_EXTERNAL_STORAGE GRANTED!", Toast.LENGTH_LONG).show();Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);intent.setData(Uri.parse("package:" + this.getPackageName()));startActivityForResult(intent, REQUEST_CODE);}}}private void installAPK(Context context,File apkFile) {Intent intent = new Intent();if (context == null) {return;}if (!apkFile.exists()) {Toast.makeText(this, "the apk is not exists", Toast.LENGTH_LONG).show();return;}String authority = getApplicationContext().getPackageName() + ".fileProvider";String packageName = context.getPackageName();Uri uri;if (apkFile != null) {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {//uri = FileProvider.getUriForFile(context, packageName//+ ".fileprovider", apkFile);//uri = FileProvider.getUriForFile(context, authority, apkFile);uri = FileProvider.getUriForFile(context, "com.topdon.installapkdemo.fileProvider", apkFile);intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);intent.setAction(Intent.ACTION_INSTALL_PACKAGE);} else {uri = Uri.fromFile(apkFile);intent.setAction(Intent.ACTION_VIEW);}intent.setDataAndType(uri, "application/vnd.android.package-archive");startActivity(intent);}}@Overridepublic void onClick(View v) {if (v.getId()==R.id.confirm) {//String pathApk = "/data/data/com.topdon.installapkdemo/files/serial_port.apk";//installAPK(this,new File(pathApk));String pathApk ="file:///storage/emulated/0/test/serial_port.apk";installAPK(this,new File(Uri.parse(pathApk).getPath()));//String pathApk = "/sdcard/serial_port.apk";//installAPK(this,new File(pathApk));}//Toast.makeText(this, "onClick", Toast.LENGTH_LONG).show();}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);checkPermission();requestmanageexternalstorage_Permission();btnConfirm = (Button) findViewById(R.id.confirm);btnConfirm.setOnClickListener(this);}
}

6、build.gradle

plugins {id 'com.android.application'
}android {compileSdkVersion 31buildToolsVersion "30.0.3"defaultConfig {applicationId "com.topdon.installapkdemo"minSdkVersion 25targetSdkVersion 30versionCode 1versionName "1.0"testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"}buildTypes {release {minifyEnabled falseproguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'}}compileOptions {sourceCompatibility JavaVersion.VERSION_1_8targetCompatibility JavaVersion.VERSION_1_8}
}dependencies {implementation 'androidx.appcompat:appcompat:1.1.0'implementation 'com.google.android.material:material:1.1.0'implementation 'androidx.constraintlayout:constraintlayout:1.1.3'testImplementation 'junit:junit:4.+'androidTestImplementation 'androidx.test.ext:junit:1.1.1'androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}

三、编译成apk,然后安装,运行测试。

1、push 要安装的apk到 /storage/emulated/0/test/serial_port.apk 里面 。

2、点击安装按钮

参考文章

android 使用FileProvider 兼容apk 在7.0版本无法安装_svenWang_的专栏-CSDN博客

安卓开发之apk自动安装代码_太阳在发光!-CSDN博客_安卓自动安装apk

android上边用代码安装apk文件_yangzm的专栏-CSDN博客_android 代码安装apk

https://www.jb51.net/article/189012.htm

https://www.jb51.net/article/235575.htm

2022-02-22 AndroidN之后 app代码安装apk,以及提示“There was a problem parsing the package“的解决方案相关推荐

  1. android app安装,Android App更新安装APK

    原标题:Android App更新安装APK 概要 一般地, Android App 都会被要求在App内进行软件更新提示, 让用户下载apk文件, 然后更新安装新版本, 一般过程如下: 检测是否有新 ...

  2. 安卓java安装apk代码_Android 通过代码安装 APK的方法详解

    在 APK 开发中,通过 Java 代码来打开系统的安装程序以安装 APK 并不是什么难事,一般的 Android 系统都有开放这一功能. 但随着 Android系统版本的迭代,其对于权限的把控越来越 ...

  3. Android 如何通过代码安装 APK

    在 APK 开发中,通过 Java 代码来打开系统的安装程序以安装 APK 并不是什么难事,一般的 Android 系统都有开放这一功能. 但随着 Android系统版本的迭代,其对于权限的把控越来越 ...

  4. android 代码 安装APK 解决了

    今晚查了很多资料,android代码安装APK BaseHelper.chmod("777", cachePath); Intent intent = new Intent(Int ...

  5. java 安装apk_Android 如何通过代码安装 APK?

    2019-10-21 关键字:Java代码安装程序 在 APK 开发中,通过 Java 代码来打开系统的安装程序以安装 APK 并不是什么难事,一般的 Android 系统都有开放这一功能. 但随着 ...

  6. Android代码安装apk程序

    文章目录 一.高低版本兼容代码及配置 1.java代码 2.AndroidManifest.xml 配置ContentProvider 3.paths xml 配置 二.老版本代码 三.可能出的问题及 ...

  7. RK3568-Android12 关于去掉安装apk时提示“来历不明的。。。”和“出于安全。。。”的修改方法

    在Android上安装apk往往有多种方式,但对于一般的操作来说有两种:1,通过U盘点击安装:2,通过网站.应用市场安装. 第一种安装方式会提示:"来历不明的应用会损坏...",点 ...

  8. genymotion2.8.1安装apk时提示ARM……x86……异常处理

    这两天接触android studio,跟着教程,接触到genymotion模拟器,版本2.8.1-- 本人使用的模拟器配置为:google nuex4,android sdk4.4.4,安装微信时提 ...

  9. 【Android 教程系列第 31 篇】通过 adb install 命令安装 apk 时提示 signatures do not match previously installed version

    这是[Android 教程系列第 31 篇],如果觉得有用的话,欢迎关注专栏. 遇到的一个小问题,做下记录. 一:问题描述 在使用 adb install 命令安装 apk 时,提示的内容如下 主要提 ...

  10. 2022.02.22

    保持自己的活力吧,无论是身体.心理还是思维 身体有活力,因为病不起,伤不起,甚至请不起假: 心理有活力,才会有精气神 思维有活力,才能够脱出困境,不会让自己甚至自己的子孙后代,世世为韭菜 昨天又没有按 ...

最新文章

  1. 面试官:你说熟悉MySQL,那来谈谈InnoDB怎么解决幻读的?
  2. anaconda重新安装pytorch,使用GPU加速
  3. w命令、vmstat命令、top命令、sar命令、noload命令
  4. 安装docker之后电脑无法关机
  5. 计算机原理期中考试,计算机组成原理期中考试试题
  6. python语句join_详解Python中的join()函数的用法
  7. Wannafly挑战赛23 A 字符串
  8. python中key_python属性和key的区别?
  9. Linux下一些简单命令的收集
  10. arr数组怎么取值_【JavaScript】Array数组常规使用小结(持续更新......)
  11. 部署mysql主从同步
  12. Opencv实战四 图像匹配
  13. PHP8与PHP7计算性能对比
  14. 远程服务RMI源码解析(二)
  15. 传统的方式写mybatis的应用程序
  16. 独角兽微盟的“AB面”
  17. ES6 isFinite()
  18. 第二十九章 管理许可(二)
  19. 取十位数,百位数,千位数的各位方法小姐
  20. 软考 计算机 都有什么考试内容,了解软考是什么 软考考试流程都包括哪些

热门文章

  1. 【Java代码之美】 -- Java11新特性解读
  2. 头条推荐越来越少是否还要坚持下去
  3. 关于String类的split方法
  4. bzoj 2339: [HNOI2011]卡农 组合数学+递推
  5. deepin显卡驱动管理器在哪_deepin显卡设置
  6. 2.5数字传输系统2.6宽带接入技术
  7. Kali-DDoS工具集合
  8. Google Earth Engine(GEE)——1981-2020年全球降水数据年均降水量直方图表示(北京市为例)
  9. 腾讯云服务器安全组8080端口开放教程
  10. ISP和摄像头工作原理