1.当进入应用程序时,就需要去服务器上获取
版本信息。
2.获取当前应用的版本与服务器上的版本进行
匹配,如果服务器上的版本高于本地版本,
就提示更新。
3.下载安装程序
步骤:
1.建立一个web工程
用xml格式在服务器上建立版本信息
Version.xml
<version> <versionName>XXX软件</versionName> <versionCode>2</versionCode> </version> |
放在WebRoot目录下
访问服务器是耗时操作,需要用到子线程。
一、拿到xml
在安卓工程里,建立一个VersionThread内部类继承Thread
实现run方法
A.创建一个统一资源标识符对象,标识version.xml
uri=new URI("http://10.0.2.2:8080/MyServer/Version.xml");
B.得到一个HttpClient对象HttpClient client = new DefaultHttpClient();
C.得到一个HttpPost请求对象HttpPost request = new HttpPost(uri);
D.通过HttpClient执行请求,返回一个HttpResponse响应对象
E.将响应的消息实体转化为字符串
String JsonStr=EntityUtils.toString(response.getEntity(),”utf-8”);
F.添加网络权限
<uses-permission android:name="android.permission.INTERNET"/>
二、解析xml,获取服务器上的版本信息
1.创建读取版本号的方法,传入xmlStr的String类型的参数
2.创建一个XmlPullParser对象:XmlPullParser parser=Xml.newPullParser();
3.通过StringReader可以很方便的将一个字符串读取为一串串流
StringReader sr=new StringReader(xmlStr);
4.使用XmlPullParser.setInput()方法设置解析器的输入。
parser.setInput(sr);
5.获取标签的状态
Int eventType=parser.getEventType();
While(eventType!=XmlPullParser.END_DOCUMENT){
........如果parser.getName是”versionName”,就获取到版本名。
同理,获取版本号。
}
6.XmlPullParser通过next(),依次向下检查
7.在run里调用该方法。
XmlPullParser可以用于解释xml文件。这里有两种xml的常见格式:<entry>Hello</entry>和<Entry value="Six" />,在Android XML中使用后者,而这种方式在XmlPullParser中处理也非常方便。它的使用方式归纳如下: 1. XmlPullParser通过next(),依次向下检查 2. XmlPullParser是事件驱动,如果检测到END_DOCUMENT,应当停止继续检测 3. XmlPullParser是事件驱动,当检测到START_TAG,可以读出<AAAA bbbb=xxxx c=yyyyy>的内容,其中AAAA可通过getName()来获取,属性的个数,可通过getAttributeCount()获取,属性的名词和内容可分别通过getAttributeName(index)和getAttributeValue(index)来获取。 4. XmlPullParser是事件驱动,如果是END_TAG,则为</AAAA>,可以通过getName()来获得AAAA的内容 5. 对于<entry>Hello</entry>这种方式,如果要获取中间的数值,则事件为XmlPullParser.TEXT,可通过getText()来获取内容。 6. 由于xml文件可能书写不正确,或者我们在解释的过程中处理不正确,应当使用异常捕获的方式来处理。 |
三、获得本地的版本号
1.创建一个方法,返回类型为int
2.获取当前应用包的信息
PackageInfo info = getPackageManager().getPackageInfo(getPackageName(), 0);
注意:init方法启动了线程,要等请求回来后再来获取本地的版本号,所以要使用Handler。
四、判断是否需要更新下载软件
1.创建handler对象
2.调用dispatchMessage方法
3.在子线程通知handler请求已完成。
4.把bin/bt.apk文件拷贝到MyServer的WebRoot目录下
5.在handler里面
A.获取本地版本号
B.进行判断是否需要更新
C.弹出一个对话框: 在初始化方法里 创建对话框
D.创建一个下载的线程的内部类。
a.创建一个统一资源标识符对象,标识version.xml
uri=new URI("http://10.0.2.2:8080/MyServer/Version.xml");
b.得到一个HttpClient对象HttpClient client = new DefaultHttpClient();
c.得到一个HttpPost请求对象HttpPost request = new HttpPost(uri);
d.通过HttpClient执行请求,返回一个HttpResponse响应对象
e.获得服务器端的输入流
InputStream is = response.getEntity().getContent();
f.获得sdcard。File apkfile=new File(sd卡的路径,文件名);apkfile = new File(Environment.getExternalStorageDirectory(),"lsn3_19.apk");
g.获取spk文件的输出流
FileOutputStream out = new FileOutputStream(apkfile);
h.读取服务器apk文件的数据
void java.io.FileOutputStream.write(byte[] buffer, int byteOffset, int byteCount) throws IOException 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流。 第一个参数:-数据。定义byte数组的时候要定义大小,一般都是 1024b,这里定义的是Byte[] buffer=new byte[1024*4];就好像一个桶,一个桶 4*1024 接水, 接满4*1024 就倒过去。1k = 1024b 第二个参数:-数据写入是起始偏移量。 第三个参数:-要写入的字节数。使用int java.io.InputStream.read(byte[] buffer) throws IOException方法,从输入流中读取一定数量的字节,并将其存储在缓冲区数组 buffer 中。如果 buffer 的长度为 0,则不读取任何字节并返回 0;否则,尝试读取至少一个字节。如果因为流位于文件末尾而没有可用的字节,则返回值 -1;否则,至少读取一个字节并将其存储在buffer 中。 |
i.往apk文件中写数据
当输入流位于文件末尾有可用的字节(不等于-1),就写入输入流。
while((length = is.read(buffer))!=-1){
out.write(buffer, 0, length);
}
j.关闭输出流
k.关闭输入流
l.在更新按钮的点击事件里启动下载线程
m.在handler里提示更新成功
添加安装权限;
n.添加写sdcard的权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
具体代码
package com.tb.bt;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
import com.tb.projo.LocalContact;
import android.R.layout;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ContentResolver;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Xml;
import android.widget.Toast;
public class TwoActivity extends Activity {
String versionName;
int versionCode;
AlertDialog.Builder builder;
File f;
Handler handler=new Handler(){
@Override
public void dispatchMessage(Message msg) {
super.dispatchMessage(msg);
switch (msg.what) {
case 0:
int code=getLocalVersionCode();
System.out.println(code);
if(code<versionCode){
builder.show();
}
break;
case 1://隐式意图
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(f),"application/vnd.android.package-archive");
startActivity(intent);
Toast.makeText(TwoActivity.this, "软件更新成功", Toast.LENGTH_LONG).show();
break;
default:
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.two);
init();
}
private void init() {
builder = new AlertDialog.Builder(TwoActivity.this);
builder.setTitle("检测更新");
builder.setMessage("已检测到新版本,是否更新?");
builder.setPositiveButton("更新", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
DownloadThread d=new DownloadThread();
d.start();
}
}).setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
Thread t=new VersionThread();
t.start();
}
//拿到xml
class VersionThread extends Thread{
@Override
public void run() {
URI uri;
try {
uri=new URI("http://10.0.2.2:8080/MyServer/Version.xml");
HttpClient client=new DefaultHttpClient();
HttpPost request=new HttpPost(uri);
HttpResponse response=client.execute(request);
String VersionStr=EntityUtils.toString(response.getEntity(), "UTF-8");
readXmlToVersionCode(VersionStr);
handler.sendEmptyMessage(0);
} catch (URISyntaxException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//读取服务端版本号的方法
public void readXmlToVersionCode(String VersionStr){
try {
XmlPullParser parser=Xml.newPullParser();
StringReader sr=new StringReader(VersionStr);
parser.setInput(sr);
int eventType=parser.getEventType();
while(eventType!=XmlPullParser.END_DOCUMENT){
switch (eventType) {
case XmlPullParser.START_TAG:
String Start_Tag=parser.getName();
if(Start_Tag.equals("versionName")){
versionName=parser.nextText();
}
else if(Start_Tag.equals("versionCode")){
versionCode=Integer.parseInt(parser.nextText());
}
break;
default:
break;
}
eventType=parser.next();
}
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//读取本地版本号的方法
public int getLocalVersionCode(){
try {
PackageInfo info = getPackageManager().getPackageInfo(getPackageName(), 0);
return info.versionCode;
} catch (NameNotFoundException e) {
e.printStackTrace();
}
return 0;
}
//下载的线程
class DownloadThread extends Thread{
@Override
public void run() {
URI uri;
try {
uri=new URI("http://10.0.2.2:8080/MyServer/bt.apk");
HttpClient client=new DefaultHttpClient();
HttpPost request=new HttpPost(uri);
HttpResponse response=client.execute(request);
InputStream is=response.getEntity().getContent();
f=new File(Environment.getExternalStorageDirectory(),"bt.apk");
FileOutputStream out=new FileOutputStream(f);
byte [] buffer = new byte[1024 * 4];
int length;
while((length = is.read(buffer))!=-1){
out.write(buffer, 0, length);
}
out.close();
is.close();
handler.sendEmptyMessage(1);
} catch (URISyntaxException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}