运用广播机制来完成版本更新模块(详解)
先看下主配置文件:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.xiaoma.www" android:versionCode="20111111" android:versionName="1.0" > <uses-sdk android:minSdkVersion="15" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <activity android:name=".BroadCastUpdateVersionActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <!-- 下载服务注册 --> <service android:name=".DownloadService"></service> <!-- XML配置方式实现广播注册 --> <!-- <receiver android:enabled=["true" | "false"] android:exported=["true" | "false"] android:icon="drawable resource" android:label="string resource" android:name="string" android:permission="string" android:process="string" > . . .这些是receiver里面的属性,爽吧?嘿嘿,不懂的朋友们可跟下链接 : http://developer.android.com/guide/topics/manifest/receiver-element.html </receiver> --> <!-- <receiver android:name="此处是你写的单独的广播子类,必须是完整路径" > <intent-filter> <action android:name="com.xiaoma.comeon"/> </intent-filter> </receiver> --> </application> </manifest>
再看下主控制类:
package com.xiaoma.www; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.content.BroadcastReceiver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager.NameNotFoundException; import android.net.Uri; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Toast; /** * @Title: BroadCastUpdateVersionActivity.java * @Package com.xiaoma.www * @Description: 运用广播机制来完成版本更新模块 * @author MZH */ public class BroadCastUpdateVersionActivity extends Activity { private Button checkBtn; private BroadcastUpdateReceiver bur = null ; private static final String BROADCAST_ACTION = "com.xiaoma.comeon"; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); /** * 此处:注册广播的方式两种,小马顺带讲下 * 方式一:XML方式在Manifest配置中注册 请看全局配置文件注册receiver * 方式二:纯代码注册如下,此处需要特别注意的是,如果使用代码注册广播的话,注册必须在发起 * 广播之前 ,否则广播无效或报错,还有就是尽量用内部类实现广播时采用这种注册方式 */ //注册是否有新版本广播 registerBroadCast(); init(); } /** * 是否有新版本广播注册实现 */ private void registerBroadCast(){ //注册之前先得有个BroadCastReceiver的子类 bur = new BroadcastUpdateReceiver(); IntentFilter filter = new IntentFilter(); //下面的BROADCAST_ACTION与全局配置中的receiver标签子标签 //intentfilter的action的name值是一致的哦 filter.addAction(BROADCAST_ACTION); registerReceiver(bur, filter); } /** * 内部类实现广播 * @Title: BroadCastUpdateVersionActivity.java * @Package com.xiaoma.www * @Description: 接收是否下载完成广播事件 * @author MZH */ public class BroadcastUpdateReceiver extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { Bundle bundle = intent.getExtras(); String status = bundle.getString("服务器返回给你的标志位"); if (status.equals("如:success")){ String urlStr = "file:///"+ bundle.getString("Path"); //以下这个Intent是指当下载完成后,用新的安装VIEW来提示用户是否安装刚下载好的APK Intent i = new Intent(Intent.ACTION_VIEW); //解析设置服务器返回数据类型 intent.setDataAndType(Uri.parse(urlStr), "application/vnd.android.package-archive"); startActivity(intent); }else{ Toast.makeText(BroadCastUpdateVersionActivity.this, "下载更新版本失败", Toast.LENGTH_SHORT).show(); } BroadCastUpdateVersionActivity.this.finish(); } } /** * 初始化信息实现 */ private void init(){ checkBtn = (Button)findViewById(R.id.checkVersion); checkBtn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { /** * 这里小马讲下在AndroidManifest.xml文件中版本号的一些限制,小马注释写详细些 * 希望大家不要嫌啰嗦,我只希望帮忙大家更多,了解得更透彻 * 首先:http://developer.android.com/guide/topics/manifest/manifest-element.html * 可双上面的链接中看到如下信息: * <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="string" android:sharedUserId="string" android:sharedUserLabel="string resource" android:versionCode="integer" android:versionName="string" 顺便了解下下面这句啦,哈哈,激动,是设置我们的应用默认安装的位置:自动、手机内存、SD卡 android:installLocation=["auto" | "internalOnly" | "preferExternal"] > . . . </manifest> * 跟进版本versionCode与versionNames可查看限制: * 再次强调一下,看到英文不要怕,不懂了用工具查,提高编程提高英文水平 * versionCode中此句最重要: * The value must be set as an integer, such as "100" * versionName也只看一句: * The version number shown to users. * */ try { //取得当前应用的包 String packageName = getPackageName(); //根据包名取得当前应用的版本号 int myVersion = getPackageManager().getPackageInfo(packageName, 0).versionCode; /** * 取服务器上的新版本文件版本号与当前应用的版本比较,如果当前版本低于服务器时弹出更新提示如下, * 访问服务器这步小马跳过,因为今天这个试例讲解广播实现版本更新嘛,通常使用webservice访问服务器 * 朋友们可以把访问服务器的代码直接写到这个地方进行版本比对哦 */ showAlertDialog(); } catch (NameNotFoundException e) { e.printStackTrace(); } } }); } //版本更新弹出对话框 private void showAlertDialog(){ Dialog dialog = new AlertDialog.Builder(this) .setTitle("新版本提示") .setMessage("发现新版本,是否需要升!") .setPositiveButton("确定",new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog,int whichButton) { //下载服务控制 downloadService(); }}).setNegativeButton("取消", new DialogInterface.OnClickListener(){ public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }).create(); dialog.show(); } private void downloadService(){ String PathName = "从服务器取到的完整的路径如:http://www.google.cn/webhp?source=g_cn/XXX.apk"; Intent intent = new Intent(); intent.putExtra("URL", "访问服务器的URL"); intent.putExtra("Path", PathName); //记得在全局配置中注册DownloadService服务 intent.setClass(this, DownloadService.class); /** * 因为是这种方式启动的service,小马就在此插张图,供朋友们理解在DownloadService.class里面 * 小马为什么把处理过程写在onStart()中而不是onBind()中。 */ startService(intent); } }
下面来看下后台服务下载的代码:
package com.xiaoma.www; import java.io.File; import java.io.InputStream; import com.xiaoma.utils.FileUtils; import android.app.Service; import android.content.Intent; import android.os.Bundle; import android.os.IBinder; /** * @Title: DownloadService.java * @Package com.xiaoma.www * @Description: 启用后台下载新版本控制类 * @author MZH */ public class DownloadService extends Service { @Override public IBinder onBind(Intent intent) { return null; } @Override public void onStart(Intent intent, int startId) { if(intent != null){ String urlStr = intent.getStringExtra("URL"); String fullPathName = intent.getStringExtra("Path"); DownloadThread downloadThread = new DownloadThread(urlStr, fullPathName); Thread thread = new Thread(downloadThread); thread.start(); } super.onStart(intent, startId); } class DownloadThread implements Runnable{ private String mUrl = null; private String mPathName = null; public DownloadThread(String aUrl, String PathName){ mUrl = aUrl; mPathName = PathName; } @Override public void run() { int result = downFile(mUrl, mPathName); Intent intent = new Intent("com.xiaoma.comeon"); Bundle bundle = new Bundle(); if( -1 == result){ bundle.putString("Status", "error"); }else { bundle.putString("Status", "success"); bundle.putString("Path", mPathName); } intent.putExtras(bundle); sendBroadcast(intent); } } public int downFile(String urlStr, String fullPathName){ InputStream inputStream = null; try{ File file = new File(fullPathName); if (file.exists()){ return 1; }else{ FileUtils fu = new FileUtils(); inputStream = fu.getStreamFromUrl(urlStr); File f = fu.writeInput(fullPathName, inputStream); if (f == null){ return -1; } } }catch(Exception e){ e.printStackTrace(); return -1; }finally{ try{ inputStream.close(); } catch (Exception e) { e.printStackTrace(); } } return 0; } }
以下是后台下载时用到的文件工具类代码:
package com.xiaoma.utils; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; /** * @Title: DeleteFile.java * @Description: 文件、文件夹操作类 * @author MZH */ public class FileUtils{ private URL url = null ; public FileUtils(){ } public File writeInput(String PathName, InputStream input){ File file = null; OutputStream output = null; try{ file = new File( PathName ); if (file.exists()) return file; int length = 0; output = new FileOutputStream(file); byte buffer[] = new byte[1024]; while((length = input.read(buffer)) > 0){ output.write(buffer, 0, length); } }catch(Exception e){ e.printStackTrace(); }finally{ try{ output.close(); }catch(Exception e){ e.printStackTrace(); } } return file; } public InputStream getStreamFromUrl(String urlStr) throws MalformedURLException, IOException { url = new URL(urlStr); HttpURLConnection urlConn = (HttpURLConnection) url.openConnection(); InputStream inputStream = urlConn.getInputStream(); return inputStream; } }
相关推荐
huha 2020-10-16
xfcyhades 2020-11-20
sgafdsg 2020-11-04
Michael 2020-11-03
fengyeezju 2020-10-14
ziyexiaoxiao 2020-10-14
业余架构师 2020-10-09
OuNuo0 2020-09-29
moses 2020-09-22
Angelia 2020-09-11
qinxu 2020-09-10
刘炳昭 2020-09-10
Nostalgiachild 2020-09-07
Nostalgiachild 2020-08-17
leavesC 2020-08-14
一青年 2020-08-13
AndroidAiStudy 2020-08-07
ydc0 2020-07-30
绿豆饼 2020-07-28