本文實例為大家分享了Android App自動更新通知欄下載的具體代碼,供大家參考,具體內容如下
版本更新說明
這里有調用UpdateService啟動服務檢查下載安裝包等
1. 文件下載,下完后寫入到sdcard
2. 如何在通知欄上顯示下載進度
3. 下載完畢自動安裝
4. 如何判斷是否有新版本
版本更新的主類
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
|
package com.wei.update; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.HashMap; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.json.JSONException; import org.json.JSONObject; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserFactory; import com.wei.util.MyApplication; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageManager.NameNotFoundException; import android.os.Handler; /** * 版本更新主類,這里有調用UpdateService啟動服務檢查下載安裝包等 1. 文件下載,下完后寫入到sdcard 2. 如何在通知欄上顯示下載進度 * 3. 下載完畢自動安裝 4. 如何判斷是否有新版本 * * @author david */ public class UpdateManager { private static String packageName; // = "com.yipinzhe"; // 應用的包名 private static String jsonUrl = "version.txt" ; // JSON版本文件URL private static String xmlUrl = "version.xml" ; // XML版本文件URL private static final String DOWNLOAD_DIR = "/" ; // 應用下載后保存的子目錄 private Context mContext; HashMap<String, String> mHashMap; // 保存解析的XML信息 int versionCode, isNew; public UpdateManager(Context context) { this .mContext = context; packageName = context.getPackageName(); jsonUrl = MyApplication.site + jsonUrl; xmlUrl = MyApplication.site + xmlUrl; checkVersion(); } Handler checkHandler = new Handler() { @Override public void handleMessage(android.os.Message msg) { if (msg.what == 1 ) { // 發現新版本,提示用戶更新 StringBuffer message = new StringBuffer(); message.append(mHashMap.get( "note" ).replace( "|" , "\n" )); AlertDialog.Builder alert = new AlertDialog.Builder(mContext); alert.setTitle( "軟件升級" ) .setMessage(message.toString()) .setPositiveButton( "更新" , new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // 開啟更新服務UpdateService System.out.println( "你點擊了更新" ); Intent updateIntent = new Intent( mContext, UpdateService. class ); /** * updateIntent.putExtra("downloadDir", * DOWNLOAD_DIR); * updateIntent.putExtra("apkUrl", * mHashMap.get("url")); */ mContext.startService(updateIntent); } }) .setNegativeButton( "取消" , new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); alert.create().show(); } }; }; /** *檢查是否有新版本 */ public void checkVersion() { try { // 獲取軟件版本號,對應AndroidManifest.xml下android:versionCode versionCode = mContext.getPackageManager().getPackageInfo( packageName, 0 ).versionCode; } catch (NameNotFoundException e) { e.printStackTrace(); } new Thread() { @Override public void run() { String result = null ; /** * try { //如果服務器端是JSON文本文件 result = * MyApplication.handleGet(jsonUrl); if (result != null) { * mHashMap = parseJSON(result); } } catch (Exception e1) { * e1.printStackTrace(); } */ InputStream inStream = null ; try { // 本機XML文件 inStream = UpdateManager. class .getClassLoader().getResourceAsStream( "version.xml" ); // 如果服務器端是XML文件 inStream = new URL(xmlUrl).openConnection().getInputStream(); if (inStream != null ) mHashMap = parseXml(inStream); } catch (Exception e1) { e1.printStackTrace(); } if (mHashMap != null ) { int serviceCode = Integer.valueOf(mHashMap.get( "version" )); if (serviceCode > versionCode) { // 版本判斷,返回true則有新版本 isNew = 1 ; } } checkHandler.sendEmptyMessage(isNew); }; }.start(); } /** *解析服務器端的JSON版本文件 */ public HashMap<String, String> parseJSON(String str) { HashMap<String, String> hashMap = new HashMap<String, String>(); try { JSONObject obj = new JSONObject(str); hashMap.put( "version" , obj.getString( "version" )); hashMap.put( "name" , obj.getString( "name" )); hashMap.put( "url" , obj.getString( "url" )); hashMap.put( "note" , obj.getString( "note" )); } catch (JSONException e) { e.printStackTrace(); } return hashMap; } /** *解析服務器端的XML版本文件 */ public HashMap<String, String> parseXml(InputStream inputStream) { HashMap<String, String> hashMap = new HashMap<String, String>(); try { XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser(); parser.setInput(inputStream, "GBK" ); //設置數據源編碼 int eventCode = parser.getEventType(); //獲取事件類型 while (eventCode != XmlPullParser.END_DOCUMENT) { System.out.println( "循環開始" ); switch (eventCode){ case XmlPullParser.START_DOCUMENT: //開始讀取XML文檔 System.out.println( "START_DOCUMENT" ); break ; case XmlPullParser.START_TAG: //開始讀取某個標簽 if ( "version" .equals(parser.getName())) { hashMap.put(parser.getName(), parser.nextText()); } else if ( "name" .equals(parser.getName())) { hashMap.put(parser.getName(), parser.nextText()); } else if ( "url" .equals(parser.getName())) { hashMap.put(parser.getName(), parser.nextText()); } else if ( "note" .equals(parser.getName())) { hashMap.put(parser.getName(), parser.nextText()); } break ; case XmlPullParser.END_TAG: break ; } eventCode = parser.next(); //繼續讀取下一個元素節點,并獲取事件碼 } System.out.println(hashMap.get( "version" )); } catch (Exception e) { } return hashMap; /** *try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document document = builder.parse(inStream); Element root = document.getDocumentElement();//獲取根節點 NodeList childNodes = root.getChildNodes();//獲得所有子節點,然后遍歷 for (int j = 0; j < childNodes.getLength(); j++) { Node childNode = childNodes.item(j); if (childNode.getNodeType() == Node.ELEMENT_NODE) { Element childElement = (Element) childNode; if ("version".equals(childElement.getNodeName())) { hashMap.put("version", childElement.getFirstChild() .getNodeValue()); } else if (("name".equals(childElement.getNodeName()))) { hashMap.put("name", childElement.getFirstChild() .getNodeValue()); } else if (("url".equals(childElement.getNodeName()))) { hashMap.put("url", childElement.getFirstChild() .getNodeValue()); } else if (("note".equals(childElement.getNodeName()))) { hashMap.put("note", childElement.getFirstChild() .getNodeValue()); } } } } catch (Exception e) { e.printStackTrace(); }*/ } } |
版本更新的服務類
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
|
package com.wei.update; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import com.wei.util.MyApplication; import com.wei.wotao.R; //import android.annotation.SuppressLint; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.content.Intent; import android.net.Uri; import android.os.Environment; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.view.View; import android.widget.RemoteViews; /** * 下載安裝包的服務類 * @author david */ public class UpdateService extends Service { // 文件存儲 private File saveDir; private File saveFile; private String apkUrl; // 通知欄 private NotificationManager updateNotificationManager = null ; private Notification updateNotification = null ; // 通知欄跳轉Intent private Intent updateIntent = null ; private PendingIntent updatePendingIntent = null ; // 下載狀態 private final static int DOWNLOAD_COMPLETE = 0 ; private final static int DOWNLOAD_FAIL = 1 ; private RemoteViews contentView; @Override public int onStartCommand(Intent intent, int flags, int startId) { System.out.println( "onStartCommand" ); contentView = new RemoteViews(getPackageName(), R.layout.activity_app_update); // 獲取傳值 String downloadDir = intent.getStringExtra( "downloadDir" ); apkUrl = MyApplication.site+intent.getStringExtra( "apkUrl" ); // 如果有SD卡,則創建APK文件 if (android.os.Environment.MEDIA_MOUNTED.equals(android.os.Environment .getExternalStorageState())) { saveDir = new File(Environment.getExternalStorageDirectory(), downloadDir); saveFile = new File(saveDir.getPath(), getResources() .getString(R.string.app_name) + ".apk" ); } this .updateNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); this .updateNotification = new Notification(); // 設置下載過程中,點擊通知欄,回到主界面 updateIntent = new Intent(); updatePendingIntent = PendingIntent.getActivity( this , 0 , updateIntent, 0 ); // 設置通知欄顯示內容 updateNotification.icon = R.drawable.icon_info; updateNotification.tickerText = "開始下載" ; updateNotification.contentView.setProgressBar(R.id.progressBar1, 100 , 0 , true ); updateNotification.setLatestEventInfo( this , getResources().getString(R.string.app_name), "0%" , updatePendingIntent); // 發出通知 updateNotificationManager.notify( 0 , updateNotification); new Thread( new DownloadThread()).start(); return super .onStartCommand(intent, flags, startId); } @Override public IBinder onBind(Intent intent) { return null ; } /** *下載的線程 */ private class DownloadThread implements Runnable { Message message = updateHandler.obtainMessage(); public void run() { message.what = DOWNLOAD_COMPLETE; if (saveDir!= null && !saveDir.exists()) { saveDir.mkdirs(); } if (saveFile!= null && !saveFile.exists()) { try { saveFile.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } try { long downloadSize = downloadFile(apkUrl, saveFile); if (downloadSize > 0 ) { // 下載成功 updateHandler.sendMessage(message); } } catch (Exception ex) { ex.printStackTrace(); message.what = DOWNLOAD_FAIL; updateHandler.sendMessage(message); // 下載失敗 } } public long downloadFile(String downloadUrl, File saveFile) throws Exception { int downloadCount = 0 ; int currentSize = 0 ; long totalSize = 0 ; int updateTotalSize = 0 ; int rate = 0 ; // 下載完成比例 HttpURLConnection httpConnection = null ; InputStream is = null ; FileOutputStream fos = null ; try { URL url = new URL(downloadUrl); httpConnection = (HttpURLConnection) url.openConnection(); httpConnection.setRequestProperty( "User-Agent" , "PacificHttpClient" ); if (currentSize > 0 ) { httpConnection.setRequestProperty( "RANGE" , "bytes=" + currentSize + "-" ); } httpConnection.setConnectTimeout( 200000 ); httpConnection.setReadTimeout( 200000 ); updateTotalSize = httpConnection.getContentLength(); //獲取文件大小 if (httpConnection.getResponseCode() == 404 ) { throw new Exception( "fail!" ); } is = httpConnection.getInputStream(); fos = new FileOutputStream(saveFile, false ); byte buffer[] = new byte [ 1024 * 1024 * 3 ]; int readsize = 0 ; while ((readsize = is.read(buffer)) != - 1 ) { fos.write(buffer, 0 , readsize); totalSize += readsize; //已經下載的字節數 rate = ( int ) (totalSize * 100 / updateTotalSize); //當前下載進度 // 為了防止頻繁的通知導致應用吃緊,百分比增加10才通知一次 if ((downloadCount == 0 ) || rate - 0 > downloadCount) { downloadCount += 1 ; updateNotification.setLatestEventInfo( UpdateService. this , "正在下載" , rate + "%" , updatePendingIntent); //設置通知的內容、標題等 updateNotification.contentView.setProgressBar(R.id.progressBar1, 100 , rate, true ); updateNotificationManager.notify( 0 , updateNotification); //把通知發布出去 } } } finally { if (httpConnection != null ) { httpConnection.disconnect(); } if (is != null ) { is.close(); } if (fos != null ) { fos.close(); } } return totalSize; } } private Handler updateHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case DOWNLOAD_COMPLETE: //當下載完畢,自動安裝APK(ps,打電話 發短信的啟動界面工作) Uri uri = Uri.fromFile(saveFile); //根據File獲得安裝包的資源定位符 Intent installIntent = new Intent(Intent.ACTION_VIEW); //設置Action installIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); //新的Activity會在一個新任務打開,而不是在原先的任務棧 installIntent.setDataAndType(uri, "application/vnd.android.package-archive" ); //設置URI的數據類型 startActivity(installIntent); //把打包的Intent傳遞給startActivity //當下載完畢,更新通知欄,且當點擊通知欄時,安裝APK updatePendingIntent = PendingIntent.getActivity(UpdateService. this , 0 , installIntent, 0 ); updateNotification.defaults = Notification.DEFAULT_SOUND; // 鈴聲提醒 updateNotification.setLatestEventInfo(UpdateService. this , getResources().getString(R.string.app_name), "下載完成,點擊安裝" , updatePendingIntent); updateNotificationManager.notify( 0 , updateNotification); // 停止服務 stopService(updateIntent); break ; case DOWNLOAD_FAIL: // 下載失敗 updateNotification.setLatestEventInfo(UpdateService. this , getResources().getString(R.string.app_name), "下載失敗,網絡連接超時" , updatePendingIntent); updateNotificationManager.notify( 0 , updateNotification); break ; default : stopService(updateIntent); break ; } } }; } |
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:https://blog.csdn.net/jueblog/article/details/15013635