本文介绍: 一、看demo代码架构二、详细源码 1、在清单文件AndroidManifest.xml 添加权限provider。&lt;?xml version=”1.0″ encoding=”utf-8″?&gt;<manifest xmlns:android=”http://schemas.android.com/apk/res/androidpackage=”com.topdon.installapkdemo”&gt; <application

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

 二、详细源码

    1、在清单文件AndroidManifest.xml 添加权限provider如果是androidR或者更高版本还得加<usespermission android:name=”android.permission.MANAGE_EXTERNAL_STORAGE” /&gt;,不然安装过程提示“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">

    <application
        android: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>

        <provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="com.topdon.installapkdemo.fileProvider"
            android:grantUriPermissions="true"
            android:exported="false">
            <meta-data
                android: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、布局文件 srcmainreslayoutactivity_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">

    <TextView
        android: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" />
    <Button
        android: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文件 srcmainresxmlfile_paths.xml

<?xml version="1.0" encoding="utf-8"?>
    <paths>
        <external-path
            name="external"
            path="." />
        <external-files-path
            name="external_files"
            path="." />
        <cache-path
            name="cache"
            path="." />
        <external-cache-path
            name="external_cache"
            path="." />
        <files-path
            name="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、执行的部分在srcmainjavacomtopdoninstallapkdemoMainActivity.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);
        }
    }

    @Override
    public 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();
        }

    @Override
    protected 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 31
    buildToolsVersion "30.0.3"

    defaultConfig {
        applicationId "com.topdon.installapkdemo"
        minSdkVersion 25
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility 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

原文地址:https://blog.csdn.net/qq_37858386/article/details/123075426

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。

如若转载,请注明出处:http://www.7code.cn/show_12793.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注