版本检查
final String verUrl = davUrl + getPackageName() + ".md"; //你的版本号所在文件
final Message msg = new Message();
msg.what = 100;
final Bundle bundle = new Bundle();
new Thread(new Runnable() {
@Override
public void run() {
OkHttpClient client = new OkHttpClient();
//这里有一些验证信息,我用的是webdav,如果你不需要,直接把header拿掉就好
Request request = new Request.Builder().url(verUrl).header("Authorization", Credentials.basic("xxx", "xxx")).build();
try (Response response = client.newCall(request).execute()) {
String ver = response.body().string().replace("\n", "");
String localVer = getPackageManager().getPackageInfo(getPackageName(), 0).versionName;
if (Double.parseDouble(ver) > Double.parseDouble(localVer)) {
downApk(ver);
}
bundle.putString("result", "New Version: " + ver + "\nOld Version: " + localVer);
} catch (Exception e) {
bundle.putString("result", "error: " + e.getMessage());
}
msg.setData(bundle);
handler.sendMessage(msg);
}
}).start();
下载应用
private void downApk(String ver){
final String downUrl = davUrl + getPackageName() + "_ver_" + ver + ".apk";
final Message msg = new Message();
msg.what = 101;
final Bundle bundle = new Bundle();
//这里有一些验证信息,我用的是webdav,如果你不需要,直接把header拿掉就好
Request request = new Request.Builder().url(downUrl).header("Authorization", Credentials.basic("xxx", "xxx")).build();
new OkHttpClient().newCall(request).enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
bundle.putString("result", "下载失败!");
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
Sink sink = null;
BufferedSink bufferedSink = null;
try {
File fapk = new File(Environment.getExternalStorageDirectory().getAbsolutePath(), downUrl.substring(downUrl.lastIndexOf("/") + 1));
sink = Okio.sink(fapk);
bufferedSink = Okio.buffer(sink);
bufferedSink.writeAll(response.body().source());
bufferedSink.close();
sink.close();
bundle.putString("result", "下载成功!");
installApk(fapk);
}catch (Exception e){
bundle.putString("result", "error: " + e.getMessage());
}finally {
if(bufferedSink != null) bufferedSink.close();
if(sink != null) sink.close();
msg.setData(bundle);
handler.sendMessage(msg);
}
}
});
}
安装apk应用
private void installApk(File fapk){
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(fapk), "application/vnd.android.package-archive");
startActivity(intent);
}
apk exposed beyond app through Intent.getData()
如果应用安装时出现 apk exposed beyond app through Intent.getData() 错误,AndroidStudio7.0之后官方对这权限做了调整,出于用户隐私安全考虑,谷歌——(对于面向 Android 7.0 的应用,Android 框架执行的 StrictMode API 政策禁止在您的应用外部公开 file://URI
。传递软件包网域外的 file://URI
可能给接收器留下无法访问的路径。因此,尝试传递 file://URI
会触发 FileUriExposedException
。分享私有文件内容的推荐方法是使用 FileProvider
//安装apk
private void installApk(File fapk){
Intent intent = new Intent(Intent.ACTION_VIEW);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
String ss = getPackageName() + ".fileProvider";
Uri contentUri = FileProvider.getUriForFile(getApplicationContext(), ss, fapk);
intent.setDataAndType(contentUri, "application/vnd.android.package-archive");
}catch (Exception e){
pub.error(FileManagerActivity.this, e.getMessage());
}
}else {
intent.setDataAndType(Uri.fromFile(fapk), "application/vnd.android.package-archive");
}
startActivity(intent);
}
以上是调用FileProvider进行apk的安装,具体FileProvider的使用需要另行设定,如AndroidManifest.xml的设定等。如有疑问可留言。
更新画面UI
因为网络操作不让在主线程上进行,所以这里借用Handle进行线程间的信息的传递和更新UI界面了解下载状态
private final Handler handler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(@NonNull Message message) {
if (message.what == 100) {
mView.tvShow.setText(message.getData().getString("result"));
} else if (message.what == 101) {
mView.tvShow.setText(mView.tvShow.getText().toString() + "\n" + message.getData().getString("result"));
}
return true;
}
});