使用方法:
1.修改MainActivity中********部分,就是自己的xml文件的地址(文章后面xml文件的事例是我们公司的,地址不能给你们用,自己 想办法吧)
2.根据xml文件的格式,修改PULL解析部分
其他不用改,就可以用
思路:
1.获取当前版本号
2.通过地址找到xml文件,解析xml文件,得到最新版本号
3.对比两个版本号
4.如果版本不一样,弹出升级提示对话框
5.点击升级对话框的确定按钮,显示下载文件进度条,同时下载文件
6.文件下载成功后,等待三秒,进入安装界面
7.安装完毕,升级成功
难点:
1.用到线程的地方比较多
遇到的问题:
1.android高版本是无法在主线程中进行好事操作的,一定要开线程来执行。
2.线程想要更新主UI界面,可以在Handler中进行
AndroidManifest.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.up"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:allowBackup="true"
android:hardwareAccelerated="false"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.up.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>
MainActivity
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import android.os.Bundle;
import android.app.Activity;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
updata();
}
private void updata() {
// TODO Auto-generated method stub
//********为XML的地址
new Upgrade(this,"http://********");
}
}
Upgrade 类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import org.xmlpull.v1.XmlPullParser;
import com.example.up.UpdataInfo;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.DialogInterface.OnClickListener;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.util.Xml;
import android.widget.Toast;
public class Upgrade {
/*
* 成员解释
* UPDATA_CLIENT:更新
* GET_UNDATAINFO_ERROR:链接异常
* DOWN_ERROR:下载时出错
* UpdataInfo:包含版本信息的类
* mContext:升级界面的activity
* updataURL:网络上的xml文件
*/
private static final int UPDATA_CLIENT = 100;
private static final int GET_UNDATAINFO_ERROR = 101;
private static final int DOWN_ERROR = 102;
private static final String TAG = "升级更新程序";
private UpdataInfo info = null;
private Context mContext;
private String updataURL;
public Upgrade(Context context,String updataURL) {
// TODO Auto-generated constructor stub
this.mContext = context;
this.updataURL=updataURL;
/*
* 版本对比
*/
Thread t = new Thread(new CheckVersionTask());
t.start();
}
/*
* 检测是否升级的方法:
* 注意,只有Looper内可以进行主UI的操作
*/
class CheckVersionTask implements Runnable {
@Override
public void run() {
Looper.prepare();
try {
//1.获取当前APK的版本
String thisVersionName=getVersionName(mContext);
//2.根据xml的地址,获取版本类,调用版本类.getVersion()获得最新的版本号方法
info = getUpdataInfo(updataURL);
String newVersionName=info.getVersion();
//3.传入两个版本号进行比较
versionCpmpare(thisVersionName, newVersionName);
} catch (Exception e) {
//如果出现连接超时异常,向Handler发送GET_UNDATAINFO_ERROR
Message msg = new Message();
msg.what = GET_UNDATAINFO_ERROR;
handler.sendMessage(msg);
e.printStackTrace();
}
Looper.loop();
}
}
/*
* Handler:
* 用来接收信息
* 信息如果是 UPDATA_CLIENT执行方法四
* 信息如果是 GET_UNDATAINFO_ERROR执行无操作
* 信息如果是 DOWN_ERROR无操作
*/
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
//可以升级
case UPDATA_CLIENT:
//提示更新对话框
showUpdataDialog();
break;
//连接超时
case GET_UNDATAINFO_ERROR:
Log.i("程序升级","获取服务器更新信息失败");
// LoginMain();
break;
//下载apk失败
case DOWN_ERROR:
Log.i("程序升级","下载apk失败");
// LoginMain();
break;
}
}
};
/*
* 方法一:
* 获取当前程序的版本号
*/
protected String getVersionName(Context context) throws Exception {
PackageManager packageManager = context.getPackageManager();
PackageInfo packInfo = packageManager.getPackageInfo(
context.getPackageName(), 0);
return packInfo.versionName;
}
/*
* 方法二:
* 用pull解析xml文件 获得版本类
* path:xml文件的地址
*
*/
protected UpdataInfo getUpdataInfo(String path) throws Exception {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
InputStream is = conn.getInputStream();
XmlPullParser parser = Xml.newPullParser();
parser.setInput(is, "utf-8");
int type = parser.getEventType();
UpdataInfo info = new UpdataInfo();// 实体
//注意,更具不同格式的xml文件的解析方法需要进行调整
while (type != XmlPullParser.END_DOCUMENT) {
switch (type) {
case XmlPullParser.START_TAG:
//如果xml的标签名为UpdateInfo
if ("UpdateInfo".equals(parser.getName())) {
//如果UpdateInfo标签的第一个属性为YES
if ("YES".equals(parser.getAttributeValue(0))) {
//获取版本号,也就是xml中UpdateInfo标签的第二个属性
info.setVersion(parser.getAttributeValue(1));
}
}
//如果xml的标签名为DownloadUrl,获取要升级APK文件的地址
else if ("DownloadUrl".equals(parser.getName())) {
info.setUrl(parser.nextText());
}
//如果xml的标签名为ResultText,获取要升级的信息
else if ("ResultText".equals(parser.getName())) {
info.setDescription(parser.nextText());
}
break;
}
type = parser.next();
}
return info;
}
/*
* 方法三:
* 版本对比
* 如果版本相等,不作处理
* 如果版本不相等,向Handler发送UPDATA_CLIENT
*/
protected void versionCpmpare(String thisVersionName,String newVersionName){
if (thisVersionName.equals(newVersionName)) {
Log.i("版本比较", "版本号相同无需升级");
Toast.makeText(mContext, "版本相同无需升级", Toast.LENGTH_SHORT).show();
} else {
Log.i("版本比较", "版本号不同 ,提示用户升级 ");
Toast.makeText(mContext, "版本不同,可以升级", Toast.LENGTH_SHORT).show();
Message msg = new Message();
msg.what = UPDATA_CLIENT;
handler.sendMessage(msg);
}
}
/*
* 方法四:
* 弹出对话框通知用户更新程序
*/
protected void showUpdataDialog() {
AlertDialog.Builder builer = new AlertDialog.Builder(mContext);
builer
.setTitle("版本升级")
.setMessage(info.getDescription())
.setPositiveButton("确定", new OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Log.i("", "下载apk,更新");
downLoadApk();
}
})
.setNegativeButton("取消", new OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
})
.create().show();
}
/*
* 方法五:
* 下载APK
* 先初始化一个进度条pd,因为下载是耗时操作,所以要开启一个线程,用来下载文件和来更新进度条进度
* 如果出现连接超时异常,向Handler发送DOWN_ERROR
*/
protected void downLoadApk() {
//初始化进度条
final ProgressDialog pd;
pd = new ProgressDialog(mContext);
pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pd.setMessage("正在下载更新");
pd.show();
//
new Thread() {
@Override
public void run() {
try {
File file = getFileFromServer(pd);
sleep(3000);
installApk(file);
pd.dismiss();
} catch (Exception e) {
Message msg = new Message();
msg.what = DOWN_ERROR;
handler.sendMessage(msg);
e.printStackTrace();
}
}
}.start();
}
/*
* 方法六:
* 下载文件的方法
* "updata.apk"为下载后的文件名
* file是下载的apk文件
*/
protected File getFileFromServer( ProgressDialog pd)
throws Exception {
URL url = new URL(info.getUrl());
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
pd.setMax(conn.getContentLength());
InputStream is = conn.getInputStream();
File file = new File(Environment.getExternalStorageDirectory(),
"updata.apk");
FileOutputStream fos = new FileOutputStream(file);
BufferedInputStream bis = new BufferedInputStream(is);
byte[] buffer = new byte[1024];
int len;
int total = 0;
while ((len = bis.read(buffer)) != -1) {
fos.write(buffer, 0, len);
total += len;
pd.setProgress(total);
}
fos.close();
bis.close();
is.close();
return file;
}
/*
* 方法七:
* 安装APK对话框
* 点击对话框中的 确定 就可以安装了,这是一个android自带的安装器
* file是下载的apk文件
*/
protected void installApk( File file) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file),
"application/vnd.android.package-archive");
mContext.startActivity(intent);
}
}
UpdataInfo类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class UpdataInfo {
private String version;
private String url;
private String description;
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
本文章所用xml文件内容为,因为这个是公司的,所以不给你们用了,以后我会补充一个自己的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<UpdateInfo updateAvailabe="YES" currentVersion="1.0.2" updateStyle="Required" fid="f07823990785ba0e46c98f8b6bfc72fb" updateTime="2014-1-8 9:59:50" appSize="12499332" requiredSdk="">
<DataResult resultCode="0">
<ResultText>
<![CDATA[ 获取升级信息成功 ]]>
</ResultText>
</DataResult>
<DownloadUrl>
<![CDATA[
http://119.167.245.69:8090/play?fid=f07823990785ba0e46c98f8b6bfc72fb&uid=0&auth=aaa&keyid=32768
]]>
</DownloadUrl>
<DetailUrl>
<![CDATA[ ]]>
</DetailUrl>
<Introduction>
<![CDATA[ ]]>
</Introduction>
</UpdateInfo>