需要一个接口返回 参数 versionCode和 下载链接,安卓6.0以上需要动态添加权限,
7.0以上需要FileProvider,8.0以上需要添加权限
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
思路:通过后台返回 versioncode 对比当前版本的versioncode,来确定是否需要更新
动态请求权限的代码就不写了
首先写一个FileProvider
清单文件中添加
<application
android:name=".App"
android:allowBackup="true"
android:icon="@mipmap/logo"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
....
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="你的包名.FileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
</application>
接下来是file_paths 文件
<paths>
<external-path
name="files_root"
path="Android/data/你的包名/" />
<external-path
name="external_storage_root"
path="." />
<external-path
name="rc_external_path"
path="." />
<root-path
name="rc_root_path"
path="" />
</paths>
封装自动更新的类
public class AutoUpdate {
private ProgressDialog mProgress;
private int progress; //apk下载的进度
private Activity activity;
public AutoUpdate(Activity activity) {
this.activity = activity;
}
/**
* 下载的apk地址
*/
private final int DOWNLOAD = 1;
private final int DOWNLOAD_FINISH = 2;
private String mSavePath;
private Handler downHandler = new Handler() {
@Override
public void handleMessage(android.os.Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case DOWNLOAD:
mProgress.setProgress(progress);
break;
case DOWNLOAD_FINISH:
installApk();
break;
}
}
};
UpdataBean checkVistionBean;
/**
* 联网查询版本
*/
String newdownurl = "";//下载apk网址
public void requestVersionData() {
new Volley_Utils(new Interface_volley_respose() {
@Override
public void onSuccesses(String respose) {
checkVistionBean=new Gson().fromJson(respose,UpdataBean.class);
newdownurl = checkVistionBean.getData().getDownload_link();//下载新版本的网址
int newVersion = (Integer) checkVistionBean.getData().getVersion_number();//新的版本号
int curVersionCode = getVersionInfo();
if (curVersionCode == Integer.MAX_VALUE) {
return;
} else {
if (curVersionCode < newVersion) {//有新版本
showUpdateDialog(newVersion, newdownurl);
} else {//没有新版本
return;
}
}
}
@Override
public void onError(int error) {
LogUtils.LOG("ceshi","c错误码"+error,"updataapp");
}
}).Http(Urls.Baseurl+Urls.autoupdata, activity, 0);
}
/**
* 得到当前版本号
*
* @return
*/
private int getVersionInfo() {
PackageManager pm =activity. getPackageManager();
// flag写一个0就是全部拿到封装在PackageInfo对象中
try {
PackageInfo info = pm.getPackageInfo(activity.getPackageName(), 0);
return info.versionCode;
} catch (Exception e) {
e.printStackTrace();
return Integer.MAX_VALUE;
}
}
private void showUpdateDialog(final int code, final String apkurl) {
activity. runOnUiThread(new Runnable() {
@Override
public void run() {
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle("升级提示");
builder.setMessage("有新版本,请更新!");
builder.setCancelable(false);
builder.setPositiveButton("立即更新", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
mProgress = new ProgressDialog(activity);
mProgress.setMax(100);
mProgress.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mProgress.setMessage("正在下载...");
// 对话框显示出来
mProgress.setCancelable(false);
mProgress.show();
/**
* 判断是否有存储权限
*/
int checkWriteStoragePermission = ContextCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);//获取系统是否被授予该种权限
if (checkWriteStoragePermission != PackageManager.PERMISSION_GRANTED) {//如果没有被授予
mProgress.dismiss();
ToastUtils.showToast(activity,"请打开应用的存储权限");
ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 0x123);
//请求获取该种权限
}else{
// 直接下载
new downloadApkThread().start();
}
}
});
builder.show();
}
});
}
/**
* 下载apk
*/
private boolean cancelUpdate = false;
private class downloadApkThread extends Thread {
@Override
public void run() {
try {
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
String sdpath = Environment.getExternalStorageDirectory() + "/";
mSavePath = sdpath + "download";
URL url = new URL(newdownurl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.connect();
int length = conn.getContentLength();
InputStream is = conn.getInputStream();
File file = new File(mSavePath);
if (!file.exists()) {
file.mkdir();
}
File apkFile = new File(mSavePath, "version.apk");
FileOutputStream fos = new FileOutputStream(apkFile);
int count = 0;
byte buf[] = new byte[1024];
do {
int numread = is.read(buf);
count += numread;
progress = (int) (((float) count / length) * 100);
downHandler.sendEmptyMessage(DOWNLOAD);
if (numread <= 0) {
downHandler.sendEmptyMessage(DOWNLOAD_FINISH);
cancelUpdate = true;
mProgress.dismiss();
break;
}
fos.write(buf, 0, numread);
} while (!cancelUpdate);
fos.close();
is.close();
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 安装APK
*/
private void installApk() {
File newFile = new File(mSavePath, "version.apk");
Intent intent = new Intent(Intent.ACTION_VIEW);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Uri contentUri = FileProvider.getUriForFile(activity, "你的包名.FileProvider", newFile);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(contentUri, "application/vnd.android.package-archive");
} else {
intent.setDataAndType(Uri.fromFile(newFile), "application/vnd.android.package-archive");
}
activity.startActivity(intent);
android.os.Process.killProcess(android.os.Process.myPid());
}
}
在app的mainactivity中调用
//检测是否更新
autoUpdate = new AutoUpdate(MainActivity.this);//实例化
autoUpdate.requestVersionData();