Android8.0 应用内升级安装程序
1 判断升级
第一步自然是通过后台接口获取最新版本号判断是否需要升级,这里不多做记录;
2 下载应用
判断需要下载后,下载应用;
这里定义一个接口,回调下载失败,下载中,下载完成三种状态:
public interface OnDownLoadListener {
//下载成功
void onDownloadSuccess();
//下载进度
void onDownloading(int progress);
//下载失败
void onDownloadFailed();
}
那么下载就应该是这样:
Request request = new Request.Builder()
.addHeader("Cookie", cookie)
.url(urlBuilder.build())
.get()
.build();
getClientInstance().newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.e(TAG, "onFailure: " + e);
listener.onDownloadFailed();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (!response.isSuccessful()) {
Log.e(TAG, "onResponse: failed,error code: " + response.code());
listener.onDownloadFailed();
}
InputStream is = null;
byte[] buf = new byte[2048];
int len = 0;
FileOutputStream fos = null;
//存储下载文件的目录
File file = new File(Environment.getExternalStorageDirectory()
+ Configs.SystemPicture.SAVE_DIRECTORY,
apkType + Configs.SAVE_APK_NAME);
if (!file.exists()) {
file.createNewFile();
}
try {
is = response.body().byteStream();
long total = response.body().contentLength();
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) {
listener.onDownloadFailed();
} finally {
try {
if (is != null) {
is.close();
}
} catch (IOException e) {
}
try {
if (fos != null) {
fos.close();
}
} catch (IOException e) {
}
}
}
});
注意,这里既然涉及到保存到硬盘中就需要申请读写权限;
3 将进度条显示到通知中
在一个单独的Service
中操作下载进度显示这是必须的,调用下载方法并实现这个回调,使用Handler
来发送消息:
URLUtils.downloadApk(VersionUpdateService.this, finalApkType, version, new URLUtils.OnDownLoadListener() {
@Override
public void onDownloadSuccess() {
Message msg = Message.obtain();
msg.what = MSG_APK_DOWNLOAD_FINISH;
handler.sendMessage(msg);
}
@Override
public void onDownloading(final int progress) {
Message msg = Message.obtain();
msg.what = MSG_APK_DOWNLOAD_PROGRESS;
msg.arg1 = progress;
handler.sendMessage(msg);
}
@Override
public void onDownloadFailed() {
Message msg = Message.obtain();
msg.what = MSG_APK_DOWNLOAD_FAILED;
handler.sendMessage(msg);
}
});
4 发送通知
发送通知,自定义通知布局什么的都不赘述,注意Android8.0的通知需要设置NotificationChannel
;
5 安装应用
下载完成之后,自然就要安装应用,安装应用首先就需要获取到文件,Android7.0以后获取文件需要共享```AndroidManifest.xml````,配置如下:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
在res\xml\
中新建文件file_paths.xml
,属性可自己设置:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<paths>
<external-path name="camera_photos" path=""/>
</paths>
</resources>
安装应用:
Intent intent = new Intent(Intent.ACTION_VIEW);
//获取指定位置文件
File file = new File(Environment.getExternalStorageDirectory()
+ Configs.SystemPicture.SAVE_DIRECTORY,
finalApkType + Configs.SAVE_APK_NAME);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
String packageName = getPackageName();
Uri contentUri = FileProvider.getUriForFile(VersionUpdateService.this,
packageName + ".fileprovider", file);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(contentUri, "application/vnd.android.package-archive");
} else {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
}
startActivity(intent);
同时,在Android8.0及以后,安装应用需要打开安装第三方应用权限许可,如下判断,或申请:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
boolean installAllowed=getPackageManager().canRequestPackageInstalls();
if (installAllowed){
//权限许可,安装应用
}else {
Intent intent1=new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent1);
}
}
网友评论