apk版本的的比对、下载、安装需求分析
0.通过xutils3进行网络数据请求、文件下载
1.请求服务器获取服务器存储的版本信息
2.通过比对手机端的版本和服务器的版本
3如果要更新需要符合以下判断条件
1)sdcard是否存在
2)sdcard剩余存储量与apk文件大小的比对
3)是否在wifi环境下
4.下载完成后自动安装
-----核心代码---
1.需要xutils3.jar自己去网上下载
2.需要的权限
activity_splash.xml
MyApplication.java
package com.smart.mobileasfe.application;
import android.app.Application;
import com.smart.mobileasfe.activity.BuildConfig;
import org.xutils.x;
/**
* Created by 光 on 2016/12/25.
*/
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
//设置xutils进行ioc操作
x.Ext.init(this);
x.Ext.setDebug( BuildConfig.DEBUG);
}
}
AndroidUtils.java
package com.smart.mobileasfe.utils;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Environment;
import android.util.Log;
import java.io.File;
/**
* Created by 光 on 2016/12/25.
*/
public class AndroidUtils {
/**
* 判断SDcard是否可用
* @return
*/
public static boolean sdcardExists() {
return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState());
}
/**
* 获取SDcard的总存储量,返回-1则不存在
* @return
*/
public static long getTotalSpace() {
if(sdcardExists()) {
File file = Environment.getExternalStorageDirectory();
return file.getTotalSpace();//文件的总大小(此方法应用于8以上,需要在此方法打上NewApi的注解)
} else {
return -1;
}
}
/**
* 获取SDcard的剩余存储量,返回-1则不存在
* @return
*/
public static long getUsableSpace() {
if(sdcardExists()) {
File file = Environment.getExternalStorageDirectory();
return file.getUsableSpace();//文件的总大小(此方法应用于8以上,需要在此方法打上NewApi的注解)
} else {
return -1;
}
}
/**
* 安装apk包
* @param context Context 上下文对象
* @param apkFile File apk文件对象
*/
public static void installApk(Context context,File apkFile) {
Log.e("OpenFile", apkFile.getName());
Intent intent = new Intent();
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setAction(android.content.Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(apkFile),
"application/vnd.android.package-archive");
context.startActivity(intent);
}
/**
* 安装apk包
* @param context Context 上下文对象
* @param apkFile String 文件路径
*/
public static void installApk(Context context,String apkFile) {
installApk(context,new File(apkFile));
}
/**
* 判断你是否在为wifi环境
* @param context
* @return
*/
public static boolean isWifi(Context context) {
ConnectivityManager connectivityManager = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo();
if (activeNetInfo != null
&& activeNetInfo.getType() == ConnectivityManager.TYPE_WIFI) {
return true;
}
return false;
}
}
5.activity类 核心
SplashActivity.java
package com.smart.mobileasfe.activity;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Environment;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;
import com.smart.mobileasfe.utils.AndroidUtils;
import org.json.JSONObject;
import org.xutils.common.Callback;
import org.xutils.http.RequestParams;
import org.xutils.view.annotation.ContentView;
import org.xutils.view.annotation.ViewInject;
import org.xutils.x;
import java.io.File;
@ContentView(R.layout.activity_splash)//通过注解引入布局文件
public class SplashActivity extends AppCompatActivity {
@ViewInject(R.id.tv_version)//通过注解,注入布局文件中的属性
private TextView tv_version;
private ProgressDialog progressDialog;
private long loadLength = 0;//下载文件的长度
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
x.view().inject(this);//通过xUtils注解初始化容器的组件
initData();
}
/**
* 初始化数据
*/
private void initData() {
tv_version.setText(getVersionName());
checkVersion();
}
/**
* 检测版本是否更新
*/
private void checkVersion() {
//设置网络请求
RequestParams params = new RequestParams("http://192.168.1.6:8080/version.json");
/** --服务器端的json文件配置
{
"downloadUrl": "http://192.168.1.6:8080/mobilesafe-debug.apk",
"versionCode": 2,
"versionDes": "2.0版本,新增。。。功能",
"versionName": "2.0"
}
*/
//以post的方式进行网络请求
x.http().post(params,new Callback.CommonCallback() {
@Override
public void onSuccess(String o) {
try {
//处理服务器回传回来的数据
JSONObject json = new JSONObject(o);
int versionCode = json.getInt("versionCode");
String versionName = json.getString("versionName");
String versionDes = json.getString("versionDes");
final String url = json.getString("downloadUrl");
int currentCode = getVersionCode();
//当前版本与服务器中的版本作比较
if(versionCode > currentCode) {
//是否存在SDcard
if(AndroidUtils.sdcardExists()) {
//获取sdcard系统的目录
final String BASE_PATH = Environment.getExternalStorageDirectory().getPath() + File.separator;
//获取当前网络状态,是否在wifi环境下
boolean isWifi = AndroidUtils.isWifi(SplashActivity.this);
if(isWifi){
downloadApk(url,BASE_PATH);
}else {
//不再wifi环境下提醒用户是否更新
AlertDialog.Builder builder = new AlertDialog.Builder(SplashActivity.this);
builder.setMessage("不再WIFI环境下,确认下载吗?");
builder.setTitle("下载新版本");
builder.setPositiveButton("确认", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
downloadApk(url,BASE_PATH);
}
});
builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
startActivity(new Intent(getApplicationContext(),SplashOneActivity.class));
}
});
builder.create().show();
}
}
} else {
//跳转到应用界面
startActivity(new Intent(getApplicationContext(),SplashOneActivity.class));
}
} catch (Exception e) {
showMessage("服务器忙请稍后。。。");
}
}
@Override
public void onError(Throwable throwable, boolean b) {
showMessage("服务器忙请稍后。。。");
}
@Override
public void onCancelled(CancelledException e) {
}
@Override
public void onFinished() {
}
});
}
private void showMessage(String content) {
Toast.makeText(getApplicationContext(),content,Toast.LENGTH_LONG).show();
}
/**
* 获取当前版本名称
* @return
*/
private String getVersionName() {
String versionName = "";
PackageManager pm = getPackageManager();
try {
PackageInfo pi = pm.getPackageInfo(getPackageName(),0);
versionName = pi.versionName;
} catch (Exception e) {
}
return versionName;
}
/**
* 获取当前版本号
* @return
*/
private int getVersionCode() {
int versioncode = 0;
PackageManager pm = getPackageManager();
try {
PackageInfo pi = pm.getPackageInfo(getPackageName(),0);
versioncode = pi.versionCode;
} catch (Exception e) {
}
return versioncode;
}
/**
*
* @param url apk的网络路径,apk下载完成后存储的路径
* @param path
*/
private void downloadApk(final String url, String path) {
progressDialog = new ProgressDialog(this);
RequestParams requestParams = new RequestParams(url);
requestParams.setSaveFilePath(path);
x.http().get(requestParams, new Callback.ProgressCallback() {
@Override
public void onWaiting() {
}
@Override
public void onStarted() {
}
/**
* 下载中
* @param total 文件的总长度
* @param current 文件当前的长度
* @param isDownloading 是否在下载
*/
@Override
public void onLoading(final long total, final long current, boolean isDownloading) {
if(AndroidUtils.getTotalSpace() < total) {
showMessage("SD卡存储空间不足,请进行清理");
return ;
}
loadLength+=current;
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.setMessage("亲,努力下载中。。。");
progressDialog.show();
progressDialog.setMax((int) total);
progressDialog.setProgress((int) loadLength);
Log.e("亲,努力下载中。。。",((double)loadLength)/((double)total) + "%");
}
/**
* 下载完成
* @param result File此文件就是apk的全部文件路径对象
*/
@Override
public void onSuccess(File result) {
loadLength = 0;
Toast.makeText(SplashActivity.this, "下载成功", Toast.LENGTH_SHORT).show();
AndroidUtils.installApk(SplashActivity.this,result);
progressDialog.dismiss();
}
@Override
public void onError(Throwable ex, boolean isOnCallback) {
ex.printStackTrace();
Toast.makeText(SplashActivity.this, "下载失败,请检查网络和SD卡", Toast.LENGTH_SHORT).show();
progressDialog.dismiss();
}
@Override
public void onCancelled(CancelledException cex) {
}
@Override
public void onFinished() {
}
});
}
}