`

运用广播机制来完成版本更新模块(详解)

阅读更多
先看下主配置文件:
<?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; 
    } 
} 
分享到:
评论

相关推荐

    第四课:Dubbo调用模块详解 (2)1

    《Dubbo调用模块详解:深入理解异步调用与容错策略》 在分布式服务框架Dubbo中,调用模块扮演着至关重要的角色,它负责实现远程方法调用并确保返回结果的顺利获取。本篇文章将深入探讨Dubbo调用模块的基本组成,...

    Android典型技术模块开发详解

    7.10 AutoCompleteTextview(自动完成) 7.11 DataPicker&TimePicker;(日期&时间) 7.12 ProgressBar (进度条) 7.12.1 横向进度条 7.12.2 旋转型进度条 7.13 SeekBar (拖动条) 7.14 RatingBar(评分条) 7.15 本章...

    Android应用开发详解(包括源码)

    了解并运用ListView、RecyclerView等可滚动视图,以及异步任务(AsyncTask)、线程池(Executor)来优化后台操作,可以使应用运行更加流畅。同时,通过使用Data Binding库和LiveData,可以实现数据的自动更新,提高...

    Android+Intent机制实例详解.rar

    总结,Intent机制是Android框架的核心部分,理解和熟练运用Intent对于开发高效、灵活的应用至关重要。无论是启动Activity、Service,还是进行组件间的通信,Intent都是不可或缺的桥梁。通过实例学习和实践,开发者...

    spring内核详解

    《Spring内核详解》 Spring框架作为Java领域最流行的轻量级应用框架,其核心机制是许多开发者关注的焦点。本文将深入剖析Spring内核,揭示其设计思想和实现原理,帮助开发者更好地理解和运用这一强大的工具。 一、...

    android各组件详解 PDF

    在Android开发中,各个组件是构建应用程序的基础模块,它们构成了Android应用的核心结构。这份"android各组件详解 PDF"文档详细阐述了这些组件的功能、用法以及如何协同工作,为开发者提供了深入理解Android应用架构...

    Android Studio—自定义广播.zip

    **Android Studio 自定义广播...理解广播机制并熟练运用,可以极大地提升 Android 应用的交互性和灵活性。在实际开发中,结合标签所提到的移动开发知识,广播接收器常被用于实现诸如网络状态检测、后台服务通知等功能。

    nodejs基于WS模块实现WebSocket聊天功能的方法.docx

    这段代码定义了一个 WebSocket 服务器,监听在 3000 端口上,并提供了一个简单的广播机制来处理客户端发送的消息以及客户端关闭连接的情况。 #### 五、前端页面设计 接下来,创建 HTML 文件 `index.html`,并在...

    Android核心技术与实例详解

    7. **BroadcastReceiver(广播接收器)**:广播是全局的通知机制,允许应用在系统事件发生时做出响应,如网络状态变化、电池电量低等。 8. **ContentProvider**:提供数据共享机制,使得不同应用间可以访问和操作...

    linux下用户程序同内核通信详解(netlink机制)

    3. **模块化支持**:内核中的Netlink部分可以作为模块实现,用户态程序和内核部分无编译时依赖,这使得内核更新更加灵活。 4. **多播支持**:Netlink支持多播,消息可以广播给一个Netlink组内的多个接收者,非常适合...

    angularjs1.2.2

    **AngularJS 1.2.2 知识点详解** AngularJS 是一款强大的前端JavaScript框架,由Google维护,主要用于构建单页应用(Single Page Applications, SPA)。在AngularJS 1.2.2版本中,它引入了多个改进和优化,为开发者...

    Android案例详解

    10. **热修复与插件化**:对于大型应用,热修复技术如Tinker允许在不更新应用的情况下修复线上问题,而插件化技术则实现了应用模块化的开发和部署,如微信的OpenKit等。 以上这些知识点都是“Android案例详解”中...

    numpy-1.6.0.zip

    本篇文章将深入探讨Numpy 1.6.0版本的核心特性,帮助你更好地理解和运用这个重要的科学计算工具。 Numpy,全称为Numeric Python,是Python编程语言的一个扩展包,它主要致力于高效地处理多维数据结构——数组...

    Android核心技术和开发详解-源码完整版

    18. **Android最新特性**:随着Android版本的更新,会引入许多新特性和API,如Android 12中的隐私保护改进、Material Design 3等,及时跟进学习能保持开发技能的前沿性。 通过深入学习和实践这些知识点,开发者可以...

    基于JAVA的ICQ系统.rar

    《基于JAVA的ICQ系统详解》 在信息技术领域,JAVA作为一种强大的编程语言,因其跨平台性和丰富的类库,被广泛应用于各种系统开发中。本文将深入探讨一个基于JAVA实现的ICQ(I Seek You)系统,这是一个即时通讯软件...

    Android ApiDemos不报错版本,eclipse可用

    **Android ApiDemos详解** ApiDemos是Android官方提供的一款示例应用,它包含了Android SDK中的各种API功能演示,帮助开发者了解和学习Android系统提供的各种API接口和功能。这个"Android ApiDemos不报错版本"是...

    LWIP编程详解以及编程实例

    - **数据传输**:LWIP使用tcp_write()和tcp_recv()函数进行数据发送和接收,并支持滑动窗口机制来实现流量控制和拥塞控制。 3. **UDP协议** - **无连接特性**:UDP是无连接的,无需建立连接即可发送数据,适合...

    java观感包

    - 模块通信:不同模块之间通过观察者模式进行通信,例如,数据加载模块完成数据获取后,通知视图模块进行渲染。 - 异步处理:一个任务完成后,通知其他任务继续执行或更新状态。 5. **优缺点** - 优点:实现了...

    Laravel开发-business

    5. 客户服务与评论系统:利用Laravel的事件监听器和广播机制,可以实现实时的消息通知,如订单状态更新、客户咨询等。同时,构建评论系统,促进用户互动。 6. 数据分析与报表:Laravel提供Artisan命令行工具,可以...

    mmo_game_zinxV4.0

    同时,广播机制保证了所有相关玩家都能接收到这些更新。 "mmo_game_zinx"可能是项目使用的服务器框架或核心库,而"zinx"可能是一个专门为游戏设计的轻量级网络通信库。这类库通常提供高效的网络层支持,如异步非...

Global site tag (gtag.js) - Google Analytics