[置顶] AndroidAPP更新升级完整实现Demo(搭建本地服务器)
2015-11-07 16:39
791 查看
市场上的Android应用都能够自动提示升级更新,这里就完整的来实现一下AndroidAPP,实现自动升级的功能。
Demo地址:http://download.csdn.net/detail/ericfantastic/9250609
效果图:
具体如何实现,其实不难,先看看流程:
本地AndroidApp必须要先有一个版本号用于标识当前版本,再从服务器获取服务器最新版本,进行相比较。
实现流程:
1、Manifest.xml添加联网权限,读写SD卡权限,版本号versionCode和版本名versionName,其中versionCode用来比较版本使用的变量,versionName为用于显示在界面上的版本字符串。
2、activity_main.xml布局文件,简单的几个控件。
3、MainActivity.java界面初始化,调用更新类的方法,刷新页面数据。
4、UpdateManager.java更新工具类,包含获取本地版本信息,服务器版本信息,下载apk文件等方法。
具体实现都在UpdateManager类中,详细说明一下,其中,
getVersion(Context context)、getVersionName(Context context)本地版本的获取很简单一看就懂;
getServerVersion()服务器版本的获取:读取服务器目录下的ver.aspx文件,返回json字符串;
compareVersion(Context context)比较版本:启动线程,读取json字符串,并解析服务器版本赋值到serverVersion中,并且比较本地版本和服务器版本,如果低于服务器版本,就启动新线程下载apk文件;
downloadApkFile(Context context)下载apk文件:设置文件保存路径,服务器访问路径,通过HTTP协议下载文件,这里测试的时候,apk文件无法下载,故将服务器的apk修改扩展名为png格式,下载完成后保存为apk文件。
搭建本地Web服务器:
1、开启功能:控制面板-> 程序-> 程序和功能 -> 打开或关闭Windows功能,将“Internet信息服务”下的所有功能都打开。
2、设置防火墙:控制面板-> 系统安全 -> Windows防火墙 -> 允许程序通过Windows防火墙,勾选“万维网服务(HTTP)”。
3、以上步骤完成后,web服务器就搭好了,可以win+R,运行cmd,键入ipconfig /all ,查看本机IP地址,打开浏览器输入地址ip地址测试一下,如果打开的是IIS7网页,说明成功了。
然后就是将新版本的apk放到服务器目录下,一般是系统盘目录下C:\inetpub\wwwroot文件夹中。
放置两个文件,一个是2.0版本的apk文件,一个是ver.aspx文件用于获取服务器版本的json字符串,里面的内容为:[{"appname":"AndroidUpdateDemo","apkname":"AndroidUpdateDemo.apk","versionName":"02.00.01","version":"2"}] 。
由于测试时候apk文件无法直接下载,想了个办法将apk文件扩展名改为png,在Android端下载完成后把它在保存为apk文件。
上述操作结束后,服务器端就完全搭好了,可以开始测试升级流程。
Demo地址:http://download.csdn.net/detail/ericfantastic/9250609
效果图:
具体如何实现,其实不难,先看看流程:
本地AndroidApp必须要先有一个版本号用于标识当前版本,再从服务器获取服务器最新版本,进行相比较。
实现流程:
1、Manifest.xml添加联网权限,读写SD卡权限,版本号versionCode和版本名versionName,其中versionCode用来比较版本使用的变量,versionName为用于显示在界面上的版本字符串。
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.eric.androidupdatedemo" android:versionCode="1" android:versionName="01.00.01" > <uses-permission android:name='android.permission.INTERNET'/> <!-- 联网权限 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <!-- 写入SD卡权限 --> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <!-- 在SD卡中创建和删除文件的权限 --> <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="14" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
2、activity_main.xml布局文件,简单的几个控件。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.eric.androidupdatedemo.MainActivity" > <TextView android:id="@+id/textview_id" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello_world" /> <Button android:id="@+id/button_id" android:layout_width="fill_parent" android:layout_height="40dp" android:layout_below="@id/textview_id" android:textColor="#FFF" android:text="检查更新" android:background="@drawable/buttonbg" /> <ProgressBar android:id="@+id/progressBar_id" style="@android:style/Widget.ProgressBar.Horizontal" android:layout_width="match_parent" android:layout_height="40dp" android:layout_below="@id/button_id" android:layout_marginTop="10dp" android:visibility="gone"/> </RelativeLayout>
3、MainActivity.java界面初始化,调用更新类的方法,刷新页面数据。
package com.eric.androidupdatedemo; import java.io.File; import android.app.Activity; import android.app.AlertDialog; import android.app.AlertDialog.Builder; import android.content.Context; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.Message; import android.view.View; import android.view.View.OnClickListener; import android.view.Window; import android.widget.Button; import android.widget.ProgressBar; import android.widget.TextView; public class MainActivity extends Activity { private TextView textView; public static int version,serverVersion; public static String versionName,serverVersionName,downloadResult; private Button btn; private ProgressBar proBar; public static receiveVersionHandler handler; private UpdateManager manager = UpdateManager.getInstance(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView = (TextView) findViewById(R.id.textview_id); btn = (Button) findViewById(R.id.button_id); proBar=(ProgressBar)findViewById(R.id.progressBar_id); Context c = this; version = manager.getVersion(c); versionName = manager.getVersionName(c); textView.setText("当前版本号:"+version+"\n"+"当前版本名:"+versionName); handler = new receiveVersionHandler(); //检查更新按钮点击事件 btn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { manager.compareVersion(MainActivity.this); } }); } public class receiveVersionHandler extends Handler{ @Override public void handleMessage(Message msg) { proBar.setProgress(msg.arg1); proBar.setVisibility(R.id.button_id); textView.setText("下载进度:"+msg.arg1); if(msg.arg1 == 100){ Intent intent = new Intent(Intent.ACTION_VIEW); String path = Environment.getExternalStorageDirectory()+"/AndroidUpdateDemo.apk"; intent.setDataAndType(Uri.fromFile(new File(path)), "application/vnd.android.package-archive"); startActivity(intent); } proBar.setVisibility(R.id.button_id); } } }
4、UpdateManager.java更新工具类,包含获取本地版本信息,服务器版本信息,下载apk文件等方法。
package com.eric.androidupdatedemo; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.net.HttpURLConnection; import java.net.URL; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import android.R.integer; import android.app.AlertDialog; import android.app.AlertDialog.Builder; import android.content.Context; import android.content.DialogInterface; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.Looper; import android.os.Message; /* *@author Eric *@2015-11-7上午8:03:31 */ public class UpdateManager { private static UpdateManager manager = null; private UpdateManager(){} public static UpdateManager getInstance(){ manager = new UpdateManager(); return manager; } //获取版本号 public int getVersion(Context context){ int version = 0; try { version = context.getPackageManager().getPackageInfo( "com.eric.androidupdatedemo", 0).versionCode; } catch (Exception e) { System.out.println("获取版本号异常!"); } return version; } //获取版本名 public String getVersionName(Context context){ String versionName = null; try { versionName = context.getPackageManager().getPackageInfo( "com.eric.androidupdatedemo", 0).versionName; } catch (Exception e) { System.out.println("获取版本名异常!"); } return versionName; } //获取服务器版本号 public String getServerVersion(){ String serverJson = null; byte[] buffer = new byte[128]; try { URL serverURL = new URL("http://192.168.226.106/ver.aspx"); HttpURLConnection connect = (HttpURLConnection) serverURL.openConnection(); BufferedInputStream bis = new BufferedInputStream(connect.getInputStream()); int n = 0; while((n = bis.read(buffer))!= -1){ serverJson = new String(buffer); } } catch (Exception e) { System.out.println("获取服务器版本号异常!"+e); } return serverJson; } //比较服务器版本与本地版本弹出对话框 public boolean compareVersion(Context context){ final Context contextTemp = context; new Thread(){ public void run() { Looper.prepare(); String serverJson = manager.getServerVersion(); //解析Json数据 try { JSONArray array = new JSONArray(serverJson); JSONObject object = array.getJSONObject(0); String getServerVersion = object.getString("version"); String getServerVersionName = object.getString("versionName"); MainActivity.serverVersion = Integer.parseInt(getServerVersion); MainActivity.serverVersionName = getServerVersionName; if(MainActivity.version < MainActivity.serverVersion){ //弹出一个对话框 AlertDialog.Builder builder = new Builder(contextTemp); builder.setTitle("版本更新" ) ; builder.setMessage("当前版本:"+MainActivity.versionName +"\n"+"服务器版本:"+MainActivity.serverVersionName ) ; builder.setPositiveButton("立即更新",new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int arg1) { //开启线程下载apk new Thread(){ public void run() { Looper.prepare(); downloadApkFile(contextTemp); Looper.loop(); }; }.start(); } }); builder.setNegativeButton("下次再说", null); builder.show(); }else{ AlertDialog.Builder builder = new Builder(contextTemp); builder.setTitle("版本信息" ) ; builder.setMessage("当前已经是最新版本" ) ; builder.setPositiveButton("确定",null); builder.show(); } } catch (JSONException e) { e.printStackTrace(); System.out.println("获取服务器版本线程异常!"+e); } Looper.loop(); }; }.start(); return false; } //下载apk文件 public void downloadApkFile(Context context){ String savePath = Environment.getExternalStorageDirectory()+"/AndroidUpdateDemo.apk"; String serverFilePath = "http://192.168.226.106/AndroidUpdateDemo.png"; try { if(Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())){ URL serverURL = new URL(serverFilePath); HttpURLConnection connect = (HttpURLConnection) serverURL.openConnection(); BufferedInputStream bis = new BufferedInputStream(connect.getInputStream()); File apkfile = new File(savePath); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(apkfile)); int fileLength = connect.getContentLength(); int downLength = 0; int progress = 0; int n; byte[] buffer = new byte[1024]; while((n=bis.read(buffer, 0, buffer.length))!=-1){ bos.write(buffer, 0, n); downLength +=n; progress = (int) (((float) downLength / fileLength) * 100); Message msg = new Message(); msg.arg1 = progress; MainActivity.handler.sendMessage(msg); //System.out.println("发送"+progress); } bis.close(); bos.close(); connect.disconnect(); } } catch (Exception e) { System.out.println("下载出错!"+e); } /*AlertDialog.Builder builder = new Builder(context); builder.setTitle("下载apk" ) ; builder.setMessage("正在下载" ) ; builder.setPositiveButton("确定",null); builder.show();*/ } }
具体实现都在UpdateManager类中,详细说明一下,其中,
getVersion(Context context)、getVersionName(Context context)本地版本的获取很简单一看就懂;
getServerVersion()服务器版本的获取:读取服务器目录下的ver.aspx文件,返回json字符串;
compareVersion(Context context)比较版本:启动线程,读取json字符串,并解析服务器版本赋值到serverVersion中,并且比较本地版本和服务器版本,如果低于服务器版本,就启动新线程下载apk文件;
downloadApkFile(Context context)下载apk文件:设置文件保存路径,服务器访问路径,通过HTTP协议下载文件,这里测试的时候,apk文件无法下载,故将服务器的apk修改扩展名为png格式,下载完成后保存为apk文件。
搭建本地Web服务器:
1、开启功能:控制面板-> 程序-> 程序和功能 -> 打开或关闭Windows功能,将“Internet信息服务”下的所有功能都打开。
2、设置防火墙:控制面板-> 系统安全 -> Windows防火墙 -> 允许程序通过Windows防火墙,勾选“万维网服务(HTTP)”。
3、以上步骤完成后,web服务器就搭好了,可以win+R,运行cmd,键入ipconfig /all ,查看本机IP地址,打开浏览器输入地址ip地址测试一下,如果打开的是IIS7网页,说明成功了。
然后就是将新版本的apk放到服务器目录下,一般是系统盘目录下C:\inetpub\wwwroot文件夹中。
放置两个文件,一个是2.0版本的apk文件,一个是ver.aspx文件用于获取服务器版本的json字符串,里面的内容为:[{"appname":"AndroidUpdateDemo","apkname":"AndroidUpdateDemo.apk","versionName":"02.00.01","version":"2"}] 。
由于测试时候apk文件无法直接下载,想了个办法将apk文件扩展名改为png,在Android端下载完成后把它在保存为apk文件。
上述操作结束后,服务器端就完全搭好了,可以开始测试升级流程。
相关文章推荐
- 线程的坑
- Fragment的展现与Activity状态丢失 IllegalStateException:Can not perform this action after onSaveInstanceState
- iOS开发系列之Objective-C基础:KVO(键值观察机制)
- 微信开发中bug的修复和遇到的问题。
- ios多线程编程
- OSX/iOS中多路I/O复用总结
- Erlang application配置之.app文件
- AndroidManifest 中original-package标签
- android svg
- RegExp 的一些基本介绍
- Android 之 Binder与进程间通信
- 编译和测试android的驱动程序学习笔记
- (iOS)Storyboard 与 initWithCoder -- designated initializer小结
- IOS 的plis他 用法 小样
- 简易易懂的android回调的实现
- IOS 的 plist方法 好记性不如看博客
- Android之Socket通信、List加载更多、Spinner下拉列表
- [转]iOS容易造成循环引用的三种场景,就在你我身边!
- Xposed (一) Android hook框架入门
- Intellij IDEA配置Android Annotations注解框架