在安卓7.0之前我们的自动更新非常好弄隐式调用就好,但是7.0之后就非常独特了谷歌为了安全加入了新的成员我们一起来看一看.
"唯一的"fileloader
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.deepdream.supercuteai.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" />
</provider>
更新
需要更新
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { // Android 6.0判断,6.0以下跳过。在清单文件注册即可,不用动态请求,这里直接视为有权限
checkpermissionwrite();
Log.d("检测系统是否需要动态权限",Build.VERSION.SDK_INT+"---"+Build.VERSION_CODES.M);
updateapk = string;
}else{
Log.d("检测系统是否需要动态权限",Build.VERSION.SDK_INT+"---"+Build.VERSION_CODES.M);
Gson userMsgBean_6004 = new Gson();
UpdateApkBean_6004 updateApkBean_6004 = userMsgBean_6004.fromJson(string, UpdateApkBean_6004.class);
UpdateApkBean_6004.DataBean data1 = updateApkBean_6004.getData();
String url = data1.getUrl();
final Autodownapk autodownapk = new Autodownapk();
autodownapk.mVersion_name = "new.apk";
autodownapk.mContext = MainActivity.this;
autodownapk.url = url;
runOnUiThread(new Runnable() {
@Override
public void run() {
autodownapk.onStart();
}
});
}
这里注意外部存储和内部存储的规则
// 上下文
public static Context mContext;
// 进度条
private ProgressBar mProgressBar;
// 对话框
private Dialog mDownloadDialog;
// 判断是否停止
private boolean mIsCancel = false;
// 进度
private int mProgress;
// 文件保存路径
private String mSavePath;
// 版本名称
public static String mVersion_name;
// 请求链接
public static String url;
public void onStart(){
mIsCancel=false;
// 展示对话框
showDownloadDialog();
}
/*
* 显示正在下载对话框
*/
protected void showDownloadDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
View view = LayoutInflater.from(mContext).inflate(R.layout.dialog_progress, null);
mProgressBar = (ProgressBar) view.findViewById(R.id.id_progress);
builder.setView(view);
builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// 隐藏当前对话框
dialog.dismiss();
// 设置下载状态为取消
mIsCancel = true;
}
});
mDownloadDialog = builder.create();
mDownloadDialog.show();
// 下载文件
downloadAPK();
}
/*
* 开启新线程下载apk文件
*/
private void downloadAPK() {
new Thread(new Runnable() {
@Override
public void run() {
try{
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
String sdPath = null;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
sdPath = Environment.getExternalStorageDirectory() + "/";
}
}else{
sdPath = mContext.getFilesDir() + "/";
}
mSavePath = sdPath + "jikedownload";
File dir = new File(mSavePath);
if (!dir.exists()){
dir.mkdir();
}
// 下载文件
HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
conn.connect();
InputStream is = conn.getInputStream();
int length = conn.getContentLength();
File apkFile = new File(mSavePath, mVersion_name);
FileOutputStream fos = new FileOutputStream(apkFile);
int count = 0;
byte[] buffer = new byte[1024];
while (!mIsCancel){
int numread = is.read(buffer);
count += numread;
// 计算进度条的当前位置
mProgress = (int) (((float)count/length) * 100);
// 更新进度条
mUpdateProgressHandler.sendEmptyMessage(1);
// 下载完成
if (numread < 0){
mUpdateProgressHandler.sendEmptyMessage(2);
break;
}
fos.write(buffer, 0, numread);
}
fos.close();
is.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}).start();
}
/**
* 接收消息
*/
private Handler mUpdateProgressHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case 1:
// 设置进度条
mProgressBar.setProgress(mProgress);
break;
case 2:
// 隐藏当前下载对话框
mDownloadDialog.dismiss();
// 安装 APK 文件
installAPK();
}
};
};
/*
* 下载到本地后执行安装
*/
protected void installAPK() {
File apkFile = new File(mSavePath, mVersion_name);
if (!apkFile.exists()){
return;
}
Uri uri = Uri.parse("file://" + apkFile.toString());
Log.d("没有课程",uri+"");
autoInstallApk(uri,apkFile.toString());
}
private void autoInstallApk(Uri uri,String apk) {
Intent intent = new Intent(Intent.ACTION_VIEW);
// intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
intent.setDataAndType(uri, "application/vnd.android.package-archive");
} else {
Toast.makeText(mContext, "去应用市场更新", Toast.LENGTH_SHORT).show();
// 第二个参数,即第一步中配置的authorities
Uri contentUri = FileProvider.getUriForFile(mContext, "com.deepdream.supercuteai.fileprovider", new File(apk));
intent.setDataAndType(contentUri, "application/vnd.android.package-archive");
// 声明需要的临时的权限
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
}
mContext.startActivity(intent);
}