kotlin 更新app
- 检查是否有最新包
- 下载安装包,(下载过程中可能有失败,不完整)
- 安装最新包
**注:使用的是轻量级的网络请求工具 **
详情查看:https://blog.youkuaiyun.com/Jeff_YaoJie/article/details/101270220
注意安装包共享
在gradle引用
implementation 'androidx.core:core-ktx:1.0.2'
在androidMainfest 中添加
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.hldm.lbtafxapp.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
file_paths.xml 文件如下
<?xml version="1.0" encoding="utf-8"?>
<resources>
<paths>
<!--
files-path: 该方式提供在应用的内部存储区的文件/子目录的文件。
它对应Context.getFilesDir返回的路径:eg:”/data/data/com.***.***/files”。
cache-path: 该方式提供在应用的内部存储区的缓存子目录的文件。
它对应Context.getCacheDir返回的路:eg:“/data/data/com.***.***/cache”;
external-path: 该方式提供在外部存储区域根目录下的文件。
它对应Environment.getExternalStorageDirectory返回的路径
external-files-path: Context.getExternalFilesDir(null)
external-cache-path: Context.getExternalCacheDir(String)
-->
<external-path name="download" path="" />
</paths>
</resources>
以上配置中使用到的文件地址如下获取为 /data/data/com.***.***/files/downloads/
//要保存的文件名
val saveFilePath = "${this.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)}/".trim()
1.检查是否有最新包
/*
* 更新app,检查是否有最新包
*/
fun updateApp() {
Handler(Looper.getMainLooper()).post {
//andorid 1 ios 2 pad 3
val map: Map<String, String> = mapOf(
"app_id" to "3",
"version_Code" to SystemUtils.getVersionCode(baseContext!!).toString()
)
LogUtils.d("获得当前版本", "map=" + map.toString())
val params = RequestParams(HttpAddress.VERSION_URL)
params.addBodyParameter("app_id", "3")
params.addParameter("version_Code", SystemUtils.getVersionCode(baseContext!!).toString())
xHttpUtil.post_Async(params,object : xHttpUtil.xCallback{
override fun onResponse(result: Any) {
LogUtils.d("检查是否有新的app", "result" + result)
try {
val dataJson: HttpResponsePDO =
Gson().fromJson(result as String, HttpResponsePDO::class.java)
if (dataJson.data != null && dataJson.data!!.size > 0) {
val mapData: Map<String, String> =
dataJson.data!![0] as Map<String, String>
val apkUrl ="${HttpAddress.FILE_HTTP}"+ AESUtil.java_openssl_decrypt(mapData!!["apk_url"]!!)
LogUtils.d("更新apk地址", apkUrl)
//下载安装包并更新
downloadInstall(apkUrl.trim())
}
} catch (e: Exception) {
LogUtils.d("检查更新", e.message!!)
}
}
override fun onError() {
super.onError()
}
})
}
}
2.下载安装包,(下载过程中可能有失败,不完整)
var mInstallUtil:InstallUtil?=null
fun downloadInstall(url: String) {
val params = RequestParams(url)
//自定义保存路径,Environment.getExternalStorageDirectory():SD卡的根目录
//要安装的时候删除文件
Handler().post {
//删除缓存文件
FileUtils.delDir(FinalValue.DIR)
}
//要保存的文件名
val saveFilePath = "${this.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)}/".trim()
val fileNmae=url.substring(url.lastIndexOf("/") + 1)
if (FileUtils.isDirectoryFile(saveFilePath)) {
//安装文件
mInstallUtil = InstallUtil(this@MainActivity, (saveFilePath+fileNmae).trim())
//检查apk是否完整
if ( mInstallUtil!!.getUninatllApkInfo()){
mInstallUtil!!.install()
return
}
//删除缓存文件
FileUtils.delDir(saveFilePath)
}
// params.saveFilePath = FinalValue.APKPATH
// //自动为文件命名
// params.isAutoRename = true
params.saveFilePath =(saveFilePath+fileNmae).trim()
xHttpUtil.get_LoadFile(params, object : xHttpUtil.xCallback {
override fun onResponse(result: Any) {
if (result != null) {
//安装文件
mInstallUtil = InstallUtil(this@MainActivity, saveFilePath)
mInstallUtil!!.install()
}
}
override fun onError() {
super.onError()
Handler().post {
//删除缓存文件
FileUtils.delDir(saveFilePath)
}
}
})
}
3.安装最新包,完整的安装工具
package com.hldm.lbtafxapp.updateutil;
import android.app.Activity;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.provider.Settings;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AlertDialog;
import androidx.core.content.FileProvider;
import java.io.File;
/**
* author : Jeff 5899859876@qq.com
* Csdn :https://blog.youkuaiyun.com/Jeff_YaoJie
* Github: https://github.com/Jay-YaoJie
* Created : 2019-08-21.
* description : android安装应用(适用于各个版本)
*
* https://www.jianshu.com/p/6b7bd2a59096
*/
public class InstallUtil {
private Activity mAct;
private String mPath;//下载下来后文件的路径
public static int UNKNOWN_CODE = 2018;
public InstallUtil(Activity mAct, String mPath) {
this.mAct = mAct;
this.mPath = mPath;
}
public boolean getUninatllApkInfo( ) {
boolean result = false;
try {
PackageManager pm = mAct.getPackageManager();
// LogUtils.e("archiveFilePath", filePath);
PackageInfo info = pm.getPackageArchiveInfo(mPath,PackageManager.GET_ACTIVITIES);
if (info != null) {
result = true;//完整
}
} catch (Exception e) {
result = false;//不完整
}
return result;
}
public void install(){
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) startInstallO();
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) startInstallN();
else startInstall();
}catch (Exception e){
e.printStackTrace();
}
}
/**
* android1.x-6.x
*/
public void startInstall() {
Intent install = new Intent(Intent.ACTION_VIEW);
install.setDataAndType(Uri.parse("file://" + mPath), "application/vnd.android.package-archive");
install.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mAct.startActivity(install);
}
/**
* android7.x
*/
public void startInstallN() {
//参数1 上下文, 参数2 在AndroidManifest中的android:authorities值, 参数3 共享的文件
Uri apkUri = FileProvider.getUriForFile(mAct.getApplicationContext(), "com.hldm.lbtafxapp.provider", new File(mPath));
Intent install = new Intent(Intent.ACTION_VIEW);
//由于没有在Activity环境下启动Activity,设置下面的标签
install.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//添加这一句表示对目标应用临时授权该Uri所代表的文件
install.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
install.setDataAndType(apkUri, "application/vnd.android.package-archive");
mAct.startActivity(install);
}
/**
* android8.x
*/
@RequiresApi(api = Build.VERSION_CODES.O)
public void startInstallO() {
boolean isGranted = mAct.getPackageManager().canRequestPackageInstalls();
if (isGranted) startInstallN();//安装应用的逻辑(写自己的就可以)
else new AlertDialog.Builder(mAct)
.setCancelable(false)
.setTitle("安装应用需要打开未知来源权限,请去设置中开启权限")
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface d, int w) {
Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
mAct.startActivityForResult(intent, UNKNOWN_CODE);
}
})
.show();
}
}