这段时间做版本升级,做的过程中碰到问题太多了,呵呵,小马写在博客里面,供自己日后复习,也供大家共同学习改进我的代码,有好的建议请直接指点小马,感激不尽,下面直接来看代码吧:
先看下主配置文件:
- <?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);
- }
- }
贴下Service启动方式的截图:
下面来看下后台服务下载的代码:
- 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;
- }
- }
大体的就是以上讲的这样啦,如果有朋友有好的建议想法,可直接指点小马,小马虚心请教,感谢大家同小马交流,共同提高进步,谢谢啦,附近有带源码,有需要的朋友可直接下载,最好下载前指下小马代码的不足,有批评才有进步,谢谢
附件:http://down.51cto.com/data/2359700
本文转自华华世界 51CTO博客,原文链接:http://blog.51cto.com/mzh3344258/766686,如需转载请自行联系原作者