以上便是全部流程,步骤很简单,接下来就是代码实现
package com.gtlxkj.cn.util;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Environment;
public class VersionUtils {
/**
* 检查是否存在SDCard
*
* @return
*/
public static boolean hasSdcard() {
String state = Environment.getExternalStorageState();
if (state.equals(Environment.MEDIA_MOUNTED)) {
return true;
} else {
return false;
}
}
/**
* 2 * 获取版本
*/
public static int getVersion(Context context) {
try {
PackageManager manager = context.getPackageManager();
PackageInfo info = manager.getPackageInfo(context.getPackageName(),0);
int versioncode = info.versionCode;
return versioncode;
} catch (Exception e) {
e.printStackTrace();
}
return 0;
}
/**
* 2 * 获取版本名称
*/
public static String getVersionName(Context context) {
try {
PackageManager manager = context.getPackageManager();
PackageInfo info = manager.getPackageInfo(context.getPackageName(),0);
String version = info.versionName;
return version;
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
}
/**
* 主页Activity
*
*/
@ContentView(R.layout.activity_home)
public class HomeActivity extends BaseActivity implements View.OnClickListener {
@ViewInject(R.id.btn_upload)
private Button btn_upload;
@ViewInject(R.id.update_apk)
private TextView update_apk;
private Context context = HomeActivity.this;
private VersionDialog dialog;
private boolean flag;//是否检测版本初始化
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i("HomeActivity", "onCreate");
initListener();
Utils.deleteLocal(new File(ConfigurationUtil.APK_PATH_ABSOULT+"GTLXKJ.apk"));//删除旧的apk
flag=true;
// 获取本版本号,是否更新
getVersion(VersionUtils.getVersion(this));
}
//初始点击事件
private void initListener(){
Log.i("HomeActivity", "initListener");
update_apk.setOnClickListener(this);
update_apk.setText("版本号 V"+Tools.getVersionName(this));
}
/**
* 点击事件
* @param view
*/
public void onClick(View v) {
Log.i("HomeActivity", "onClick");
switch(v.getId()){
case R.id.update_apk:
flag=false;
getVersion(Tools.getVersion(this));
break;
}
}
//版本更新弹出框
public void showUploadApkDialog(String content,String versionName) {
Log.i("HomeActivity", "showUploadTaskDialog");
dialog = new VersionDialog(this,R.style.mystyle,this,R.layout.version__update_dialog,content,versionName);
dialog.show();
}
// 获取更新版本号
private void getVersion(final int vision) {
if (!NetWorkUtil.isNetworkAvalible(context)) {
Toast.makeText(HomeActivity.this,"请检查网络",Toast.LENGTH_SHORT).show();
return;
}
RequestParams params = new RequestParams(ConfigurationUtil.WEBVERSION);
x.http().get(params, new Callback.ProgressCallback() {
@Override
public void onSuccess(String result) {
Log.i("onSuccess", "onSuccess");
try{
JSONObject object = new JSONObject(result);
//返回状态
String status = object.optString("code");
//返回的更新内容
String content = object.optString("content");
//返回的版本号
String versionName = object.optString("msg");
//返回版本
String nversion = object.optString("data");
if("1".equals(status)){
int newversion = Integer.parseInt(nversion);
if (newversion != vision) {//新旧版本比较
if (vision < newversion) {//旧版本低于新版本则更新
System.out.println("新版本:v"+newversion + " 旧版本v"+ vision);
// 版本号不同
showUploadApkDialog(content,versionName);
}
}else if(!flag){
Toast.makeText(HomeActivity.this,"已经是最新版本",Toast.LENGTH_SHORT).show();
}
}
}catch(Exception e){
e.printStackTrace();
Log.e("onSuccess", "Error");
}
}
@Override
public void onCancelled(CancelledException arg0) {
Log.i("onCancelled", "onCancelled");
}
@Override
public void onError(Throwable arg0, boolean arg1) {
Log.e("onError", "onError");
Toast.makeText(HomeActivity.this,"请求服务器无响应",Toast.LENGTH_SHORT).show();
}
@Override
public void onFinished() {
Log.i("onFinished", "onFinished");
}
@Override
public void onLoading(long arg0, long arg1, boolean arg2) {
Log.i("onLoading", "onLoading");
}
@Override
public void onStarted() {
Log.i("onStarted", "onStarted");
}
@Override
public void onWaiting() {
Log.i("onWaiting", "onWaiting");
}
});
}
}
后台用的springboot,具体接口比较简单就不展示了
AndroidManifest.xml文件中这里配置版本号,发布新版本apk到服务器上时不要忘了修改这里的版本号
//下载apk
public void downloadApk(String apkUrl) throws PackageManager.NameNotFoundException {
Utils.deleteLocal(new File(ConfigurationUtil.APK_PATH_ABSOULT+"GTLXKJ.apk"));//删除旧的apk
Uri uri = Uri.parse(apkUrl);
DownloadManager downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
DownloadManager.Request request = new DownloadManager.Request(uri);
// 设置允许使用的网络类型,这里是移动网络和wifi都可以
request.setAllowedNetworkTypes(request.NETWORK_MOBILE | request.NETWORK_WIFI);
//设置是否允许漫游
request.setAllowedOverRoaming(true);
//设置文件类型
MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton();
String mimeString = mimeTypeMap.getMimeTypeFromExtension(MimeTypeMap.getFileExtensionFromUrl(apkUrl));
request.setMimeType(mimeString);
//在通知栏中显示
request.setNotificationVisibility(request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.setTitle("正在下载");
request.setVisibleInDownloadsUi(true);
//sdcard目录下的download文件夹
request.setDestinationInExternalPublicDir(ConfigurationUtil.APK_PATH, "GTLXKJ.apk");
// 将下载请求放入队列
downloadManager.enqueue(request);
}
此处使用DownloadManager 下载apk
package com.gtlxkj.cn.activity;
import java.io.File;
import com.gtlxkj.cn.util.ConfigurationUtil;
import com.gtlxkj.cn.util.Utils;
import android.app.DownloadManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
public class InstallReceiver extends BroadcastReceiver {
// 安装下载接收器
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) {
installApk(context);
}
}
// 安装Apk
private void installApk(Context context) {
try {
Intent i = new Intent(Intent.ACTION_VIEW);
String filePath = ConfigurationUtil.APK_PATH_ABSOULT+"GTLXKJ.apk";
System.out.println(filePath);
i.setDataAndType(Uri.parse("file://" + filePath), "application/vnd.android.package-archive");
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
} catch (Exception e) {
e.printStackTrace();
}
}
}
权限:
receiver:
package com.gtlxkj.cn.dialog;
import com.gtlxkj.cn.R;
import com.gtlxkj.cn.activity.HomeActivity;
import com.gtlxkj.cn.util.ConfigurationUtil;
import android.app.Dialog;
import android.content.Context;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
/**
* 自定义dialog
*/
public class VersionDialog extends Dialog implements
View.OnClickListener {
/**
* 布局文件
**/
int layoutRes;
/**
* 上下文对象
**/
Context context;
/**
* 取消按钮
**/
private Button bt_cancal;
/**
* 更新按钮
**/
private Button bt_delect;
private String content;//版本内容
private String versionName;//版本号
private HomeActivity homeActivity;
public VersionDialog(Context context) {
super(context);
this.context = context;
}
/**
* 自定义布局的构造方法
*
* @param context
* @param resLayout
*/
public VersionDialog(Context context, int resLayout) {
super(context);
this.context = context;
this.layoutRes = resLayout;
}
/**
* 自定义主题及布局的构造方法
*
* @param context
* @param theme
* @param resLayout
* @param postion
*/
public VersionDialog(Context context,int theme, HomeActivity activity,int resLayout,String content,String versionName) {
super(context, theme);
this.context = context;
this.content = content;
this.layoutRes = resLayout;
this.homeActivity = activity;
this.versionName = versionName;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 指定布局
this.setContentView(layoutRes);
TextView textView=(TextView) findViewById(R.id.version_content);
TextView titleView=(TextView) findViewById(R.id.lay_view);
textView.setText("更新内容:\n\n"+content);
titleView.setText("发现新版本 "+versionName);
// 根据id在布局中找到控件对象
bt_cancal = (Button) findViewById(R.id.cancal);
bt_delect = (Button) findViewById(R.id.update);
// 为按钮绑定点击事件监听器
bt_cancal.setOnClickListener(this);
bt_delect.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.update:
optUpdateApk();
this.dismiss();
break;
// 取消按钮
case R.id.cancal:
this.dismiss();
default:
break;
}
}
/**
* 操作 版本更新
*
*/
private void optUpdateApk( ) {
try {
homeActivity.downloadApk(ConfigurationUtil.APKHOST);
} catch (NameNotFoundException e) {
e.printStackTrace();
}
}
}
注意此升级代码是在onUpgrade方法内实现,
这样更新完app后重新启动就会初始化升级本地数据库结构了
public class LXApplication extends Application {
// Effective Java 第一版推荐写法
private static class LXApplicationHolder {
private static final LXApplication INSTANCE = new LXApplication();
}
public LXApplication() {
}
public static final LXApplication getInstance() {
return LXApplicationHolder.INSTANCE;
}
public static DbManager.DaoConfig daoConfig;
@Override
public void onCreate() {
super.onCreate();
CrashHandler crashHandler = CrashHandler.getInstance();
crashHandler.init(this);
x.Ext.init(this);
x.Ext.setDebug(true);
dbinit();
}
//xutils3初始化
private void dbinit() {
File file = new File(ConfigurationUtil.SDFILE + "db");
if (!file.exists()) {
file.mkdirs();
}
daoConfig = new DbManager.DaoConfig()
.setDbName(ConfigurationUtil.DBNAME)
.setDbDir(file).setDbVersion(ConfigurationUtil.DBVERSION)
.setAllowTransaction(true)
.setDbOpenListener(new DbManager.DbOpenListener() {
@Override
public void onDbOpened(DbManager db) {
// 开启WAL, 对写入加速提升巨大
db.getDatabase().enableWriteAheadLogging();
}
}).setDbUpgradeListener(new DbManager.DbUpgradeListener() {
@Override
public void onUpgrade(DbManager db, int oldVersion, int newVersion) {//数据库升级
try {
for (int j = oldVersion; j <= newVersion; j++) {
switch(newVersion){
case 2:
//增加表字段
db.addColumn(Person.class, "name");
break;
case 3:
/**
*保留历史数据的升级数据库
*/
// db.execSQL(""); //第一步将旧表改为临时表
//db.execSQL(""); //第二步创建新表(新添加的字段或去掉 的字段)
//db.execSQL(""); //第三步将旧表中的原始数据保存到新表中以防遗失
//db.execSQL(""); //第四步删除临时备份表
break;
case 4://其他操作
// TODO: ...
// db.dropTable(...);
// ...
// or
// db.dropDb();
break;
default:
break;
}
}
} catch (DbException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).setTableCreateListener(new DbManager.TableCreateListener() {// 设置表创建的监听
@Override
public void onTableCreated(DbManager arg0, TableEntity> arg1) {
Log.i("sjl__", "onTableCreated:" + arg1.getName());
}
});
}
public DbManager.DaoConfig getDbConfig() {
if (daoConfig == null) {
dbinit();
}
return daoConfig;
}
private static List activityLists = new ArrayList();
// 添加Activity到容器中
public static void addActivity(Activity activity) {
activityLists.add(activity);
}
// 遍历所有Activity并finish
public static void exit() {
try {
for (Activity activity : activityLists) {
activity.finish();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
数据库升级在此文中没有过多的说明,有需要的可以百度,有关资料还是很多的,也比较简单,打好的apk包放到服务器上,安卓请求这个apk链接就可以下载,版本升级切记打包的时候要使配置的版本和服务器接口内的版本一致同步,