首先需要添加权限,否则下载完成之后是无法跳转到安装页面的
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" /><!-- 自动更新URI跳转安装时需要 -->
1:请求接口如有新版本则提示更新(第一张图)
if (data.getMsg().equals("有新版本") && appUpdateBean != null) {
AppUpdateDialog dialog = new AppUpdateDialog(MainActivity.this, "发现新版本", appUpdateBean.getLevel(), appUpdateBean.getCreatetime(), appUpdateBean.getContent(), "", "立即更新", new OnButtonClick() {
@Override
public void button01ClickListener() {
}
@Override
public void button02ClickListener() {
//立即更新
Log.v(TAG, "url==" + appUpdateBean.getUrl());
if (appUpdateBean.getUrl() == null) {
return;
}
// AppUpdateUtils.dialogUpdateVersion(appUpdateBean.getUrl(), MainActivity.this);
AppUpdateUtils.downLoadApk(MainActivity.this, appUpdateBean.getUrl());
}
});
dialog.show();
dialog.setCanceledOnTouchOutside(false);
dialog.setCancelable(false);
}
/**
* date:2020/8/4
* author:wsm(Administrator)
* funcation:版本更新
*/
public class AppUpdateDialog extends Dialog {
public static final String TAG = "AppUpdateDialog";
private Activity mActivity;
private String title;
private String versionname;
private String time;
private String content;
private String button1Text;
private String button2Text;
private OnButtonClick onButtonClicks;
private RelativeLayout mRl_progress;
private ProgressBar mProgressBar;
private TextView mTxt_progess;
public AppUpdateDialog(Activity context, String title, String version, String cratetime, String content, String button1Text,
String button2Text, final OnButtonClick onButtonClick) {
super(context, R.style.MyDialog);
mActivity = context;
this.title = title;
this.versionname = version;
this.time = cratetime;
this.content = content;
this.button1Text = button1Text;
this.button2Text = button2Text;
this.onButtonClicks = onButtonClick;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.public_updateapp);
TextView tv_title = (TextView) findViewById(R.id.tv_title);
TextView tv_version = (TextView) findViewById(R.id.tv_version);
TextView tv_time = (TextView) findViewById(R.id.tv_time);
TextView tv_content = (TextView) findViewById(R.id.tv_content);
TextView tv_ok = (TextView) findViewById(R.id.tv_ok);
mRl_progress = (RelativeLayout) findViewById(R.id.rl_progress);
mProgressBar = (ProgressBar) findViewById(R.id.progressBar);
mTxt_progess = (TextView) findViewById(R.id.txt_progess);
tv_title.setText(title);
tv_version.setText(versionname);
tv_time.setText(time);
tv_content.setText(content);
tv_ok.setText("立即更新");
initBroadcastListener();
tv_ok.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
tv_ok.setText("正在更新,请稍等。。。");
onButtonClicks.button02ClickListener();
}
});
}
/**
* 接收广播监听下载进度
*/
private void initBroadcastListener() {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("STATUS_RUNNING");
BroadcastReceiver Receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("STATUS_RUNNING")) {
String progress = intent.getStringExtra("progress");
if (Integer.parseInt(progress) > 0) {
//下载进度大于1则显示进度条
mRl_progress.setVisibility(View.VISIBLE);
mProgressBar.setProgress(Integer.parseInt(progress));
mTxt_progess.setText(progress + "%");
}
}
}
};
mActivity.registerReceiver(Receiver, intentFilter);
}
}
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/rlcommon"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:background="@drawable/white10"
android:orientation="vertical">
<TextView
android:id="@+id/tv_title"
android:layout_width="match_parent"
android:layout_height="40dp"
android:gravity="center"
android:paddingTop="10dp"
android:text="提示"
android:textColor="@color/txt0"
android:textSize="18sp"
android:visibility="visible" />
<TextView
android:id="@+id/tv_version"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center"
android:textSize="14sp" />
<TextView
android:id="@+id/tv_time"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center"
android:textSize="14sp" />
<TextView
android:id="@+id/tv_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center"
android:textSize="14sp" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="15dp"
android:background="@color/search" />
<RelativeLayout
android:id="@+id/rl_progress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:visibility="gone">
<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="3dp"
android:layout_centerVertical="true"
android:layout_marginRight="5dp"
android:layout_toLeftOf="@id/txt_progess"
android:progressDrawable="@drawable/progressbar_carch" />
<TextView
android:id="@+id/txt_progess"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:text="0%"
android:textColor="@color/txtblack" />
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="5dp">
<RelativeLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:visibility="gone">
<TextView
android:id="@+id/tv_cancel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center"
android:padding="10dp"
android:text="否"
android:textSize="14sp" />
</RelativeLayout>
<TextView
android:layout_width="1dp"
android:layout_height="match_parent"
android:background="@color/search" />
<RelativeLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1">
<TextView
android:id="@+id/tv_ok"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center"
android:padding="10dp"
android:text="立即更新"
android:textColor="@color/txt0"
android:textSize="16sp" />
</RelativeLayout>
</LinearLayout>
</LinearLayout>
</RelativeLayout>
2:点击立即更新(第二张图)
public class AppUpdateUtils {
public static final String TAG = "AppUpdateUtils";
private static long mId;
private static DownloadManager mDownloadManager;
private static Activity mActivity;
public static void downLoadApk(Activity activity, String url) {
mActivity = activity;
//以下两行代码可以让下载的apk文件被直接安装而不用使用Fileprovider,系统7.0或者以上才启动。
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
StrictMode.VmPolicy.Builder localBuilder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(localBuilder.build());
}
//创建request对象
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
//设置什么网络情况下可以下载
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);
//设置通知栏的标题
request.setTitle("下载");
//设置通知栏的message
request.setDescription("应用正在下载.....");
//7.0以上的系统适配
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
request.setRequiresDeviceIdle(false);
request.setRequiresCharging(false);
}
//制定下载的文件类型为APK
request.setMimeType("application/vnd.android.package-archive");
//设置漫游状态下是否可以下载
request.setAllowedOverRoaming(false);
// 下载过程和下载完成后通知栏有通知消息。
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE | DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
//大于11版本手机允许扫描
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
//表示允许MediaScanner扫描到这个文件,默认不允许。
request.allowScanningByMediaScanner();
}
//设置文件存放目录
request.setDestinationInExternalFilesDir(activity, Environment.DIRECTORY_DOWNLOADS, "update.apk");
//获取系统服务
mDownloadManager = (DownloadManager) activity.getSystemService(Context.DOWNLOAD_SERVICE);
//进行下载
//注册广播接收者,监听下载状态
mId = mDownloadManager.enqueue(request);
activity.registerReceiver(receiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
//用于监听显示下载进度
mDownloadObserver = new DownloadChangeObserver(null);
mActivity.getContentResolver().registerContentObserver(CONTENT_URI, true, mDownloadObserver);
}
//广播监听下载的各个状态
private static BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
checkStatus();
}
};
//检查下载状态
private static void checkStatus() {
DownloadManager.Query query = new DownloadManager.Query();
//通过下载的id查找
query.setFilterById(mId);
Cursor cursor = mDownloadManager.query(query);
if (cursor.moveToFirst()) {
int status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
switch (status) {
//下载暂停
case DownloadManager.STATUS_PAUSED:
Log.v(TAG, "checkStatus 下载暂停");
break;
//下载延迟
case DownloadManager.STATUS_PENDING:
Log.v(TAG, "checkStatus 下载延迟");
break;
//正在下载
case DownloadManager.STATUS_RUNNING:
Log.v(TAG, "checkStatus 正在下载");
break;
//下载完成
case DownloadManager.STATUS_SUCCESSFUL:
ToastUtil.show("下载完成");
Log.v(TAG, "checkStatus 下载完成");
//下载完成安装APK
installAPK();
// cursor.close();
break;
//下载失败
case DownloadManager.STATUS_FAILED:
Log.v(TAG, "checkStatus 下载失败");
ToastUtil.show("下载失败");
// cursor.close();
mActivity.unregisterReceiver(receiver);
break;
}
}
}
//用于显示下载进度
static class DownloadChangeObserver extends ContentObserver {
public DownloadChangeObserver(Handler handler) {
super(handler);
}
@Override
public void onChange(boolean selfChange) {
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(mId);
DownloadManager dManager = (DownloadManager) mActivity.getSystemService(Context.DOWNLOAD_SERVICE);
final Cursor cursor = dManager.query(query);
if (cursor != null && cursor.moveToFirst()) {
final int totalColumn = cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES);
final int currentColumn = cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR);
int totalSize = cursor.getInt(totalColumn);
int currentSize = cursor.getInt(currentColumn);
float percent = (float) currentSize / (float) totalSize;
int progress = Math.round(percent * 100);
Log.v(TAG, "下载进度==" + progress);
//发送广播进行界面显示
Intent intent = new Intent("STATUS_RUNNING");
intent.putExtra("progress", progress + "");
mActivity.sendBroadcast(intent);
}
}
}
private static void installAPK() {
Log.v(TAG, "installAPK 正在安装");
// 由于没有在Activity环境下启动Activity,设置下面的标签
//Android 7.0以上要使用FileProvider
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Log.v(TAG, "Build.VERSION.SDK_INT>=24");
//下载的路径
File file = new File(mActivity.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "update.apk");
Log.v(TAG, "file==" + file);
//参数1 上下文, 参数2 Provider主机地址 和配置文件中保持一致 参数3 共享的文件
Uri apkUri = FileProvider.getUriForFile(mActivity, "这里是你的清单文件中配置包名.fileprovider", file);
//添加这一句表示对目标应用临时授权该Uri所代表的文件
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
mActivity.startActivity(intent);
} else {
Log.v(TAG, "老方法");
//以前的启动方法
File file = new File(mActivity.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "update.apk");
Intent install = new Intent(Intent.ACTION_VIEW);
install.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
install.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mActivity.startActivity(install);
}
}
}
3:配置清单文件相关
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="app包名.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths" />
</provider>
4:res文件下新建xml文件夹,新建filepaths
<?xml version="1.0" encoding="utf-8"?>
<resources>
<paths>
<external-path
name="download"
path="" />
</paths>
</resources>
5:注意加入需要的权限,例如存储权限网络权限等。。
到这里效果就实现了,当下载完成后打开系统自带更新页面安装app即可
另外一种方式逻辑为跳转应用市场更新
app版本跳转应用市场更新