1、效果图
注意:
- 1、声明权限,并动态获取权限
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!--在SDCard中创建与删除文件权限-->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.VIBRATE" />
- 2、Application中添加requestLegacyExternalStorage
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:name=".MyApplication"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
android:requestLegacyExternalStorage="true"
android:networkSecurityConfig="@xml/network_security_config"
>
- 3、network_security_config.xml
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true" />
</network-security-config>
2、使用
//------------APP内部下载和安装--------------
var url = "https://chatplus.buzz/download/chatplus-android.apk"
//var url = "https://storage-asura.ruigushop.com/wms/client/73500430201577474/wmstest0.5.221017.apk"
//获取本地的下载路径
var localPath = FileUtils.getApkFilePath(MyApplication.instance, url)
//获取文件名
var fileName = FileUtils.getFileName(MyApplication.instance, url)
var filePath = localPath+fileName
LogUtils.debugInfo("-----filePath: ${filePath}---文件名:${fileName}")
val file = File(filePath)
if (file.exists()){
//文件存在
progressBar.text = "100%"
progressBar.progress = 100.0
//下载完成,去安装apk
var intent = FileUtils.openApkFile(context, File(filePath))
intent?.let {
startActivity(context,it,null)
}
}else{
//文件不存在
RequestNetDialog.showDialog(activity)
mainScope.launch {
downLoad(
tag = "appDown",
url = url,
savePath = localPath,
saveName = fileName,
reDownload = true,
loadListener = object : OnDownLoadListener {
override fun onDownLoadPrepare(key: String) {
}
override fun onDownLoadError(key: String, throwable: Throwable) {
RequestNetDialog.hideDialog()
LogUtils.debugInfo("---下载报错------key:${throwable.toString()}")
}
override fun onDownLoadSuccess(key: String, path: String, size: Long) {
LogUtils.debugInfo("---下载完成------key:${key}")
//下载完成,去安装apk
var intent = FileUtils.openApkFile(context, File(filePath))
intent?.let {
startActivity(context,it,null)
}
}
override fun onDownLoadPause(key: String) {
}
override fun onUpdate(
key: String,
progress: Int,
read: Long,
count: Long,
done: Boolean
) {
RequestNetDialog.hideDialog()
progressBar.text = "${progress}%"
progressBar.progress = progress.toDouble()
LogUtils.debugInfo("---下载进度------progress:${progress}")
}
})
}
}
3、获取app本地路径
package com.asura.android.tmspda.util;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import androidx.core.content.FileProvider;
import com.asura.android.tmspda.MyApplication;
import java.io.File;
public class FileUtils {
/**
* 获取app本地的路径
*
* @param context
* @param downLoadUrl
* @return
*/
public static String getApkFilePath(Context context, String downLoadUrl) {
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
File external = MyApplication.Companion.getInstance().getExternalFilesDir(null);
if (external != null) {
return external.getAbsolutePath();
}
}
return MyApplication.Companion.getInstance().getFilesDir().getAbsolutePath();
}
/**
* 获取下载的文件名字
*
* @param context
* @param downLoadUrl
* @return
*/
public static String getFileName(Context context, String downLoadUrl) {
String fileName = "";
if (downLoadUrl.endsWith(".apk")) {
int index = downLoadUrl.lastIndexOf("/");
if (index != -1) {
fileName = downLoadUrl.substring(index);
} else {
fileName = context.getPackageName() + ".apk";
}
} else {
fileName = "";
}
return fileName;
}
/**
* 安装apk
*
* @param context
* @param outputFile
* @return
*/
public static Intent openApkFile(Context context, File outputFile) {
Intent intent = new Intent();
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setAction(Intent.ACTION_VIEW);
Uri uri;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
uri = FileProvider.getUriForFile(context, context.getPackageName() + ".provider.fileprovider", outputFile);
} else {
uri = Uri.fromFile(outputFile);
}
intent.setDataAndType(uri, "application/vnd.android.package-archive");
return intent;
}
}
4、XML中声明FileProvider
<provider
android:name=".base.FileProvider"
android:authorities="${applicationId}.provider.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" />
</provider>
5、provider_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
</paths>
6、FileProvider.java
/**
* @Author lyy
*/
public class FileProvider extends androidx.core.content.FileProvider {
}