Android第五期 - 更新自己的apk本地与网络两种方法
首先是本地: ParseXmlService部分: 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 package com.szy.update; import java.io.InputStream; import java.util.HashMap; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** *@authorcoolszy *@date2012-4-26 *@bloghttp://blog.92coding.com */ public class ParseXmlService { public HashMap<String,String>parseXml(InputStreaminStream) throws Exception { HashMap<String,String>hashMap= new HashMap<String,String>(); //实例化一个文档构建器工厂 DocumentBuilderFactoryfactory=DocumentBuilderFactory.newInstance(); //通过文档构建器工厂获取一个文档构建器 DocumentBuilderbuilder=factory.newDocumentBuilder(); //通过文档通过文档构建器构建一个文档实例 Documentdocument=builder.parse(inStream); //获取XML文件根节点 Elementroot=document.getDocumentElement(); //获得所有子节点 NodeListchildNodes=root.getChildNodes(); for ( int j= 0 ;j<childNodes.getLength();j++) { //遍历子节点 NodechildNode=(Node)childNodes.item(j); if (childNode.getNodeType()==Node.ELEMENT_NODE) { ElementchildElement=(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()); } } } return hashMap; } } UpdateManager部分: 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 308 309 310 311 312 313 package com.gaoxiaotongctone.update; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.util.HashMap; import com.gaoxiaotongctone.R; import android.app.AlertDialog; import android.app.AlertDialog.Builder; import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.content.Intent; import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Resources.NotFoundException; 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.view.LayoutInflater; import android.view.View; import android.widget.ProgressBar; public class UpdateManager{ /*下载中*/ privatestaticfinalintDOWNLOAD=1; /*下载结束*/ privatestaticfinalintDOWNLOAD_FINISH=2; /*保存解析的XML信息*/ HashMap<String,String>mHashMap; /*下载保存路径*/ privateStringmSavePath; /*记录进度条数量*/ privateintprogress; /*是否取消更新*/ privatebooleancancelUpdate=false; privateContextmContext; /*更新进度条*/ privateProgressBarmProgress; privateDialogmDownloadDialog; privateHandlermHandler=newHandler(){ @Override publicvoidhandleMessage(Messagemsg){ switch(msg.what){ //正在下载 caseDOWNLOAD: //设置进度条位置 mProgress.setProgress(progress); break; caseDOWNLOAD_FINISH: //安装文件 installApk(); break; default: break; } }; }; publicUpdateManager(Contextcontext){ this.mContext=context; } /** *检测软件更新 * *@throwsIOException *@throwsNotFoundException */ publicvoidcheckUpdate()throwsNotFoundException,IOException{ newThread(newRunnable(){ @Override publicvoidrun(){ //TODOAuto-generatedmethodstub try{ if(isUpdate()){ //显示提示对话框 Looper.prepare(); showNoticeDialog(); Looper.loop(); Log.d("消息","有新版本"); }else{ //Toast.makeText(mContext,R.string.soft_update_no, //Toast.LENGTH_LONG).show(); Log.d("消息","已是最新版本"); } }catch(NotFoundExceptione){ //TODOAuto-generatedcatchblock //Toast.makeText(UpdateManager.this,"QQ空间",2).show(); e.printStackTrace(); }catch(IOExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); } } }).start(); } /** *检查软件是否有更新版本 * *@return *@throwsIOException */ privatebooleanisUpdate()throwsIOException{ //获取当前软件版本 intversionCode=getVersionCode(mContext); //把version.xml放到src,然后获取文件信息 InputStreaminStream= ParseXmlService.class.getClassLoader().getResourceAsStream("version.xml"); InputStreaminStream=urlConn.getInputStream(); //解析XML文件。由于XML文件比较小,因此使用DOM方式进行解析 ParseXmlServiceservice=newParseXmlService(); try{ mHashMap=service.parseXml(inStream); }catch(Exceptione){ e.printStackTrace(); } if(null!=mHashMap){ intserviceCode=Integer.valueOf(mHashMap.get("version"));//String.valueOf("serviceCode"+"---"+serviceCode) //Toast.makeText(UpdateManager.this,'',Toast.LENGTH_SHORT).show(); Log.i("-----serviceCode",""+serviceCode); Log.i("-----versionCode",""+versionCode); //版本判断 if(serviceCode>versionCode){ returntrue; } }else{ Log.i("-----null==mHashMap","null==mHashMap"); } returnfalse; } /** *获取软件版本号 * *@paramcontext *@return */ privateintgetVersionCode(Contextcontext){ intversionCode=0; try{ //获取软件版本号,对应AndroidManifest.xml下android:versionCode versionCode=context.getPackageManager().getPackageInfo( "com.gaoxiaotongctone",0).versionCode; }catch(NameNotFoundExceptione){ e.printStackTrace(); } returnversionCode; } /** *显示软件更新对话框 */ privatevoidshowNoticeDialog(){ //构造对话框 AlertDialog.Builderbuilder=newBuilder(mContext); builder.setTitle(R.string.soft_update_title); builder.setMessage(R.string.soft_update_info); //更新 builder.setPositiveButton(R.string.soft_update_updatebtn, newOnClickListener(){ @Override publicvoidonClick(DialogInterfacedialog,intwhich){ dialog.dismiss(); //显示下载对话框 showDownloadDialog(); } }); //稍后更新 builder.setNegativeButton(R.string.soft_update_later, newOnClickListener(){ @Override publicvoidonClick(DialogInterfacedialog,intwhich){ dialog.dismiss(); } }); DialognoticeDialog=builder.create(); noticeDialog.show(); } /** *显示软件下载对话框 */ privatevoidshowDownloadDialog(){ //构造软件下载对话框 AlertDialog.Builderbuilder=newBuilder(mContext); builder.setTitle(R.string.soft_updating); //给下载对话框增加进度条 finalLayoutInflaterinflater=LayoutInflater.from(mContext); Viewv=inflater.inflate(R.layout.sotfupdate_progress,null); mProgress=(ProgressBar)v.findViewById(R.id.update_progress); builder.setView(v); //取消更新 builder.setNegativeButton(R.string.soft_update_cancel, newOnClickListener(){ @Override publicvoidonClick(DialogInterfacedialog,intwhich){ dialog.dismiss(); //设置取消状态 cancelUpdate=true; } }); mDownloadDialog=builder.create(); mDownloadDialog.show(); //现在文件 downloadApk(); } /** *下载apk文件 */ privatevoiddownloadApk(){ //启动新线程下载软件 newdownloadApkThread().start(); } /** *下载文件线程 */ privateclassdownloadApkThreadextendsThread{ @Override publicvoidrun(){ try{ //判断SD卡是否存在,并且是否具有读写权限 if(Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED)){ //获得存储卡的路径 Stringsdpath=Environment.getExternalStorageDirectory() +"/"; mSavePath=sdpath+"download"; URLurl=newURL(mHashMap.get("url")); //创建连接 HttpURLConnectionconn=(HttpURLConnection)url .openConnection(); conn.connect(); //获取文件大小 intlength=conn.getContentLength(); //创建输入流 InputStreamis=conn.getInputStream(); Filefile=newFile(mSavePath); //判断文件目录是否存在 if(!file.exists()){ file.mkdir(); } FileapkFile=newFile(mSavePath,mHashMap.get("name")); FileOutputStreamfos=newFileOutputStream(apkFile); intcount=0; //缓存 bytebuf[]=newbyte[1024]; //写入到文件中 do{ intnumread=is.read(buf); count+=numread; //计算进度条位置 progress=(int)(((float)count/length)*100); //更新进度 mHandler.sendEmptyMessage(DOWNLOAD); if(numread<=0){ //下载完成 mHandler.sendEmptyMessage(DOWNLOAD_FINISH); break; } //写入文件 fos.write(buf,0,numread); }while(!cancelUpdate);//点击取消就停止下载. fos.close(); is.close(); } }catch(MalformedURLExceptione){ e.printStackTrace(); }catch(IOExceptione){ e.printStackTrace(); } //取消下载对话框显示 mDownloadDialog.dismiss(); } }; /** *安装APK文件 */ private void installApk(){ Fileapkfile= new File(mSavePath,mHashMap.get( "name" )); if (!apkfile.exists()){ return ; } //通过Intent安装APK文件 Intenti= new Intent(Intent.ACTION_VIEW); i.setDataAndType(Uri.parse( "file://" +apkfile.toString()), "application/vnd.android.package-archive" ); mContext.startActivity(i); } } MainActivity.java部分: 1 2 3 4 5 6 7 8 9 @Override public void onCreate(BundlesavedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.main); UpdateManagermanager= new UpdateManager(MainActivity. this ); manager.checkUpdate(); } 别忘了xml中给权限。 version.xml部分: 1 2 3 4 5 < update > < version >2</ version > < name >彩通科技</ name > < url >http://imp.ctone.net/Frame/ctone.apk</ url > </ update > 网络链接UpdateManager.java部分: 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 308 309 310 311 312 package com.gaoxiaotongctone.update; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.util.HashMap; import com.gaoxiaotongctone.R; import android.app.AlertDialog; import android.app.AlertDialog.Builder; import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.content.Intent; import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Resources.NotFoundException; 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.view.LayoutInflater; import android.view.View; import android.widget.ProgressBar; public class UpdateManager{ /*下载中*/ privatestaticfinalintDOWNLOAD=1; /*下载结束*/ privatestaticfinalintDOWNLOAD_FINISH=2; /*保存解析的XML信息*/ HashMap<String,String>mHashMap; /*下载保存路径*/ privateStringmSavePath; /*记录进度条数量*/ privateintprogress; /*是否取消更新*/ privatebooleancancelUpdate=false; privateContextmContext; /*更新进度条*/ privateProgressBarmProgress; privateDialogmDownloadDialog; privateHandlermHandler=newHandler(){ @Override publicvoidhandleMessage(Messagemsg){ switch(msg.what){ //正在下载 caseDOWNLOAD: //设置进度条位置 mProgress.setProgress(progress); break; caseDOWNLOAD_FINISH: //安装文件 installApk(); break; default: break; } }; }; publicUpdateManager(Contextcontext){ this.mContext=context; } /** *检测软件更新 * *@throwsIOException *@throwsNotFoundException */ publicvoidcheckUpdate()throwsNotFoundException,IOException{ newThread(newRunnable(){ @Override publicvoidrun(){ //TODOAuto-generatedmethodstub try{ if(isUpdate()){ //显示提示对话框 Looper.prepare(); showNoticeDialog(); Looper.loop(); Log.d("消息","有新版本"); }else{ //Toast.makeText(mContext,R.string.soft_update_no, //Toast.LENGTH_LONG).show(); Log.d("消息","已是最新版本"); } }catch(NotFoundExceptione){ //TODOAuto-generatedcatchblock //Toast.makeText(UpdateManager.this,"QQ空间",2).show(); e.printStackTrace(); }catch(IOExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); } } }).start(); } /** *检查软件是否有更新版本 * *@return *@throwsIOException */ privatebooleanisUpdate()throwsIOException{ //获取当前软件版本 intversionCode=getVersionCode(mContext); //把version.xml放到网络上,然后获取文件信息 URLurl=newURL("http://imp.ctone.net/Frame/version.xml"); HttpURLConnectionurlConn=(HttpURLConnection)url.openConnection(); InputStreaminStream=urlConn.getInputStream(); //解析XML文件。由于XML文件比较小,因此使用DOM方式进行解析 ParseXmlServiceservice=newParseXmlService(); try{ mHashMap=service.parseXml(inStream); }catch(Exceptione){ e.printStackTrace(); } if(null!=mHashMap){ intserviceCode=Integer.valueOf(mHashMap.get("version"));//String.valueOf("serviceCode"+"---"+serviceCode) //Toast.makeText(UpdateManager.this,'',Toast.LENGTH_SHORT).show(); Log.i("-----serviceCode",""+serviceCode); Log.i("-----versionCode",""+versionCode); //版本判断 if(serviceCode>versionCode){ returntrue; } }else{ Log.i("-----null==mHashMap","null==mHashMap"); } returnfalse; } /** *获取软件版本号 * *@paramcontext *@return */ privateintgetVersionCode(Contextcontext){ intversionCode=0; try{ //获取软件版本号,对应AndroidManifest.xml下android:versionCode versionCode=context.getPackageManager().getPackageInfo( "com.gaoxiaotongctone",0).versionCode; }catch(NameNotFoundExceptione){ e.printStackTrace(); } returnversionCode; } /** *显示软件更新对话框 */ privatevoidshowNoticeDialog(){ //构造对话框 AlertDialog.Builderbuilder=newBuilder(mContext); builder.setTitle(R.string.soft_update_title); builder.setMessage(R.string.soft_update_info); //更新 builder.setPositiveButton(R.string.soft_update_updatebtn, newOnClickListener(){ @Override publicvoidonClick(DialogInterfacedialog,intwhich){ dialog.dismiss(); //显示下载对话框 showDownloadDialog(); } }); //稍后更新 builder.setNegativeButton(R.string.soft_update_later, newOnClickListener(){ @Override publicvoidonClick(DialogInterfacedialog,intwhich){ dialog.dismiss(); } }); DialognoticeDialog=builder.create(); noticeDialog.show(); } /** *显示软件下载对话框 */ privatevoidshowDownloadDialog(){ //构造软件下载对话框 AlertDialog.Builderbuilder=newBuilder(mContext); builder.setTitle(R.string.soft_updating); //给下载对话框增加进度条 finalLayoutInflaterinflater=LayoutInflater.from(mContext); Viewv=inflater.inflate(R.layout.sotfupdate_progress,null); mProgress=(ProgressBar)v.findViewById(R.id.update_progress); builder.setView(v); //取消更新 builder.setNegativeButton(R.string.soft_update_cancel, newOnClickListener(){ @Override publicvoidonClick(DialogInterfacedialog,intwhich){ dialog.dismiss(); //设置取消状态 cancelUpdate=true; } }); mDownloadDialog=builder.create(); mDownloadDialog.show(); //现在文件 downloadApk(); } /** *下载apk文件 */ privatevoiddownloadApk(){ //启动新线程下载软件 newdownloadApkThread().start(); } /** *下载文件线程 */ privateclassdownloadApkThreadextendsThread{ @Override publicvoidrun(){ try{ //判断SD卡是否存在,并且是否具有读写权限 if(Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED)){ //获得存储卡的路径 Stringsdpath=Environment.getExternalStorageDirectory() +"/"; mSavePath=sdpath+"download"; URLurl=newURL(mHashMap.get("url")); //创建连接 HttpURLConnectionconn=(HttpURLConnection)url .openConnection(); conn.connect(); //获取文件大小 intlength=conn.getContentLength(); //创建输入流 InputStreamis=conn.getInputStream(); Filefile=newFile(mSavePath); //判断文件目录是否存在 if(!file.exists()){ file.mkdir(); } FileapkFile=newFile(mSavePath,mHashMap.get("name")); FileOutputStreamfos=newFileOutputStream(apkFile); intcount=0; //缓存 bytebuf[]=newbyte[1024]; //写入到文件中 do{ intnumread=is.read(buf); count+=numread; //计算进度条位置 progress=(int)(((float)count/length)*100); //更新进度 mHandler.sendEmptyMessage(DOWNLOAD); if(numread<=0){ //下载完成 mHandler.sendEmptyMessage(DOWNLOAD_FINISH); break; } //写入文件 fos.write(buf,0,numread); }while(!cancelUpdate);//点击取消就停止下载. fos.close(); is.close(); } }catch(MalformedURLExceptione){ e.printStackTrace(); }catch(IOExceptione){ e.printStackTrace(); } //取消下载对话框显示 mDownloadDialog.dismiss(); } }; /** *安装APK文件 */ private void installApk(){ Fileapkfile= new File(mSavePath,mHashMap.get( "name" )); if (!apkfile.exists()){ return ; } //通过Intent安装APK文件 Intenti= new Intent(Intent.ACTION_VIEW); i.setDataAndType(Uri.parse( "file://" +apkfile.toString()), "application/vnd.android.package-archive" ); mContext.startActivity(i); } } 附效果图: 好好学习,好好活着。 附件:http://down.51cto.com/data/2364560 本文转自 吴雨声 51CTO博客,原文链接:http://blog.51cto.com/liangxiao/1429384,如需转载请自行联系原作者