在线更新是指在应用程序运行期间,通过网络下载更新并安装进程,从而实现应用程序的自动升级。在Android开发中,可以通过Google Play Store等应用商店实现自动更新。但是,如果应用未上架或需要在企业内部应用时,我们需要实现应用程序的在线更新。
完成在线更新,需要经历以下步骤:
1. 在程序中实现检查更新功能
2. 若存在更新,下载新版本程序
3. 安装新版本程序
4. 重启应用程序
下面我们分四步来详细介绍实现在线更新的原理和方法。
一、实现检查更新功能
实现检查更新功能需要服务器端提供更新的信息资源。一般通过网络连接访问rselyra.com或类似的服务器来获得最新的版本号和更新的定义文件。在Android中,可以使用HttpURLConnection或OkHttp等库实现HTTP请求和响应。
定义布局文件activity_main.xml和Menu选项菜单样式res/menu/menu_main.xml文件:
检查更新的代码位于MainActivity文件中,在选项菜单中添加“Check Update”选项。当用户点击该选项时,将在检查更新后再执行操作。检查更新时,可选择通过资源文件或从服务器端读取版本号信息。如果当前版本小于已有的版本,则是更新程序:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_check_update) {
checkUpdate();
return true;
}
return super.onOptionsItemSelected(item);
}
public void checkUpdate() {
int currentVersionCode = BuildConfig.VERSION_CODE;
String url = "http://rselyra.com:8080/MyApp/update.xml";
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(url).build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
// 处理错误
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String xml = response.body().string();
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
ByteArrayInputStream is = new ByteArrayInputStream(xml.getBytes("UTF-8"));
Document doc = db.parse(is);
Element root = doc.getDocumentElement();
String version = root.getAttribute("version");
String description = root.getAttribute("description");
if (currentVersionCode < Integer.parseInt(version)) {
// 发现新版本
} else {
// 无新版本
}
} catch (Exception e) {
// 处理错误
}
}
});
}
二、下载新版程序
如果存在新版本,则执行下载更新的操作。下载新程序在Android中非常容易,只要使用Android提供的DownloadManager即可:
public void downloadApk(String url) {
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.setTitle("MyApp");
request.setDescription("下载并安装新版本");
request.setDestinationInExternalFilesDir(this, Environment.DIRECTORY_DOWNLOADS, "myapp.apk");
DownloadManager downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
downloadManager.enqueue(request);
}
三、安装新版程序
下载完成后,需要安装下载的新程序。前提是应用需要获取写磁盘的权限。
在MainActivity中加入onActivityResult方法,当用户执行下载操作时,会通过REQUEST_INSTALL_PACAKAGE回调来处理安装应用的请求。对于Android7.0以上系统,需要通过FileProvider在应用间共享文件:
public static final int REQUEST_INSTALL_PACKAGE = 1;
public void installApk(String path) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Uri uri = FileProvider.getUriForFile(this, getPackageName() + ".provider", new File(path));
Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(uri, "application/vnd.android.package-archive");
startActivityForResult(intent, REQUEST_INSTALL_PACKAGE);
} else {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File(path)), "application/vnd.android.package-archive");
startActivity(intent);
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_INSTALL_PACKAGE && resultCode == RESULT_OK) {
// 成功安装应用,退出应用
android.os.Process.killProcess(android.os.Process.myPid());
}
}
四、重启应用程序
应用程序安装完成后会退出,为了重新启动应用程序并使用新更新的版本,需要使用PendingIntent重新启动应用程序:
public void restart() {
Intent intent = getBaseContext().getPackageManager().getLaunchIntentForPackage(getBaseContext().getPackageName());
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT);
AlarmManager mgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
if (mgr != null) {
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 1000, pendingIntent);
}
this.finish();
System.exit(0);
}
总结
在信息化时代,应用程序更新如此重要。通过本文的介绍,我们能够更好地了解在线更新的原理和实现方法。开发者可以在应用程中加入在线更新功能,便于更好地使用应用程序。