版本更新邏輯
1赁还、聯(lián)網(wǎng)妖泄,從遠(yuǎn)程服務(wù)器獲取最新的版本,然后跟本地的版本號比對艘策,如果遠(yuǎn)程的版本號大于本地的版本號蹈胡,彈出對話框,有新版本朋蔫,如果相等罚渐,已經(jīng)是最新版本,不需要更新驯妄,本地版本號不可能比遠(yuǎn)程版本好大荷并,
1、立刻升級
點(diǎn)擊立刻升級青扔,把最新的apk下載下來源织,然后提示更新安裝。
2微猖、稍后再說
點(diǎn)擊稍后再說谈息,立即進(jìn)入主界面。
3凛剥、版本名侠仇、版本號
1、versionCode:給程序員看的
2、versionName:給用戶看的
3逻炊、版本名規(guī)則:eg互亮。6.1.3
1、6.1.C:小版本更新余素,修改了小bug豹休,做一些微調(diào)
2、6.B.3:中等版本更新桨吊,更改了比較重要的bug慕爬,添加新功能
3、A.1.3:大版本更新屏积,很重要的更新医窿,里程碑意義的更新。
實(shí)戰(zhàn)
D:\Software-tools\Tomcat\webapps\ROOT\update.txt
里面新建文本update模擬遠(yuǎn)程版本炊林,在update文本里面寫上json格式的數(shù)據(jù):
{"remoteVesion":"2"} //版本號為:2
訪問成功:
異常處理的原則
1姥卢、如果有統(tǒng)一的解決方案,就在方法內(nèi)部try catch掉
2渣聚、如果每次調(diào)用處理異常的方式都不同独榴,就直接往外拋(誰調(diào)用,誰處理)
版本更新demo
SplashActivity
public class SplashActivity extends Activity {
private static final String TAG = "SplashActivity";
private static final int REQUEST_CODE = 100;
//錯(cuò)誤碼
protected static final int NET_ERROR = 1001;
protected static final int NET_KEEP = 1002;
private TextView tv_version;
private ProgressDialog progressDialog;
Handler mHandler = new Handler(){
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case NET_ERROR:
Toast.makeText(getApplicationContext(), "網(wǎng)絡(luò)錯(cuò)誤奕枝!", Toast.LENGTH_SHORT).show();
enterHome();
break;
case NET_KEEP:
Toast.makeText(getApplicationContext(), "服務(wù)器正在維護(hù)棺榔!", Toast.LENGTH_SHORT).show();
enterHome();
break;
default:
break;
}
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
tv_version = (TextView) findViewById(R.id.splash_tv_version);
// 設(shè)置版本名
initVersionName();
//版本更新
updateVersion();
}
private void updateVersion() {
final String url = "http://192.168.39.50:8080/update.txt";
//1.訪問服務(wù)器,獲取最新版本信息
new Thread(new Runnable() {
@Override
public void run() {
//01. 定義okhttp
// OkHttpClient okHttpClient_get = new OkHttpClient();
//設(shè)置連接超時(shí)時(shí)間
OkHttpClient okHttpClient_get = new OkHttpClient.Builder().connectTimeout(3, TimeUnit.SECONDS).build();
//02.請求體
Request request = new Request.Builder()
.get()//get請求方式
.url(url)//網(wǎng)址
.build();
//03.執(zhí)行okhttp
Response response;
try {
response = okHttpClient_get.newCall(request).execute();
/**
* 打印數(shù)據(jù),注意一次請求隘道,一次響應(yīng)症歇,讀取一次就沒了,要注釋掉
*/
// System.out.println(response.body().string());
String json = response.body().string();
//001.解析
//{"remoteVesion":"2","desc":"1.添加了搖一搖的功能\n2.優(yōu)化了用戶的體驗(yàn)","apkUrl":"http://192.168.39.50:8080/safenet.apk"}
JSONObject jsonObject = new JSONObject(json);
int remoteVesion = jsonObject.getInt("remoteVesion");
String desc = jsonObject.getString("desc");
String url = jsonObject.getString("apkUrl");
final UpdateInfo updateInfo = new UpdateInfo();
updateInfo.remoteVesion = remoteVesion;
updateInfo.desc = desc;
updateInfo.apkUrl = url;
//2.判斷最新版本與本地是否一致
int localVersion = PackageUtil.getVersionCode(getApplicationContext());
if (remoteVesion > localVersion) {
//3.彈出提示dialog
//不能在子線程中更新UI
runOnUiThread(new Runnable() {
@Override
public void run() {
showUpdateDialog(updateInfo);
}
});
}else{
//跳轉(zhuǎn)到主頁
enterHome();
}
} catch (IOException e) {
Message message = mHandler.obtainMessage();
message.what = NET_ERROR;
message.sendToTarget();
e.printStackTrace();
} catch (JSONException e) {
Message message = mHandler.obtainMessage();
message.what = NET_KEEP;
message.sendToTarget();
e.printStackTrace();
}
}
}).start();
}
//進(jìn)入主頁
protected void enterHome() {
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
Intent intent = new Intent(SplashActivity.this, HomeActivity.class);
startActivity(intent);
}
}, 2000);
}
private void showUpdateDialog(final UpdateInfo info) {
AlertDialog.Builder builder = new Builder(SplashActivity.this);
builder.setTitle("版本更新提示");
builder.setCancelable(false);//點(diǎn)擊旁邊不能消失
builder.setMessage(info.desc);
//4.是否升級
builder.setPositiveButton("立刻升級", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
downApk(info);
}
});
builder.setNegativeButton("稍后再說", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//回到主頁
enterHome();
}
});
builder.show();
}
protected void downApk(UpdateInfo info) {
//5.下載最新APK
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
progressDialog = new ProgressDialog(this);
progressDialog.setCancelable(false);
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.show();
new Thread(new DownTask(info.apkUrl)).start();
}else{
//回到主頁
Toast.makeText(this, "沒有SD卡谭梗!", Toast.LENGTH_SHORT).show();
enterHome();
}
}
class DownTask implements Runnable{
String mUrl;
public DownTask(String apkUrl) {
this.mUrl = apkUrl;
}
@Override
public void run() {
InputStream is = null;
FileOutputStream fos = null;
try {
Response response = HttpUtil.get(mUrl);
is = response.body().byteStream();
long contentLength = response.body().contentLength();
//01.設(shè)置進(jìn)度條最大值
progressDialog.setMax((int) contentLength);
//路徑:mnt/sdcard/
File file = new File(Environment.getExternalStorageDirectory(), "safe.apk");
fos = new FileOutputStream(file);
byte[] buffer = new byte[1024];
int len = -1;
int progress = 0;
while((len = is.read(buffer)) != -1){
fos.write(buffer, 0, len);
// SystemClock.sleep(10);
progress += len;
//02.設(shè)置進(jìn)度
progressDialog.setProgress(progress);
}
fos.flush();
//03.進(jìn)度條消失
progressDialog.dismiss();
//6.提示用戶安裝
installApk(file);
} catch (IOException e) {
Message message = mHandler.obtainMessage();
message.what = NET_ERROR;
message.sendToTarget();
e.printStackTrace();
} finally{
closeIo(fos);
closeIo(is);
// closeIo2(fos,is);
}
}
}
public void closeIo(Closeable io){
if (io != null) {
try {
io.close();
io = null;
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void installApk(File file) {
// <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>
//7.安裝APK
Intent intent = new Intent();
intent.addCategory("android.intent.category.DEFAULT");
intent.setAction("android.intent.action.VIEW");
//獲取文件的uri
Uri data = Uri.fromFile(file);
intent.setDataAndType(data, "application/vnd.android.package-archive");
// startActivity(intent);
startActivityForResult(intent, REQUEST_CODE);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE) {
//系統(tǒng)默認(rèn)的用戶行為只有兩種:yes no
switch (resultCode) {
case Activity.RESULT_OK:
//***被覆蓋安裝了忘晤,所以不會(huì)出日志
Log.d(TAG, "RESULT_OK");
break;
case Activity.RESULT_CANCELED:
Log.d(TAG, "RESULT_CANCELED");
//進(jìn)入到主頁
enterHome();
break;
default:
break;
}
}
}
public void closeIo2(Closeable... io){
for (int i = 0; i < io.length; i++) {
if(io[i] != null){
try {
io[i].close();
io[i] = null;
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private void initVersionName() {
// PackageManager pm = this.getPackageManager();
// /**
// * flags:標(biāo)志位,0標(biāo)志包的基本信息
// */
// try {
// PackageInfo info = pm.getPackageInfo(getPackageName(), 0);
// String versionName = info.versionName;
//
// tv_version.setText(versionName);
// } catch (NameNotFoundException e) {
// e.printStackTrace();
// }
String versionName = PackageUtil.getVersionName(this);
tv_version.setText(versionName);
}
}
UpdateInfo
public class UpdateInfo {
public int remoteVesion;//遠(yuǎn)程版本號
public String desc;//版本描述
public String apkUrl;//apk的下載地址
}
HttpUtil
public class HttpUtil {
public static Response get(String url) throws IOException{
//01. 定義okhttp
OkHttpClient okHttpClient_get = new OkHttpClient();
//02.請求體
Request request = new Request.Builder()
.get()//get請求方式
.url(url)//網(wǎng)址
.build();
//03.執(zhí)行okhttp
Response response = okHttpClient_get.newCall(request).execute();
return response;
}
}
public class PackageUtil {
public static String getVersionName(Context context){
PackageManager pm = context.getPackageManager();
/**
* flags:標(biāo)志位激捏,0標(biāo)志包的基本信息
*/
try {
PackageInfo info = pm.getPackageInfo(context.getPackageName(), 0);
String versionName = info.versionName;
return versionName;
} catch (NameNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "未知版本名";
}
public static int getVersionCode(Context context){
PackageManager pm = context.getPackageManager();
/**
* flags:標(biāo)志位设塔,0標(biāo)志包的基本信息
*/
try {
PackageInfo info = pm.getPackageInfo(context.getPackageName(), 0);
int versionCode = info.versionCode;
return versionCode;
} catch (NameNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return 1;
}
}