安卓APP自动更新功能实现
安卓APP自动更新功能实现
- 前言
- 代码实现
前言
安卓App自动更新基本上是每个App都需要具备的功能,接下来介绍一下实现自动更新的步骤。
代码实现
App自动更新主要分为新版本检测、升级弹窗、下载升级包、安装app这4个步骤,以下为MainActivity的实现代码(注意:目标升级版本和升级包下载地址实际需要向平台拉取):
package com.example.testupgrade;import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.FileProvider;import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;import java.io.File;public class MainActivity extends AppCompatActivity {private final String TAG = "Jason";private File file;private TextView textView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initView();if(versionCheck()) {showTip(this);}}//在主界面显示app版本号,非必要private void initView() {textView = findViewById(R.id.tv_version);textView.setText("version:" + getVersionName());}//新版本检测private boolean versionCheck() {String targetVersion = "xxx"; //todo 实际目标版本号应向平台查询Log.d(TAG, "versionCheck version:" + getVersionName());Log.d(TAG, "versionCheck targetVersion:" + targetVersion);if(getVersionName().contentEquals(targetVersion)) {return false;} else {return true;}}//升级弹窗private void showTip(Context context) {AlertDialog dialog = new AlertDialog.Builder(context).setTitle("升级提示").setMessage("检测到新版本,请升级").setNeutralButton("升级", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {doDownload();}}).setNegativeButton("取消", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {dialog.dismiss();}}).show();dialog.setCanceledOnTouchOutside(false);//可选dialog.setCancelable(false);//可选}//下载升级包private void doDownload() {String downloadUrl = "https://xxx"; //todo 实际下载地址应向平台查询String parentPath = "";try {if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {parentPath = this.getExternalFilesDir(null).getPath();} else {parentPath = this.getFilesDir().getPath();}} catch (Exception e) {Log.d(TAG, "doDownload e:" + e.getMessage());}Log.d(TAG, "doDownload parentPath:" + parentPath);file = new File(parentPath, "myhouse.apk");final String filePath = file.getAbsolutePath();//如果已有文件,删除if (file.exists()) {Log.d(TAG, "doDownload delete APK");file.delete();}try {DownloadUtil.get().download(downloadUrl, filePath, new DownloadUtil.OnDownloadListener() {@Overridepublic void onDownloadSuccess() {//成功Log.d(TAG, "doDownload download success");installApk();}@Overridepublic void onDownloading(int progress) {//进度//Log.d(TAG, "doDownload download:" + progress +"%");}@Overridepublic void onDownloadFailed() {//失败Log.d(TAG, "doDownload download fail");}});} catch (Exception e) {Log.d(TAG, "doDownload e2:" + e.getMessage());}}//安装appprivate void installApk() {Intent intent = new Intent(Intent.ACTION_VIEW);Uri data;//7.0以上安卓系统安装app需要通过fileProvider(需要在AndroidManifest.xml声明)if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {data = FileProvider.getUriForFile(this, "com.example.testupgrade.provider", file);intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);Log.d(TAG,"installApk 7.0data:" + data);} else {data = Uri.fromFile(file);Log.d(TAG,"installApk data:" + data);}intent.setDataAndType(data, "application/vnd.android.package-archive");this.startActivity(intent);}//获取软件版本号private String getVersionName() {String versionName = "";try {versionName = getApplicationContext().getPackageManager().getPackageInfo(getApplicationContext().getPackageName(), 0).versionName;} catch (PackageManager.NameNotFoundException e) {e.printStackTrace();}return versionName;}
}
上述下载功能基于okhttp实现的DownloadUtil工具类,具体代码如下:
package com.example.testupgrade;import android.os.Environment;
import android.util.Log;import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;public class DownloadUtil {private static DownloadUtil downloadUtil;private final OkHttpClient okHttpClient;public static DownloadUtil get() {if (downloadUtil == null) {Log.d("Jason", "DownloadUtil get new DownloadUtil");downloadUtil = new DownloadUtil();}return downloadUtil;}private DownloadUtil() {okHttpClient = new OkHttpClient();}/*** @param url 下载连接* @param filePath 储存下载文件的SDCard目录* @param listener 下载监听*/public void download(final String url, final String filePath, final OnDownloadListener listener) {Log.d("Jason", "DownloadUtil download start");Request request = new Request.Builder().url(url).build();Log.d("Jason", "DownloadUtil request:" + request.toString());okHttpClient.newCall(request).enqueue(new Callback() {@Overridepublic void onFailure(Call call, IOException e) {Log.d("Jason", "DownloadUtil onFailure e:" + e.getMessage());listener.onDownloadFailed();}@Overridepublic void onResponse(Call call, Response response) throws IOException {Log.d("Jason", "DownloadUtil onResponse start");InputStream is = null;byte[] buf = new byte[2048];int len = 0;FileOutputStream fos = null;// 储存下载文件的目录//String savePath = isExistDir(saveDir);Log.d("Jason", "DownloadUtil filePath:" + filePath);try {is = response.body().byteStream();long total = response.body().contentLength();//File file = new File(savePath, getNameFromUrl(url));File file = new File(filePath);fos = new FileOutputStream(file);long sum = 0;while ((len = is.read(buf)) != -1) {fos.write(buf, 0, len);sum += len;int progress = (int) (sum * 1.0f / total * 100);// 下载中listener.onDownloading(progress);}fos.flush();// 下载完成listener.onDownloadSuccess();} catch (Exception e) {Log.d("Jason", "DownloadUtil onResponse e1:" + e.getMessage());listener.onDownloadFailed();} finally {try {if (is != null) {is.close();}} catch (IOException e) {Log.d("Jason", "DownloadUtil onResponse e2:" + e.getMessage());}try {if (fos != null) {fos.close();}} catch (IOException e) {Log.d("Jason", "DownloadUtil onResponse e3:" + e.getMessage());}}}});}/*** @param saveDir* @return* @throws IOException* 判断下载目录是否存在*/private String isExistDir(String saveDir) throws IOException {// 下载位置File downloadFile = new File(Environment.getExternalStorageDirectory(), saveDir);if (!downloadFile.mkdirs()) {downloadFile.createNewFile();}String savePath = downloadFile.getAbsolutePath();return savePath;}/*** @param url* @return* 从下载连接中解析出文件名*/public static String getNameFromUrl(String url) {return url.substring(url.lastIndexOf("/") + 1);}public interface OnDownloadListener {/*** 下载成功*/void onDownloadSuccess();/*** @param progress* 下载进度*/void onDownloading(int progress);/*** 下载失败*/void onDownloadFailed();}
}
注:为了使用okhttp,需要在build.gradle添加如下配置:
implementation 'com.squareup.okhttp3:okhttp:4.3.1'
为了实现下载和安装功能,需要在AndroidManifest.xml声明网络、SD卡读写和安装包权限;另外,为了实现7.0以上安卓系统的app安装,还需要声明fileProvider,具体代码如下:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.example.testupgrade"><uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/><uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:networkSecurityConfig="@xml/network_security_config"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/AppTheme"><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="${applicationId}.provider"android:exported="false"android:grantUriPermissions="true"><meta-dataandroid:name="android.support.FILE_PROVIDER_PATHS"android:resource="@xml/file_path" /></provider></application></manifest>
添加fileProvider对应的file_path.xml
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android"><paths><external-path path="" name="download"/></paths>
</resources>
添加network_security_config.xml,配置可访问http地址:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config><base-config cleartextTrafficPermitted="true" />
</network-security-config>
安卓APP自动更新功能实现相关推荐
- 安卓APP自动更新实现
一.参考文献 简单实现安卓app自动更新功能 - 简书 安卓app自动更新功能完美实现_白云天的博客-CSDN博客_android 自动更新 Android 实现自动更新及强制更新功能_farley的 ...
- Uniapp 实现app自动更新功能
APP.vue文件中 <script>export default {data: function() {return {version: "1.5.4"//版本号}} ...
- java编写实现更新_Android实现APP自动更新功能
现在一般的android软件都是需要不断更新的,当你打开某个app的时候,如果有新的版本,它会提示你有新版本需要更新.该小程序实现的就是这个功能. 该小程序的特点是,当有更新时,会弹出一个提示框,点击 ...
- Android如何实现APP自动更新
先来看看要实现的效果图: 对于安卓用户来说,手机应用市场说满天飞可是一点都不夸张,比如小米,魅族,百度,360,机锋,应用宝等等,当我们想上线一款新版本APP时,先不说渠道打包的麻烦,单纯指上传APP ...
- 记录--uniapp上如何实现安卓app微信登录功能(操作流程总结)
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 uniapp上如何实现安卓app微信登录功能?下面本篇文章给大家分享一下uniapp上实现安卓app微信登录的权限申请.开发的具体操作流程 ...
- Android 程序自动更新功能模块实现
2019独角兽企业重金招聘Python工程师标准>>> Android 程序自动更新功能模块实现 在程序启动的时候检测服务器上有没有对应版本更新,如果有更新,提示用户是否更新. 在程 ...
- android app 自动更新,AndroidUpdateDemo
Android课程-App更新策略 @(Android) 第一节 课程介绍 概述 App更新是应用当中很常见的一个功能,基本上联网的app都应该具备这样的功能,对于更新迭代比较快速的产品,应用更新升级 ...
- 如何关闭苹果手机自动扣费_教你关闭苹果手机系统的自动更新功能,旧手机还能再用几年!...
大家都知道,苹果手机在更新几个大版本后,手机不是变得非常卡,就是非常的耗电,大大的缩短了手机的使用寿命. 所以,许多人都不会选择更新系统,但是手机只要连上WiFi并且在充电状态,就会在半夜自动更新系统 ...
- android自动更新demo,Android程序自动更新功能模块的实现方法【附完整demo源码下载】...
本文实例讲述了Android程序自动更新功能模块的实现方法.分享给大家供大家参考,具体如下: 在程序启动的时候检测服务器上有没有对应版本更新,如果有更新,提示用户是否更新. 在程序启动的时候首先调用更 ...
最新文章
- Uncaught TypeError: Object [object Object] has no method 'xxx'
- MySQL / 多版本并发控制
- gtk+学习笔记(五)
- Java实训项目:GUI学生信息管理系统(2019)【上】
- Golang: How to sort struct with multiple sort parameters?
- Python调用海康威视网络相机_调用海康SDK
- ams1117封装尺寸
- matlab求一维热传导方程数值解代码,一维热传导方程的数值解
- Pycharm快速入门(6) — 版本控制
- 云vr和传统vr_宣布我们的VR艺术家居住地
- 终端文本编辑神器--Vim命令详解。如何配置使用Vim、Vim插件?
- 分段函数的期望和方差_概率论中数学期望什么时候不存在?
- android简历!写给即将正在找工作的Android攻城狮,已拿offer
- 【最新】M1芯片Mac安装PS2021/2020卡在启动页解决教程下载方法
- 腾讯QQ的验证码,很黄很暴力
- linux内核添加系统调用(详细)
- 我奋斗了18年才和你坐在一起喝咖啡(转)
- hdu 6217 BBP Formula
- java模拟post请求上传图片
- ArcGIS Pro 中的编辑器