Android版本更新及提示安装

import java.io.Closeable;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.util.EntityUtils;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.net.http.AndroidHttpClient;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.widget.TextView;
import android.widget.Toast;

public class SplashActivity extends Activity {

	public static final String TAG = "SplashActivity";

	public static final int WHAT_SHOW_UDPATE = 0;
	public static final int WHAT_DOWNLOAD_ERROR = 1;
	private static final int WHAT_NET_ERROR = 2;// 联网失败的错误信息

	private static final int REQUEST_INSTALL_CODE = 100;// 请求安装应用程序的标记

	private TextView mTvVersion;

	private String mVersionDesc;// 版本的描述信息
	private String mUrl;

	private Handler mHandler = new Handler() {
		public void handleMessage(android.os.Message msg) {
			// 在主线程中执行

			switch (msg.what) {
			case WHAT_SHOW_UDPATE:
				showUpdateDialog();
				break;
			case WHAT_DOWNLOAD_ERROR:
				Toast.makeText(getApplicationContext(), "下载失败",
						Toast.LENGTH_SHORT).show();
				break;
			case WHAT_NET_ERROR:
				Toast.makeText(getApplicationContext(), msg.obj.toString(),
						Toast.LENGTH_SHORT).show();

				// 跳转到主页
				load2Main();
				break;
			default:
				break;
			}

		};
	};

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_splash);

		// 初始化view
		initView();

		// 初始化数据
		initData();
	}

	private void initView() {
		mTvVersion = (TextView) findViewById(R.id.splash_tv_version);
	}

	private void initData() {
		// 给textView设置版本号
		// 获得版本号
		mTvVersion.setText("版本号:" + PackageInfoUtils.getVersionName(this));

		// 检测更新
		if (PreferenceUtils.getBoolean(this, Constants.AUTO_UPDATE, true)) {
			new Thread(new CheckVersionTask()).start();
		} else {
			load2Main();
		}
	}	
	/**
	 * 进入主页
	 */
	private void load2Main() {
		// 延时执行
		mHandler.postDelayed(new Runnable() {

			@Override
			public void run() {
				// 是在主线程中执行的
				Logger.d(TAG, "" + Thread.currentThread().getName());

				Intent intent = new Intent(SplashActivity.this,
						HomeActivity.class);
				startActivity(intent);

				finish();
			}
		}, 1500);
	}

	private class CheckVersionTask implements Runnable {

		@Override
		public void run() {
			// 去服务器获得最新的版本号
			// 服务器:提供最新的版本信息

			AndroidHttpClient client = AndroidHttpClient.newInstance("bsj");

			// 设置超时时间
			HttpConnectionParams.setConnectionTimeout(client.getParams(),
					5 * 1000);// 设置请求超时的时长
			HttpConnectionParams.setSoTimeout(client.getParams(), 5 * 1000);// 设置响应的超时时长

			String uri = "http://188.188.6.100:8080/update.json";
			HttpGet get = new HttpGet(uri);
			// 执行
			try {
				HttpResponse response = client.execute(get);

				// 获得返回的结果码
				int statusCode = response.getStatusLine().getStatusCode();
				if (200 == statusCode) {
					// 获得成功
					String json = EntityUtils.toString(response.getEntity(),
							"utf-8");

					Logger.d(TAG, "json : " + json);

					// {"versionCode":2,"versionDesc":"描述","url":"http://188.188.6.100:8080/mobilesafe.apk"}
					// 解析json
					JSONObject jsonObject = new JSONObject(json);
					int netVersion = jsonObject.getInt("versionCode");
					// 获得本地的版本号
					int localVersion = PackageInfoUtils
							.getVersionCode(SplashActivity.this);

					if (netVersion > localVersion) {
						mVersionDesc = jsonObject.getString("versionDesc");
						mUrl = jsonObject.getString("url");

						// 需要更新
						Message msg = mHandler.obtainMessage();
						msg.what = WHAT_SHOW_UDPATE;// 显示更新的dialog
						msg.sendToTarget();
					} else {
						// 不需要更新
						load2Main();
					}
				} else {
					// 获得失败
					Message msg = mHandler.obtainMessage();
					msg.what = WHAT_NET_ERROR;// 显示更新的dialog
					msg.obj = "Error:1000";
					msg.sendToTarget();
				}
			} catch (ClientProtocolException e) {
				// e.printStackTrace();

				Message msg = mHandler.obtainMessage();
				msg.what = WHAT_NET_ERROR;// 显示更新的dialog
				msg.obj = "Error:1001";
				msg.sendToTarget();

			} catch (IOException e) {
				// e.printStackTrace();

				Message msg = mHandler.obtainMessage();
				msg.what = WHAT_NET_ERROR;// 显示更新的dialog
				msg.obj = "Error:1002";
				msg.sendToTarget();

			} catch (JSONException e) {
				// e.printStackTrace();

				Message msg = mHandler.obtainMessage();
				msg.what = WHAT_NET_ERROR;// 显示更新的dialog
				msg.obj = "Error:1003";
				msg.sendToTarget();
			}

			// 关闭连接
			client.close();
		}
	}

	private void showUpdateDialog() {
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setCancelable(false);// 设置dialog不可以取消
		// 设置title
		builder.setTitle("版本更新提醒");
		// 设置内容部分
		builder.setMessage(mVersionDesc);
		// 设置点击按钮
		builder.setPositiveButton("立即更新", new OnClickListener() {

			@Override
			public void onClick(DialogInterface dialog, int which) {
				// 去下载更新
				// 根据服务器提供的url,去下载最新的版本
				downloadNewApk();
			}
		});
		builder.setNegativeButton("稍后再说", new OnClickListener() {

			@Override
			public void onClick(DialogInterface dialog, int which) {
				load2Main();
			}
		});

		builder.show();
	}

	protected void downloadNewApk() {
		// 显示下载的进度条
		ProgressDialog dialog = new ProgressDialog(this);
		dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
		dialog.setCancelable(false);// 设置不可取消
		dialog.show();

		// 下载apk
		new Thread(new DownloadTask(dialog)).start();
	}

	private class DownloadTask implements Runnable {
		private ProgressDialog mDialog;

		public DownloadTask(ProgressDialog dialog) {
			this.mDialog = dialog;
		}

		@Override
		public void run() {
			AndroidHttpClient client = AndroidHttpClient.newInstance("bsj");

			// url
			HttpGet get = new HttpGet(mUrl);

			InputStream is = null;
			FileOutputStream fos = null;
			try {
				HttpResponse response = client.execute(get);
				int statusCode = response.getStatusLine().getStatusCode();
				if (200 == statusCode) {
					// 读取流信息
					is = response.getEntity().getContent();
					// 将流写成文件

					File file = new File(
							Environment.getExternalStorageDirectory(),
							System.currentTimeMillis() + ".apk");

					// 输出流
					fos = new FileOutputStream(file);

					long contentLength = response.getEntity()
							.getContentLength();
					Logger.d(TAG, "total : " + contentLength);
					mDialog.setMax((int) contentLength);

					byte[] buffer = new byte[1024];
					int len = -1;
					int progress = 0;
					while ((len = is.read(buffer)) != -1) {
						fos.write(buffer, 0, len);

						Thread.sleep(20);

						progress += len;
						// 写进度
						Logger.d(TAG, "progress : " + progress);
						mDialog.setProgress(progress);
					}

					// dialog消失
					mDialog.dismiss();

					// 提示用户安装
					showInstall(file);
				} else {
					// 主线程中执行
					Message msg = mHandler.obtainMessage();
					msg.what = WHAT_DOWNLOAD_ERROR;
					msg.sendToTarget();

					// 跳转到主页
					load2Main();
				}
			} catch (ClientProtocolException e) {
				// e.printStackTrace();
				Message msg = mHandler.obtainMessage();
				msg.what = WHAT_NET_ERROR;// 显示更新的dialog
				msg.obj = "Error:1004";
				msg.sendToTarget();

			} catch (IOException e) {
				// e.printStackTrace();

				Message msg = mHandler.obtainMessage();
				msg.what = WHAT_NET_ERROR;// 显示更新的dialog
				msg.obj = "Error:1005";
				msg.sendToTarget();
			} catch (InterruptedException e) {
				// e.printStackTrace();

				Message msg = mHandler.obtainMessage();
				msg.what = WHAT_NET_ERROR;// 显示更新的dialog
				msg.obj = "Error:1006";
				msg.sendToTarget();
			} finally {
				closeIO(is);
				closeIO(fos);
			}

			// 关闭连接
			client.close();
		}
	}

	private void closeIO(Closeable io) {
		if (io != null) {
			try {
				io.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
			io = null;
		}
	}
	private void showInstall(File file) {
		// TODO:
		// <intent-filter>
		// <action android:name="android.intent.action.VIEW" />
		// <category android:name="android.intent.category.DEFAULT" />
		// <data android:scheme="content" />
		// <data android:scheme="file" />
		// <data android:mimeType="application/vnd.android.package-archive" />
		// </intent-filter>

		Intent intent = new Intent();
		intent.setAction("android.intent.action.VIEW");
		intent.addCategory("android.intent.category.DEFAULT");
		intent.setDataAndType(Uri.fromFile(file),
				"application/vnd.android.package-archive");

		// startActivity(intent);
		startActivityForResult(intent, REQUEST_INSTALL_CODE);
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);

		// requestCode:请求的code,start时指定
		// resultCode: 是有开启后的activity提供的, setResult()
		if (requestCode == REQUEST_INSTALL_CODE) {
			// 开启安装请求的回调

			// android系统,将用户行为分为两种:确定,取消
			switch (resultCode) {
			case Activity.RESULT_OK:
				// 确定
				break;
			case Activity.RESULT_CANCELED:
				// 取消
				load2Main();
				break;
			default:
				break;
			}

		}

	}
}

框架内部支持中/英文(其他语言只需要在对应的string.xml中取相同的名字即可)内部对话框背景图片、按钮支持自定义了查看版本中的Log只需要过滤AppUpdate开头的Tag重点: 如果没有设置downloadPath则默认为getExternalCacheDir()目录,同时不会申请[存储]权限!目录编译问题效果图功能介绍DownloadManagerUpdateConfiguration使用步骤Demo下载体验版本更新记录结语编译问题因为适配了Android O的通知栏,所以依赖的v7包版本比较高appcompat-v7:26.1.0使用的gradle版本为gradle-4.1-all,所以建议使用Android Studio 3.0及以上的版本打开此项目效果图     功能介绍 支持断点下载 支持后台下载 支持自定义下载过程 支持 设备 >= Android M 动态权限的申请 支持通知栏进度条展示(或者自定义显示进度) 支持Android N 支持Android O 支持中/英文双语 支持自定内置对话框的样式 使用HttpURLConnection下载,未集成其他第三方框架更加详细的文档参阅此处《AppUpdate API文档》DownloadManager:配置文档初始化使用DownloadManager.getInstance(this)属性描述默认值是否必须设置context上下文nulltrueapkUrlapk的下载地址nulltrueapkNameapk下载好的名字nulltruedownloadPathapk下载的位置getExternalCacheDir()falseshowNewerToast是否提示用户 "当前已是最新版本"falsefalsesmallIcon通知栏的图标(资源id)-1trueconfiguration这个库的额外配置nullfalseapkVersionCode更新apk的versionCode (如果设置了那么库中将会进行版本判断下面的属性也就需要设置了)1falseapkVersionName更新apk的versionNamenullfalseapkDescription更新描述nullfalseapkSize新版本安装包大小(单位M)nullfalseauthorities兼容Android N uri授权应用包名falseUpdateConfiguration:配置文档属性描述默认值notifyId通知栏消息id1011notificationChannel适配Android O的渠道通知详情查阅源码httpManager设置自己的下载过程nullbreakpointDownload是否需要支持断点下载trueenableLog是否需要日志输出trueonDownloadListener下载过程的回调nulljumpInstallPage下载完成是否自动弹出安装页面trueshowNotification是否显示通知栏进度(后台下载提示)trueforcedUpgrade是否强制升级falseonButtonClickListener按钮点击事件回调nulldialogImage对话框背景图片资源(图片规范参考demo)-1dialogButtonColor对话框按钮的颜色-1dialogButtonTextColor对话框按钮的文字颜色-1所有版本:点击查看使用步骤第一步: app/build.gradle进行依赖implementation 'com.azhon:appupdate:1.7.3'第二步:创建DownloadManager,更多用法请查看这里示例代码DownloadManager manager = DownloadManager.getInstance(this); manager.setApkName("appupdate.apk")         .setApkUrl("https://raw.githubusercontent.com/azhon/AppUpdate/master/apk/appupdate.apk")         .setSmallIcon(R.mipmap.ic_launcher)         //可设置,可不设置         .setConfiguration(configuration)         .download();第三步:兼容Android N 及以上版本,在你应用的Manifest.xml添加如下代码<--! android:authorities="${applicationId}"  这个值必须与DownloadManager中的authorities一致(不设置则为应用包名)--> <provider     android:name="android.support.v4.content.FileProvider"     android:authorities="${applicationId}"     android:exported="false"     android:grantUriPermissions="true">     <meta-data         android:name="android.support.FILE_PROVIDER_PATHS"         android:resource="@xml/file_paths_public" /> </provider>第四步:资源文件res/xml/file_paths_public.xml内容<?xml version="1.0" encoding="utf-8"?> <paths>     <external-path         name="app_update_external"         path="/" />     <external-cache-path         name="app_update_cache"         path="/" /> </paths>兼容Android O及以上版本,需要设置NotificationChannel(通知渠道);库中已经写好可以前往查阅NotificationUtil.java温馨提示:升级对话框中的内容是可以上下滑动的哦!如果需要实现自己一套下载过程,只需要继承BaseHttpDownloadManager 并使用listener更新进度public class MyDownload extends BaseHttpDownloadManager {}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值