主要的逻辑代码UpdateAppManager
public class UpdateAppManager {
// 文件分隔符
private static final String FILE_SEPARATOR = "/";
// 外存sdcard存放路径
private static final String FILE_PATH = Environment.getExternalStorageDirectory() + FILE_SEPARATOR + "autoupdate" + FILE_SEPARATOR;
// 下载应用存放全路径
private static final String FILE_NAME = FILE_PATH + "autoupdate.apk";
// 更新应用版本标记
private static final int UPDARE_TOKEN = 0x29;
// 准备安装新版本应用标记
private static final int INSTALL_TOKEN = 0x31;
//比较版本信息
private static final int CHECK_VERSION = 0x32;
private Context context;
private String message = "检测到本程序有新版本发布,建议您更新!";
// 以华为天天聊hotalk.apk为例
private String spec = Constants.URL_DOWNLOAD_FILE;
// 下载应用的对话框
private Dialog dialog;
// 下载应用的进度条
private ProgressBar progressBar;
// 进度条的当前刻度值
private int curProgress;
// 用户是否取消下载
private boolean isCancel;
private String versionName;
private String currentAppVerName;
private IUpdateVersionListener updateVersionListener;
private String downloadUrl;
public interface IUpdateVersionListener {
void needToUpdate(boolean needtoupdate);
void startInstallApp(String uri);
}
public void registerListener(IUpdateVersionListener listener) {
updateVersionListener = listener;
}
public UpdateAppManager(Context context) {
this.context = context;
}
private final Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case UPDARE_TOKEN:
progressBar.setProgress(curProgress);
break;
case INSTALL_TOKEN:
installApp();
break;
case CHECK_VERSION:
// 如果版本不同则更新app
// if (!versionName.contentEquals(currentAppVerName)){
if (versionName.compareTo(currentAppVerName) > 0) {
updateVersionListener.needToUpdate(true);
showNoticeDialog();
} else {
updateVersionListener.needToUpdate(false);
}
break;
}
}
};
/**
* 检测应用更新信息
*/
public void checkUpdateInfo() {
String url = Constants.URL_GET_VERSION;
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(url, null, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject jsonObject) {
try {
if (jsonObject.getInt("code") == 0) {
JSONObject data = jsonObject.optJSONObject("data");
//获取最新版本信息
versionName = data.getString("VersionNo");
downloadUrl = data.optString("DownloadUrl");
if(downloadUrl ==null){
downloadUrl =spec;
}
//获取当前app的版本
currentAppVerName = getAppVersionName(context);
Message msg = new Message();
msg.what = CHECK_VERSION;
handler.sendMessage(msg);
} else {
ignoreVersionUpdate();
}
} catch (JSONException ex) {
ex.printStackTrace();
//获取当前app的版本
// currentAppVerName = getAppVersionName(context);
// versionName = currentAppVerName;
// Message msg = new Message();
// msg.what = CHECK_VERSION;
// handler.sendMessage(msg);
ignoreVersionUpdate();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError volleyError) {
// currentAppVerName = getAppVersionName(context);
// versionName = currentAppVerName;
// Message msg = new Message();
// msg.what = CHECK_VERSION;
// handler.sendMessage(msg);
ignoreVersionUpdate();
volleyError.printStackTrace();
}
});
RequestManager.getRequestQueue().add(jsonObjectRequest);
// showNoticeDialog();
}
private void ignoreVersionUpdate() {
currentAppVerName = getAppVersionName(context);
versionName = currentAppVerName;
Message msg = new Message();
msg.what = CHECK_VERSION;
handler.sendMessage(msg);
}
public String getAppVersionName(Context context) {
String versionName = "";
String versionCode = "";
try {
PackageManager packageManager = context.getPackageManager();
PackageInfo packageInfo = packageManager.getPackageInfo(context.getPackageName(), 0);
versionName = packageInfo.versionName;
if (TextUtils.isEmpty(versionName)) {
return "";
}
} catch (Exception e) {
e.printStackTrace();
}
return versionName;
}
/**
* 显示提示更新对话框
*/
private void showNoticeDialog() {
VersionUpdateDialog dialog = new VersionUpdateDialog(context);
dialog.show();
}
public class VersionUpdateDialog extends Dialog {
public VersionUpdateDialog(Context context) {
super(context, R.style.sign_rules_dialog_style);
setContentView(R.layout.version_check_dialog);
setCanceledOnTouchOutside(false);
TextView accept = (TextView) findViewById(R.id.accept);
accept.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
VersionUpdateDialog.this.dismiss();
showDownloadDialog();
}
});
TextView ignoreTextView = (TextView) findViewById(R.id.ignore);
ignoreTextView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
VersionUpdateDialog.this.dismiss();
updateVersionListener.needToUpdate(false);
}
});
}
}
/**
* 显示下载进度对话框
*/
private void showDownloadDialog() {
View view = LayoutInflater.from(context).inflate(R.layout.download_progressbar, null);
progressBar = (ProgressBar) view.findViewById(R.id.progressBar);
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(context.getString(R.string.version_update));
builder.setView(view);
dialog = builder.create();
dialog.setCanceledOnTouchOutside(false);
dialog.show();
downloadApp();
}
/**
* 下载新版本应用
*/
private void downloadApp() {
new Thread(new Runnable() {
@Override
public void run() {
URL url = null;
InputStream in = null;
FileOutputStream out = null;
HttpURLConnection conn = null;
try {
url = new URL(downloadUrl);
conn = (HttpURLConnection) url.openConnection();
conn.connect();
long fileLength = conn.getContentLength();
in = conn.getInputStream();
File filePath = new File(FILE_PATH);
if (!filePath.exists()) {
filePath.mkdir();
}
out = new FileOutputStream(new File(FILE_NAME));
byte[] buffer = new byte[1024];
int len = 0;
long readedLength = 0l;
while ((len = in.read(buffer)) != -1) {
// 用户点击“取消”按钮,下载中断
if (isCancel) {
break;
}
out.write(buffer, 0, len);
readedLength += len;
curProgress = (int) (((float) readedLength / fileLength) * 100);
handler.sendEmptyMessage(UPDARE_TOKEN);
if (readedLength >= fileLength) {
dialog.dismiss();
// 下载完毕,通知安装
handler.sendEmptyMessage(INSTALL_TOKEN);
break;
}
}
out.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (conn != null) {
conn.disconnect();
}
}
}
}).start();
}
/**
* 安装新版本应用
*/
private void installApp() {
File appFile = new File(FILE_NAME);
if (!appFile.exists()) {
return;
}
// 跳转到新版本应用安装页面
updateVersionListener.startInstallApp(appFile.toString());
}
public String getNewVer() {
if(versionName!=null){
return versionName;
}else {
return "1.0";
}
}
}
XML文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="@dimen/sign_rule_dialog_width"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@drawable/sign_rules_dialog_bg"
android:orientation="vertical"
android:paddingLeft="20dp"
android:paddingRight="20dp">
<View
android:layout_width="match_parent"
android:layout_height="20dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:gravity="center"
android:text="@string/update_title"
android:textAppearance="?android:textAppearanceLarge"
android:textColor="@color/goldcolorfortext" />
<View
android:layout_width="match_parent"
android:layout_height="20dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/update_hint_content"
android:textAppearance="?android:textAppearanceMedium"
android:textColor="#808080" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="20dp" />
<TextView
android:id="@+id/accept"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/red_round_corners_button_bg"
android:gravity="center"
android:padding="10dp"
android:text="@string/update_now"
android:textAppearance="?android:textAppearanceMedium"
android:textColor="#ffffff" />
<View
android:layout_width="match_parent"
android:layout_height="20dp" />
<TextView
android:id="@+id/ignore"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/gray_round_corners_button_bg"
android:gravity="center"
android:padding="10dp"
android:text="@string/update_ignore"
android:textAppearance="?android:textAppearanceMedium"
android:textColor="#ffffff" />
<View
android:layout_width="match_parent"
android:layout_height="20dp" />
</LinearLayout>
Style
<style name="sign_rules_dialog_style" parent="android:style/Theme.Dialog">
<item name="android:background">#00FFFFFF</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowIsFloating">true</item>
<item name="android:backgroundDimEnabled">true</item>
</style>
progressBar XML
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
调用
UpdateAppManager updateManager = new UpdateAppManager(this);
updateManager.checkUpdateInfo();
updateManager.registerListener(new UpdateAppManager.IUpdateVersionListener() {
@Override
public void needToUpdate(boolean needtoupdate) {
if (!needtoupdate) {
handler.sendEmptyMessageDelayed(0, 2000); //不用升级,这里处理逻辑
}
}
@Override
public void startInstallApp(String uri) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse("file://" + uri), "application/vnd.android.package-archive");
startActivityForResult(intent, RESULT_CANCELED);
}
});