先看下主配置文件:
<?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;
}
}