Android 应用检查更新并下载
1.在Android应用当中都有应用检查更新的要求,往往都是在打开应用的时候去更新下载。
实现的方法是:服务器端提供接口,接口中可以包含在最新APK下载的URL,最新APK的VersionCode,等附带信息。
将最新APK的Versioncode与当前的APP的VersionCode做大小比较就可以知道是否是最新版本,如果是最新版本就下载安装。
2.效果图:
4.上代码:
借用别人的接口:http://jcodecraeer.com/update.php
AppVersion:是版本信息的模型类,基本上和服务端返回的东西是相对应的。
DownloadService:是下载模块。
UpdateChecker:是检查更新,调用下载模块,下载完安装的工具类。
PS:注意Service在Manifest.xml中要申明。
AppVersion:
1 public class AppVersion { 2 3 private String updateMessage; 4 private String apkUrl; 5 private int apkCode; 6 public static final String APK_DOWNLOAD_URL = "url"; 7 public static final String APK_UPDATE_CONTENT = "updateMessage"; 8 public static final String APK_VERSION_CODE = "versionCode"; 9 10 public String getUpdateMessage() { 11 return updateMessage; 12 } 13 14 public void setUpdateMessage(String updateMessage) { 15 this.updateMessage = updateMessage; 16 } 17 18 public String getApkUrl() { 19 return apkUrl; 20 } 21 22 public void setApkUrl(String apkUrl) { 23 this.apkUrl = apkUrl; 24 } 25 26 public int getApkCode() { 27 return apkCode; 28 } 29 30 public void setApkCode(int apkCode) { 31 this.apkCode = apkCode; 32 } 33 34 }
DownloadService:
1 public class DownloadService extends IntentService { 2 3 public static final int UPDATE_PROGRESS = 8344; 4 5 public DownloadService() { 6 super("DownloadService"); 7 } 8 9 @Override 10 protected void onHandleIntent(Intent intent) { 11 String urlToDownload = intent.getStringExtra("url"); 12 System.out.println("URLtOdOWNLOAD-->>" +urlToDownload); 13 String fileDestination = intent.getStringExtra("dest"); 14 ResultReceiver receiver = (ResultReceiver) intent 15 .getParcelableExtra("receiver"); 16 try { 17 URL url = new URL(urlToDownload); 18 URLConnection connection = url.openConnection(); 19 connection.connect(); 20 // this will be useful so that you can show a typical 0-100% 21 // progress bar 22 int fileLength = connection.getContentLength(); 23 // download the file 24 InputStream input = new BufferedInputStream( 25 connection.getInputStream()); 26 OutputStream output = new FileOutputStream(fileDestination); 27 byte data[] = new byte[100]; 28 long total = 0; 29 int count; 30 while ((count = input.read(data)) != -1) { 31 total += count; 32 // publishing the progress.... 33 Bundle resultData = new Bundle(); 34 resultData.putInt("progress", (int) (total * 100 / fileLength)); 35 receiver.send(UPDATE_PROGRESS, resultData); 36 output.write(data, 0, count); 37 } 38 output.flush(); 39 output.close(); 40 input.close(); 41 } catch (IOException e) { 42 e.printStackTrace(); 43 } 44 Bundle resultData = new Bundle(); 45 resultData.putInt("progress", 100); 46 receiver.send(UPDATE_PROGRESS, resultData); 47 } 48 }
UpdateChecker:
1 public class UpdateChecker { 2 private static final String TAG = "UpdateChecker"; 3 private Context mContext; 4 // 检查版本信息的线程 5 private Thread mThread; 6 // 版本对比地址 7 private String mCheckUrl; 8 private AppVersion mAppVersion; 9 // 下载apk的对话框 10 private ProgressDialog mProgressDialog; 11 12 private File apkFile; 13 14 public void setCheckUrl(String url) { 15 mCheckUrl = url; 16 } 17 18 public UpdateChecker(Context context) { 19 mContext = context; 20 // instantiate it within the onCreate method 21 mProgressDialog = new ProgressDialog(context); 22 mProgressDialog.setMessage("正在下载"); 23 mProgressDialog.setIndeterminate(false); 24 mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); 25 mProgressDialog.setCancelable(true); 26 mProgressDialog 27 .setOnCancelListener(new DialogInterface.OnCancelListener() { 28 @Override 29 public void onCancel(DialogInterface dialog) { 30 31 } 32 }); 33 mProgressDialog 34 .setOnDismissListener(new DialogInterface.OnDismissListener() { 35 @Override 36 public void onDismiss(DialogInterface dialog) { 37 // TODO Auto-generated method stub 38 39 } 40 }); 41 } 42 43 public void checkForUpdates() { 44 if (mCheckUrl == null) { 45 // throw new Exception("checkUrl can not be null"); 46 return; 47 } 48 final Handler handler = new Handler() { 49 public void handleMessage(Message msg) { 50 if (msg.what == 1) { 51 mAppVersion = (AppVersion) msg.obj; 52 try { 53 int versionCode = mContext.getPackageManager() 54 .getPackageInfo(mContext.getPackageName(), 0).versionCode; 55 System.out.println("version-->" + versionCode 56 + " mAppVersion.getApkCode()-->>" 57 + mAppVersion.getApkCode()); 58 if (mAppVersion.getApkCode() > versionCode) { 59 showUpdateDialog(); 60 } else { 61 Toast.makeText(mContext, "已经是最新版本", 62 Toast.LENGTH_SHORT).show(); 63 } 64 } catch (PackageManager.NameNotFoundException ignored) { 65 // 66 } 67 } 68 } 69 }; 70 71 mThread = new Thread() { 72 @Override 73 public void run() { 74 // if (isNetworkAvailable(mContext)) { 75 Message msg = new Message(); 76 String json = sendPost(); 77 Log.i("jianghejie", "json = " + json); 78 if (json != null) { 79 AppVersion appVersion = parseJson(json); 80 msg.what = 1; 81 msg.obj = appVersion; 82 handler.sendMessage(msg); 83 } else { 84 Log.e(TAG, "can't get app update json"); 85 } 86 } 87 }; 88 mThread.start(); 89 } 90 91 protected String sendPost() { 92 HttpURLConnection uRLConnection = null; 93 InputStream is = null; 94 BufferedReader buffer = null; 95 String result = null; 96 try { 97 URL url = new URL(mCheckUrl); 98 uRLConnection = (HttpURLConnection) url.openConnection(); 99 uRLConnection.setDoInput(true); 100 uRLConnection.setDoOutput(true); 101 uRLConnection.setRequestMethod("POST"); 102 uRLConnection.setUseCaches(false); 103 uRLConnection.setConnectTimeout(10 * 1000); 104 uRLConnection.setReadTimeout(10 * 1000); 105 uRLConnection.setInstanceFollowRedirects(false); 106 uRLConnection.setRequestProperty("Connection", "Keep-Alive"); 107 uRLConnection.setRequestProperty("Charset", "UTF-8"); 108 uRLConnection 109 .setRequestProperty("Accept-Encoding", "gzip, deflate"); 110 uRLConnection 111 .setRequestProperty("Content-Type", "application/json"); 112 uRLConnection.connect(); 113 is = uRLConnection.getInputStream(); 114 String content_encode = uRLConnection.getContentEncoding(); 115 if (null != content_encode && !"".equals(content_encode) 116 && content_encode.equals("gzip")) { 117 is = new GZIPInputStream(is); 118 } 119 buffer = new BufferedReader(new InputStreamReader(is)); 120 StringBuilder strBuilder = new StringBuilder(); 121 String line; 122 while ((line = buffer.readLine()) != null) { 123 strBuilder.append(line); 124 } 125 result = strBuilder.toString(); 126 } catch (Exception e) { 127 Log.e(TAG, "http post error", e); 128 } finally { 129 if (buffer != null) { 130 try { 131 buffer.close(); 132 } catch (IOException e) { 133 e.printStackTrace(); 134 } 135 } 136 if (is != null) { 137 try { 138 is.close(); 139 } catch (IOException e) { 140 e.printStackTrace(); 141 } 142 } 143 if (uRLConnection != null) { 144 uRLConnection.disconnect(); 145 } 146 } 147 return result; 148 } 149 150 private AppVersion parseJson(String json) { 151 AppVersion appVersion = new AppVersion(); 152 try { 153 JSONObject obj = new JSONObject(json); 154 String updateMessage = obj.getString(AppVersion.APK_UPDATE_CONTENT); 155 String apkUrl = obj.getString(AppVersion.APK_DOWNLOAD_URL); 156 int apkCode = obj.getInt(AppVersion.APK_VERSION_CODE); 157 System.out.println("updateMessage-->" + updateMessage 158 + " apkUrl-->>" + apkUrl + " apkCode-->>" + apkCode); 159 appVersion.setApkCode(apkCode); 160 appVersion.setApkUrl(apkUrl); 161 appVersion.setUpdateMessage(updateMessage); 162 } catch (JSONException e) { 163 Log.e(TAG, "parse json error", e); 164 } 165 return appVersion; 166 } 167 168 public void showUpdateDialog() { 169 AlertDialog.Builder builder = new AlertDialog.Builder(mContext); 170 // builder.setIcon(R.drawable.icon); 171 builder.setTitle("有新版本"); 172 builder.setMessage(mAppVersion.getUpdateMessage()); 173 builder.setPositiveButton("下载", new DialogInterface.OnClickListener() { 174 public void onClick(DialogInterface dialog, int whichButton) { 175 downLoadApk(); 176 } 177 }); 178 builder.setNegativeButton("忽略", new DialogInterface.OnClickListener() { 179 public void onClick(DialogInterface dialog, int whichButton) { 180 181 } 182 }); 183 builder.show(); 184 } 185 186 public void downLoadApk() { 187 String apkUrl = mAppVersion.getApkUrl(); 188 System.out.println("apkUrl-->>" + apkUrl); 189 String dir = mContext.getExternalFilesDir("apk").getAbsolutePath(); 190 File folder = Environment.getExternalStoragePublicDirectory(dir); 191 if (folder.exists() && folder.isDirectory()) { 192 // do nothing 193 } else { 194 folder.mkdirs(); 195 } 196 String filename = apkUrl.substring(apkUrl.lastIndexOf("/"), 197 apkUrl.length()); 198 String destinationFilePath = dir + "/" + filename; 199 apkFile = new File(destinationFilePath); 200 mProgressDialog.show(); 201 Intent intent = new Intent(mContext, DownloadService.class); 202 intent.putExtra("url", apkUrl); 203 intent.putExtra("dest", destinationFilePath); 204 intent.putExtra("receiver", new DownloadReceiver(new Handler())); 205 mContext.startService(intent); 206 } 207 208 private class DownloadReceiver extends ResultReceiver { 209 public DownloadReceiver(Handler handler) { 210 super(handler); 211 } 212 213 @Override 214 protected void onReceiveResult(int resultCode, Bundle resultData) { 215 super.onReceiveResult(resultCode, resultData); 216 if (resultCode == DownloadService.UPDATE_PROGRESS) { 217 int progress = resultData.getInt("progress"); 218 mProgressDialog.setProgress(progress); 219 if (progress == 100) { 220 mProgressDialog.dismiss(); 221 // 如果没有设置SDCard写权限,或者没有sdcard,apk文件保存在内存中,需要授予权限才能安装 222 String[] command = { "chmod", "777", apkFile.toString() }; 223 try { 224 ProcessBuilder builder = new ProcessBuilder(command); 225 builder.start(); 226 Intent intent = new Intent(Intent.ACTION_VIEW); 227 intent.setDataAndType(Uri.fromFile(apkFile), 228 "application/vnd.android.package-archive"); 229 mContext.startActivity(intent); 230 } catch (Exception e) { 231 232 } 233 } 234 } 235 } 236 } 237 }
MainActivity:
1 public class MainActivity extends Activity { 2 UpdateChecker update; 3 @Override 4 protected void onCreate(Bundle savedInstanceState) { 5 super.onCreate(savedInstanceState); 6 setContentView(R.layout.activity_main); 7 update = new UpdateChecker(MainActivity.this); 8 findViewById(R.id.btn).setOnClickListener(new OnClickListener() { 9 10 @Override 11 public void onClick(View v) { 12 update.setCheckUrl("http://jcodecraeer.com/update.php"); 13 update.checkForUpdates(); 14 } 15 }); 16 } 17 18 }
源码下载:下载