目前,应用市场上的应用程序基本上都有自动更新的功能,用于版本迭代,软件更新以达到更好的应用体验效果。本文我将简要介绍一下Android版本更新的相关知识。
一、知识预热
2.versonName:版本名称,String类型,主要是用于用户界面交互。
3.versionCode和versionName的配置在项目下的build.gradle中,可根据项目需要进行相应的配置,如下所示:
defaultConfig {
applicationId "example.com.demo_update"
minSdkVersion 22
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
4.代码获取versionCode和versionName。
PackageManager manager = MainActivity.this.getPackageManager();
PackageInfo info = manager.getPackageInfo(MainActivity.this.getPackageName(), 0);
String appVersion = info.versionName; // 版本名
int currentVersionCode = info.versionCode; // 版本号
二、磨刀开工
1.编写检测更新弹框。该步骤主要是通过点击进行事件更新获取操作,进行弹框提示。
/**
* 点击下载弹框
*/
private void showUpdateDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.checked_new_version);
builder.setMessage(R.string.check_is_update);
builder.setPositiveButton("下载", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
startActivity(new Intent(MainActivity.this, NotificationUpdateActivity.class));
mDownLoadApp.setDownload(true);
}
}).setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
builder.show();
}
2.更新代码实现。首先应用组件需调用bindService()绑定Service,然后系统自动调用onBind()方法,返回一个用于交互的Ibinder.
绑定是异步的,要接收Ibinder需要创建一个ServiceConnection实例传给bindService(),因为bindService()是不会将IBInder返回给客户端的。系统需要调用该方法传递返回。
ServiceConnection方法如下:
ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
isBinded = false;
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
binder = (DownloadService.DownloadBinder) service;
System.out.println("服务启动!!!");
// 开始下载
isBinded = true;
binder.addCallback(callback);
binder.start();
}
};
更新进度方法实现:
private ICallbackResult callback = new ICallbackResult() {
@Override
public void OnBackResult(Object result) {
// TODO Auto-generated method stub
if ("finish".equals(result)) {
finish();
return;
}
int i = (Integer) result;
mProgressBar.setProgress(i);
mHandler.sendEmptyMessage(i);
}
};
private Handler mHandler = new Handler() {
public void handleMessage(android.os.Message msg) {
mProgressText.setText("当前进度 : " + msg.what + "%");
};
};
public interface ICallbackResult {
public void OnBackResult(Object result);
}
注:因为更新操作在子线程中操作,但是我们需要在UI线程中显示当前进度,所以需要进行消息传递机制进行UI更新操作。
3.下载更新Service方法实现。Service操作主要是根据当前的操作进度进行Service服务,本段代码中主要是考虑了三个方面的操作:
(1)下载完毕,取消通知,进行安装。
mDownLoadApp.setDownload(false);
// 下载完毕
// 取消通知
mNotificationManager.cancel(NOTIFY_ID);
installApk();
(2)更新中的操作。
int rate = msg.arg1;
mDownLoadApp.setDownload(true);
if (rate <= 100) {
RemoteViews contentview = mNotification.contentView;
contentview.setTextViewText(R.id.id_activity_download_progress_tv, rate + "%");
contentview.setProgressBar(R.id.id_activity_download_progressbar, 100, rate, false);
} else {
System.out.println("下载完毕!!!!!!!!!!!");
// 下载完毕后变换通知形式
mNotification.flags = Notification.FLAG_AUTO_CANCEL;
mNotification.contentView = null;
Intent intent = new Intent(mContext, NotificationUpdateActivity.class);
// 告知已完成
intent.putExtra("completed", "yes");
// 更新参数,注意flags要使用FLAG_UPDATE_CURRENT
PendingIntent contentIntent = PendingIntent.getActivity(mContext, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
// mNotification.setLatestEventInfo(mContext, "下载完成", "文件已下载完毕", contentIntent);
//
serviceIsDestroy = true;
stopSelf();// 停掉服务自身
}
mNotificationManager.notify(NOTIFY_ID, mNotification);
(3)手动取消操作,通知取消。
mDownLoadApp.setDownload(false);
// 这里是用户界面手动取消,所以会经过activity的onDestroy();方法
// 取消通知
mNotificationManager.cancel(NOTIFY_ID);
(4)下载apk。
/**
* 下载apk
* @param url
*/
private Thread downLoadThread;
private void downloadApk() {
downLoadThread = new Thread(mdownApkRunnable);
downLoadThread.start();
}
private int lastRate = 0;
private Runnable mdownApkRunnable = new Runnable() {
@Override
public void run() {
try {
URL url = new URL(mDownLoadUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.connect();
int length = conn.getContentLength();
InputStream is = conn.getInputStream();
File file = new File(savePath);
if (!file.exists()) {
file.mkdirs();
}
String apkFile = saveFileName;
File ApkFile = new File(apkFile);
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);
// 更新进度
Message msg = mHandler.obtainMessage();
msg.what = 1;
msg.arg1 = progress;
if (progress >= lastRate + 1) {
mHandler.sendMessage(msg);
lastRate = progress;
if (callback != null)
callback.OnBackResult(progress);
}
if (numread <= 0) {
// 下载完成通知安装
mHandler.sendEmptyMessage(0);
// 下载完了,cancelled也要设置
canceled = true;
break;
}
fos.write(buf, 0, numread);
} while (!canceled);// 点击取消就停止下载.
fos.close();
is.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
};
(5)安装apk。
/**
* 安装apk
* @param
*/
private void installApk() {
File apkfile = new File(saveFileName);
if (!apkfile.exists()) {
return;
}
Intent i = new Intent(Intent.ACTION_VIEW);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.setDataAndType(Uri.parse("file://" + apkfile.toString()), "application/vnd.android.package-archive");
mContext.startActivity(i);
callback.OnBackResult("finish");
}
4.Application代码,用于全局检测更新操作。
public class DownLoadApplication extends Application {
private boolean isDownload;
public boolean isDownload() {
return isDownload;
}
public void setDownload(boolean isDownload) {
this.isDownload = isDownload;
}
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
isDownload = false;
}
}
三、效果展示
地址:http://download.youkuaiyun.com/detail/u012721519/9743234
Good Luck!
Write by Jimmy.li