Android详细教程(基础篇):二十六、Android组件通信,Intent详解、消息机制(Message、Handler、Looper)详解、 PendingIntent详解

Android组件通信

9.1. Intent

Intent 是一个将要执行的动作的抽象的描述,一般来说是作为参数来使用,由Intent来协助完成android各个组件之间的通讯。比如说调用startActivity()来启动一个activity,或者由broadcaseIntent()来传递给所有感兴趣的BroadcaseReceiver, 再或者由startService()/bindservice()来启动一个后台的service.所以可以看出来,intent主要是用来启动其他的activity 或者service,所以可以将intent理解成activity之间的粘合剂。

9.1.1. Intent的构造函数

public class Intent extends Object implements Parcelable Cloneable

java.lang.Object

   

android.content.Intent

 

Constructors:

Intent()

Create an empty intent.

Intent(Intent o)

Copy constructor.

Intent(String action)

Create an intent with a given action.

Intent(String action, Uri uri)

Create an intent with a given action and for a given data url.

Intent(Context packageContext, Class<?> cls)

Create an intent for a specific component.

Intent(String action, Uri uri, Context packageContext, Class<?> cls)

Create an intent for a specific component with a specified action and data.

公共构造函数:

1、Intent() 空构造函数

2、Intent(Intent o) 拷贝构造函数

3、Intent(String action) 指定action类型的构造函数

4、Intent(String action, Uri uri) 指定Action类型和Uri的构造函数,URI主要是结合程序之间的数据共享ContentProvider

5、Intent(Context packageContext, Class<?> cls) 传入组件的构造函数,也就是上文提到的

6、Intent(String action, Uri uri, Context packageContext, Class<?> cls) 前两种结合体

Intent有六种构造函数,3、4、5是最常用的,并不是其他没用!

Intent(String action, Uri uri) 的action就是对应在AndroidMainfest.xml中的action节点的name属性值。在Intent类中定义了很多的Action和Category常量。

示例:

Intent intent = new Intent(Intent.ACTION_EDIT, null);

startActivity(intent);

代码是用了第四种构造函数,只是uri参数为null。执行此代码的时候,系统就会在程序主配置文件AndroidMainfest.xml中寻找

<action android:name="android.intent.action.EDIT" />对应的Activity,如果对应有多个activity具有<action android:name="android.intent.action.EDIT" />此时就会弹出一个dailog选择Activity。

9.1.2. Activity对Intent的支持

Activity程序支持的Intent操作方法。

Android详细教程(基础篇):二十六、Android组件通信,Intent详解、消息机制(Message、Handler、Looper)详解、 PendingIntent详解

Android详细教程(基础篇):二十六、Android组件通信,Intent详解、消息机制(Message、Handler、Looper)详解、 PendingIntent详解

9.1.3. Intent的构成

Android详细教程(基础篇):二十六、Android组件通信,Intent详解、消息机制(Message、Handler、Looper)详解、 PendingIntent详解

9.1.3.1. Action-动作

       用来指明要实施的动作是什么,比如说ACTION_VIEW, ACTION_EDIT等。具体的可以查阅android SDK-> reference中的Android.content.intent类,里面的constants中定义了所有的action。

Android详细教程(基础篇):二十六、Android组件通信,Intent详解、消息机制(Message、Handler、Looper)详解、 PendingIntent详解

相当于通过Activity制定要操作的类型

9.1.3.2. Data-数据

      Data 要传递的具体数据,一般由一个Uri变量来表示,下面是一些简单的例子:

ACTION_VIEW content://contacts/1 //显示identifier为1的联系人的信息。

ACTION_DIAL content://contacts/1 //给这个联系人打电话

Android详细教程(基础篇):二十六、Android组件通信,Intent详解、消息机制(Message、Handler、Looper)详解、 PendingIntent详解

9.1.3.3. Type-数据类型

       显式指定Intent的数据类型(MIME)。一般Intent的数据类型能够根据数据本身进行判定,但是通过设置这个属性,可以强制采用显式指定的类型而不再进行推导。

Android详细教程(基础篇):二十六、Android组件通信,Intent详解、消息机制(Message、Handler、Looper)详解、 PendingIntent详解

9.1.3.4. Category-类别

       这个选项指定了将要执行的这个action的其他一些额外的信息,例如 LAUNCHER_CATEGORY 表示Intent 的接受者应该在Launcher中作为顶级应用出现;而ALTERNATIVE_CATEGORY表示当前的Intent是一系列的可选动作中的一个,这些动作可以在同一块数据上执行。具体同样可以参考android SDK-> reference中的Android.content.intent类。以前我也写过一篇于category有关的文章,点击这里可以查看。

Android详细教程(基础篇):二十六、Android组件通信,Intent详解、消息机制(Message、Handler、Looper)详解、 PendingIntent详解

9.1.3.5. component-组件

       指定Intent的的目标组件的 类名称。通常 Android会根据Intent 中包含的其它属性的信息,比如action、data/type、category进行查找,最终找到一个与之匹配的目标组件。但是,如果 component这个属性有指定的话,将直接使用它指定的组件,而不再执行上述查找过程。指定了这个属性以后,Intent的其它所有属性都是可选的。

9.1.3.6. extras-附加信息

       是其它所有附加信息的集合。使用extras可以为组件提供扩展信息,比如,如果要执行“发送电子邮件”这个动作,可以将电子邮件的标题、正文等保存在extras里,传给电子邮件发送组件。

Android详细教程(基础篇):二十六、Android组件通信,Intent详解、消息机制(Message、Handler、Looper)详解、 PendingIntent详解

 

9.1.4. Android中页面跳转以及传值的几种方式!

1、页面跳转及传值:

Activity跳转与传值,主要是通过Intent类来连接多个Activity,通过Builder类来传递数据。

最常见最一般的页面跳转代码,很简单,如下:

Intent intent = new Intent(A.this, B.class); 

startActivity(intent); 

 

也可以这样写:

Intent intent = new Intent(); 

intent.setClass(A.this, B.class); 

startActivity(intent); 

 

只要这两句,就可以实现从A页面跳转到B页面了。  (A、B均继承自Activity)

有的时候,在跳转页面时还需要传递数据,这个时候如何做呢?

如果数据比较少,比如只要传一个名字,那么只要加一句"intent.putExtra("Name", "feng88724");"即可,代码如下:

Intent intent = new Intent(); 

intent.setClass(A.this, B.class); 

intent.putExtra("Name", "feng88724"); 

startActivity(intent); 

 

如果数据比较多,就需要使用 Bunder类了,代码如下: (说明直接看注释)

Intent intent = new Intent(A.this, B.class); 

/* 通过Builder对象存储需要传递的数据 */ 

Builder builder = new Builder (); 

/*字符、字符串、布尔、字节数组、浮点数等等,都可以传*/ 

builder.putString("Name", "feng88724"); 

builder.putBoolean("Ismale", true); 

/*builder对象加给Intent*/ 

intent.putExtras(builder); 

startActivity(intent); 

 

以上我们讲的都是如何进行页面跳转及数据传递,那么在另一个页面B上,应该如何接收数据呢?

9.1.5. 接受Intent传来的值:

在A页面上是以Builder封装了对象,自然在B页面也是以Builder的方式来解开封装的数据。主要通过

"getIntent().getExtras()"方法来获取Builder对象,然后再从Builder中获取数据。 也可以通过

" this.getIntent().getStringExtra("Name");"方法直接从Intent中获取数据。

从Builder获取数据的代码

@Override 

 public void onCreate(Bundle savedInstanceState) { 

        super.onCreate(savedInstanceState); 

        /*加载页面*/ 

     setContentView(R.layout.main); 

        /*获取Intent中的Builder对象*/ 

        Builder builder = this.getIntent().getExtras(); 

        /*获取Builder中的数据,注意类型和key*/ 

        String name = bunder.getString("Name"); 

        boolean ismale = builder.getBoolean("Ismale"); 

9.1.6. 通过Intent跳转到另一页面之后,再返回到之前的页面: 

有时,在页面跳转之后,需要返回到之前的页面,同时要保留用户之前输入的信息,这个时候该怎么办呢?

在页面跳转后,前一个Activity已经被destroy了。如果要返回并显示数据,就必须将前一个Activity再次唤醒,

同时调用某个方法来获取并显示数据。

要实现这个效果,需要做以下几步:

1. 首先,从A页面跳转到B页面时,不可以使用"startActivity()"方法,而要使用"startActivityForResult"方法。

2. 在A页面的Activity中,需要重写"onActivityResult"方法

 /*这里的requestCode用来标识某一个调用,一般由我们定义一个常量。

resultCode是返回代码,同样用来标识一个返回类型,而data则是它要返回的参数。*/

@Override 

protected void onActivityResult(int resultCode,Intent data){ 

    switch(requestCode){ 

    case RESULT_OK: 

        /*取得来自B页面的数据,并显示到画面*/ 

       Builder builder = data.getExtras(); 

         

        /*获取Builder中的数据,注意类型和key*/ 

        String name = bunder.getString("Name"); 

        boolean ismale = bunder.getBoolean("Ismale"); 

    } 

 

  1. 在B页面上加一个返回按钮,并在事件写如下代码:

 /*给上一个Activity返回结果*/ 

B.this.setResult(RESULT_OK,intent); 

/*结束本Activity*/ 

B.this.finish(); 

 

 

9.1.7. Intent的解析

 应用程序的组件为了告诉Android自己能响应、处理哪些隐式Intent请求,可以声明一个甚至多个Intent Filter。每个Intent Filter描述该组件所能响应Intent请求的能力——组件希望接收什么类型的请求行为,什么类型的请求数据。比如之前请求网页浏览器这个例子中,网页浏览器程序的Intent Filter就应该声明它所希望接收的Intent Action是WEB_SEARCH_ACTION,以及与之相关的请求数据是网页地址URI格式。如何为组件声明自己的Intent Filter? 常见的方法是在AndroidManifest.xml文件中用属性< Intent-Filter>描述组件的Intent Filter。

  前面我们提到,隐式Intent(Explicit Intents)和Intent Filter(Implicit Intents)进行比较时的三要素是Intent的动作、数据以及类别。实际上,一个隐式Intent请求要能够传递给目标组件,必要通过这三个方面的检查。如果任何一方面不匹配,Android都不会将该隐式Intent传递给目标组件。接下来我们讲解这三方面检查的具体规则。

9.1.7.1. 动作匹配-action

 <intent-filter>元素中可以包括子元素< action>,比如:

<intent-filter>

       <action android:name=”com.example.project.SHOW_CURRENT” />

       <action android:name=”com.example.project.SHOW_RECENT” />

       <action android:name=”com.example.project.SHOW_PENDING” />

</intent-filter>

    一条< intent-filter>元素至少应该包含一个<action>,否则任何Intent请求都不能和该<intent-filter>匹配。如果Intent请求的Action和< intent-filter>中某一条<action>匹配,那么该Intent就通过了这条<intent-filter>的动作匹配。如果Intent请求或<intent-filter>中没有说明具体的Action类型,那么会出现下面两种情况。

(1) 如果<intent-filter>中没有包含任何Action类型,那么无论什么Intent请求都无法和这条<intent- filter>匹配;

(2) 反之,如果Intent请求中没有设定Action类型,那么只要< intent-filter>中包含有Action类型,这个 Intent请求就将顺利地通过< intent-filter>的行为测试。

9.1.7.2. 类别匹配

  <intent-filter>元素可以包含< category>子元素,比如:

<intent-filter>

      ....

      <category android:name=”android.Intent.Category.DEFAULT” />

      <category android:name=”android.Intent.Category.BROWSABLE” />

</intent-filter>

 

   

  只有当Intent请求中所有的Category与组件中某一个IntentFilter的<category>完全匹配时,才会让该 Intent请求通过匹配,IntentFilter中多余的<category>声明并不会导致匹配失败。一个没有指定任何类别的 IntentFilter仅仅只会匹配没有设置类别的Intent请求。

9.1.7.3. 数据匹配

    数据在< intent-filter>中的描述如下:

<intent-filter>

     ...

     <data android:type=”video/mpeg” android:scheme=”http” . . . />

     <data android:type=”audio/mpeg” android:scheme=”http” . . . />

</intent-filter>

  元素指定了希望接受的Intent请求的数据URI和数据类型,URI被分成三部分来进行匹配:scheme、 authority和path。其中,用setData()设定的Inteat请求的URI数据类型和scheme必须与IntentFilter中所指定的一致。若IntentFilter中还指定了authority或path,它们也需要相匹配才会通过测试。

9.1.7.4. 简单例子说明

  讲解完Intent基本概念之后,接下来我们就使用Intent**Android自带的电话拨号程序,通过这个实例你会发现,使用Intent并不像其概念描述得那样难。最终创建Intent的代码如下所示。

Intent i = new Intent(Intent.ACTION_DIAL,Uri.parse(”tel://13800138000″));

创建好Intent之后,你就可以通过它告诉Android希望启动新的Activity了。startActivity(i);

9.1.8. 实例:

    1、调用web浏览器

Java代码

Uri myBlogUri = Uri.parse("http://kuikui.javaeye.com");

  returnIt = new Intent(Intent.ACTION_VIEW, myBlogUri);

 

  2、地图

Java代码

Uri mapUri = Uri.parse("geo:38.899533,-77.036476");

returnIt = new Intent(Intent.ACTION_VIEW, mapUri);

 

  3、调拨打电话界面

Java代码

Uri telUri = Uri.parse("tel:100861");

returnIt = new Intent(Intent.ACTION_DIAL, telUri)

  4、直接拨打电话

Java代码

Uri callUri = Uri.parse("tel:100861");

returnIt = new Intent(Intent.ACTION_CALL, callUri);

  5、卸载

Java代码

Uri uninstallUri = Uri.fromParts("package", "xxx", null);

returnIt = new Intent(Intent.ACTION_DELETE, uninstallUri);

   6、安装

Java代码

Uri installUri = Uri.fromParts("package", "xxx", null);

returnIt = new Intent(Intent.ACTION_PACKAGE_ADDED, installUri);

  7、播放

Java代码

Uri playUri = Uri.parse("file:///sdcard/download/everything.mp3");

returnIt = new Intent(Intent.ACTION_VIEW, playUri);

  8、调用发邮件

Java代码

Uri emailUri = Uri.parse("mailto:[email protected]");

returnIt = new Intent(Intent.ACTION_SENDTO, emailUri);

 

  9、发邮件

Java代码

returnIt = new Intent(Intent.ACTION_SEND);

  String[] tos = { "[email protected]" };

  String[] ccs = { "[email protected]" };

  returnIt.putExtra(Intent.EXTRA_EMAIL, tos);

  returnIt.putExtra(Intent.EXTRA_CC, ccs);

  returnIt.putExtra(Intent.EXTRA_TEXT, "body");

  returnIt.putExtra(Intent.EXTRA_SUBJECT, "subject");

  returnIt.setType("message/rfc882");

  Intent.createChooser(returnIt, "Choose Email Client");

 

  10、发短信

Java代码

Uri smsUri = Uri.parse("tel:100861");

  returnIt = new Intent(Intent.ACTION_VIEW, smsUri);

  returnIt.putExtra("sms_body", "shenrenkui");

  returnIt.setType("vnd.android-dir/mms-sms");

 

  11、直接发邮件

Java代码

Uri smsToUri = Uri.parse("smsto://100861");

  returnIt = new Intent(Intent.ACTION_SENDTO, smsToUri);

  returnIt.putExtra("sms_body", "shenrenkui");

 

  12、发彩信

Java代码

Uri mmsUri = Uri.parse("content://media/external/images/media/23");

  returnIt = new Intent(Intent.ACTION_SEND);

  returnIt.putExtra("sms_body", "shenrenkui");

  returnIt.putExtra(Intent.EXTRA_STREAM, mmsUri);

  returnIt.setType("image/png");

 

  用获取到的Intent直接调用startActivity(returnIt)就ok了。

范例一:打开网页

package com.makyan.demo;

import android.app.Activity;

import android.content.Intent;

import android.net.Uri;

import android.os.Bundle;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

public class IntentActionActivity extends Activity {

     private Button button = null;

     @Override

     protected void onCreate(Bundle savedInstanceState) {

          super.onCreate(savedInstanceState);

          setContentView(R.layout.activity_intent_action);

          button = (Button) super.findViewById(R.id.button);

          button.setOnClickListener(new OnClickListener() {

              

               @Override

               public void onClick(View v) {

                    Uri uri = Uri.parse("www://baidu.com");

                    Intent it = new Intent();

                    it.setAction(Intent.ACTION_VIEW);

                    it.setData(uri);

                    startActivity(it);

               }

          });

     }

}

 

 

范例二:发送彩信

Android详细教程(基础篇):二十六、Android组件通信,Intent详解、消息机制(Message、Handler、Looper)详解、 PendingIntent详解

 

范例四:发送邮件

 

9.2. ActionGroup

9.3. 消息机制(Message、Handler、Looper)

Android详细教程(基础篇):二十六、Android组件通信,Intent详解、消息机制(Message、Handler、Looper)详解、 PendingIntent详解

9.3.1. Message、Loope、Handler之间的关系

Android详细教程(基础篇):二十六、Android组件通信,Intent详解、消息机制(Message、Handler、Looper)详解、 PendingIntent详解

主线程一般在Android之中称为UI线程,一个界面显示,那么这个就属于主线程,而子线程指的是那些利用

Runnable实现的线程操作类。每个消息(Message)都可以通过Handler进行增加和取出,而操作Handler的对象

就是主线程。

9.3.2. Message –消息的封装

Android详细教程(基础篇):二十六、Android组件通信,Intent详解、消息机制(Message、Handler、Looper)详解、 PendingIntent详解

9.3.3. Handler –操作Message消息

Android详细教程(基础篇):二十六、Android组件通信,Intent详解、消息机制(Message、Handler、Looper)详解、 PendingIntent详解

范例一:

            配置:

           

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:tools="http://schemas.android.com/tools"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:paddingBottom="@dimen/activity_vertical_margin"

    android:paddingLeft="@dimen/activity_horizontal_margin"

    android:paddingRight="@dimen/activity_horizontal_margin"

    android:paddingTop="@dimen/activity_vertical_margin"

    tools:context=".MessageActivity" >

    <TextView

        android:id="@+id/show"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:text="@string/message" />

</LinearLayout>

Activity:

package com.makyan.demo;

 

import java.util.Timer;

import java.util.TimerTask;

import android.app.Activity;

import android.os.Bundle;

import android.os.Handler;

import android.os.Message;

import android.widget.TextView;

public class MessageActivity extends Activity {

            private int count = 0;

            private final static int state = 1;

            private TextView txt;

            @Override

            protected void onCreate(Bundle savedInstanceState) {

                       super.onCreate(savedInstanceState);

                       setContentView(R.layout.activity_message);

                       txt = (TextView) super.findViewById(R.id.show);

                       Timer task = new Timer();

                       task.schedule(new MyTimerTask(), 0, 1000);

            }

           

            Handler handler = new Handler(){

                       @Override

                       public void handleMessage(Message msg) {

                                   switch(msg.what){

                                   case state:

                                               txt.setText("杨雄工作室" + count);

                                               count ++;

                                   }

                       }

            };

           

            private class MyTimerTask extends TimerTask{

                       @Override

                       public void run() {

                                   Message msg = new Message();

                                   msg.what = state;

                                   handler.sendMessage(msg);

                       }

            }

}

 

子线程产生消息,通过Handler发出去,在Activity层,Handler去处理接受到的消息

只要是子线程就无法更新组件,就只能采用在子线程之中返回要操作的消息,而后在主线程之中利用

Handler处理这些消息,从而实现线程的操作。

9.3.4. Looper –存放消息的队列,自动完成对Message对象的存取

Android详细教程(基础篇):二十六、Android组件通信,Intent详解、消息机制(Message、Handler、Looper)详解、 PendingIntent详解

Android详细教程(基础篇):二十六、Android组件通信,Intent详解、消息机制(Message、Handler、Looper)详解、 PendingIntent详解

 

范例二:主线程与子线程之间的消息交互

配置:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:tools="http://schemas.android.com/tools"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:paddingBottom="@dimen/activity_vertical_margin"

    android:paddingLeft="@dimen/activity_horizontal_margin"

    android:paddingRight="@dimen/activity_horizontal_margin"

    android:paddingTop="@dimen/activity_vertical_margin"

    tools:context=".LooperActivity" >

    <TextView

        android:id="@+id/info"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:text="等待子线程发送消息" />

    <Button

        android:id="@+id/but"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:text="启动" />

</LinearLayout>

 

Activity:

package com.makyan.demo;

import android.app.Activity;

import android.os.Bundle;

import android.os.Handler;

import android.os.Looper;

import android.os.Message;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

import android.widget.TextView;

public class LooperActivity extends Activity {

            private final static int STATE = 2;

            private TextView txt;

            private Button but;

            @Override

            protected void onCreate(Bundle savedInstanceState) {

                       super.onCreate(savedInstanceState);

                       setContentView(R.layout.activity_looper);

                       txt = (TextView) super.findViewById(R.id.info);

                       but = (Button) super.findViewById(R.id.but);

                       but.setOnClickListener(new OnClickListenerImpl());

                      

            }

            private class OnClickListenerImpl implements OnClickListener{

                       @Override

                       public void onClick(View v) {

                                   Looper looper = Looper.myLooper();

                                   MyHandler handler = new MyHandler(looper);

                                   String data = "杨雄工作室...";

                                   Message msg = handler.obtainMessage(STATE, 1, 1, data);

                                   handler.sendMessage(msg);

                       }

            }

           

            private class MyHandler extends Handler{

                       public MyHandler(Looper looper){

                                   super(looper);

                       }

                        public void handleMessage(Message msg) {

                                   switch(msg.what){

                                   case STATE:

                                               txt.setText(msg.obj.toString());

                                   };

                       }

            }

}

 

以上程序中,我们完全可以不使用Looper,效果是一样的,所以在消息机制中最主要的是Handler和Message

示例:主线程与子线程之间的消息交互(即主线程发送消息给子线程,子线程发送消息给主线程)

配置:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:tools="http://schemas.android.com/tools"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:paddingBottom="@dimen/activity_vertical_margin"

    android:paddingLeft="@dimen/activity_horizontal_margin"

    android:paddingRight="@dimen/activity_horizontal_margin"

    android:paddingTop="@dimen/activity_vertical_margin"

    tools:context=".ThreadInteractionActivity" >

 

    <TextView

        android:id="@+id/showInfo"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:text="等待......" />

     <Button

        android:id="@+id/but"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:text="交互" />

</LinearLayout>

Activity:

package com.makyan.demo;

import android.app.Activity;

import android.os.Bundle;

import android.os.Handler;

import android.os.Looper;

import android.os.Message;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

import android.widget.TextView;

public class ThreadInteractionActivity extends Activity {

            private final static int MAINWHAT = 1; //主线程WHAT标记

            private final static int CHILDWHAT = 2; //子线程WHAT标记

            private TextView txt ;

            private Button but;

            private Handler mainHandler;

            private Handler childHandler;

            @Override

            protected void onCreate(Bundle savedInstanceState) {

                       super.onCreate(savedInstanceState);

                       setContentView(R.layout.activity_thread_interaction);

                       txt = (TextView) super.findViewById(R.id.showInfo);

                       but = (Button) super.findViewById(R.id.but);

                       new Thread(new ChildThread(),"Child Thread").start();

                       but.setOnClickListener(new OnClickListener() {

                                   @Override

                                   public void onClick(View v) {

                                               Message msg = childHandler.obtainMessage();

                                               msg.obj = "主线程发送消息给子线程";

                                               msg.what = CHILDWHAT;

                                               childHandler.sendMessage(msg);

                                   }

                       });

                      

                       mainHandler = new Handler(){

                                   public void handleMessage(Message msg) {

                                              super.handleMessage(msg);

                                               System.out.println(msg.obj.toString());

                                               switch(msg.what){

                                               case MAINWHAT:

                                                          txt.setText("子线程已经回应");

                                               }

                                   }

                       };

            }

            class ChildThread implements Runnable{

                       @Override

                       public void run() {

                                   Looper.prepare();

                                   childHandler = new Handler(){

                                               @Override

                                               public void handleMessage(Message msg) {

                                                          super.handleMessage(msg);

                                                          switch(msg.what){

                                                          case CHILDWHAT:

                                                                      Message msg2 = mainHandler.obtainMessage();

                                                                      msg.obj = "我已经接受到您的消息";

                                                                      msg2.what = MAINWHAT;

                                                                      mainHandler.sendMessage(msg2);

                                                                      break;

                                                          }

                                               }

                                   };

                       }

            }

           

            @Override

            protected void onDestroy() {

                       childHandler.getLooper().quit();

            }

}

 

范例三:时钟显示

配置:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:tools="http://schemas.android.com/tools"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:orientation="vertical"

    android:paddingBottom="@dimen/activity_vertical_margin"

    android:paddingLeft="@dimen/activity_horizontal_margin"

    android:paddingRight="@dimen/activity_horizontal_margin"

    android:paddingTop="@dimen/activity_vertical_margin"

    tools:context=".AnalogClickActivity" >

            <AnalogClock

                android:id="@+id/analog"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"/>

    <TextView

        android:id="@+id/timeShow"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:text="时钟显示.." />

</LinearLayout>

Activity:

package com.makyan.demo;

import java.text.SimpleDateFormat;

import java.util.Date;

import android.app.Activity;

import android.os.Bundle;

import android.os.Handler;

import android.os.Message;

import android.widget.TextView;

public class AnalogClickActivity extends Activity {

            private final static int state = 1;

            private TextView txt;

            Handler handler = new Handler(){

                       @Override

                       public void handleMessage(Message msg) {

                                   super.handleMessage(msg);

                                   switch(msg.what){

                                   case state:

                                               txt.setText(msg.obj.toString());

                                   }

                       }

            };

            @Override

            protected void onCreate(Bundle savedInstanceState) {

                       super.onCreate(savedInstanceState);

                       setContentView(R.layout.activity_analog_click);

                       txt = (TextView) super.findViewById(R.id.timeShow);

                       new Thread(new Clock()).start();

            }

            class Clock implements Runnable{

                       @Override

                       public void run() {

                                   while(true){

                                               Message msg = handler.obtainMessage(state, 1, 1,"当前时间:" + new SimpleDateFormat("yyyy-mm-dd HH:mm:ss").format(new Date()));

                                               handler.sendMessage(msg);

                                               try {

                                                          Thread.sleep(1000);

                                               } catch (InterruptedException e) {

                                                          e.printStackTrace();

                                               }

                                   }

                       }

            }

}

9.3.5. ProgressBar -使用消息机制对进度条的控制

Android详细教程(基础篇):二十六、Android组件通信,Intent详解、消息机制(Message、Handler、Looper)详解、 PendingIntent详解

Android详细教程(基础篇):二十六、Android组件通信,Intent详解、消息机制(Message、Handler、Looper)详解、 PendingIntent详解

 

Android详细教程(基础篇):二十六、Android组件通信,Intent详解、消息机制(Message、Handler、Looper)详解、 PendingIntent详解

 

9.3.6. 详解Android Handler的使用

 

我们进行Android开发时,Handler可以说是使用非常频繁的一个概念,它的用处不言而喻。本文就详细介绍Handler的基本概念和用法。

 

       Handler的基本概念

 

       Handler主要用于异步消息的处理:当发出一个消息之后,首先进入一个消息队列,发送消息的函数即刻返回,而另外一个部分逐个的在消息队列中将消息取出,然后对消息进行出来,就是发送消息和接收消息不是同步的处理。 这种机制通常用来处理相对耗时比较长的操作。

 

       Handler工具类在多线程中有两方面的应用:

 

  1、发送消息,在不同的线程间发送消息,使用的方法为sendXXX();。

 

  android.os.Handler对象通过下面的方法发送消息的:

  sendEmptyMessage(int),发送一个空的消息;

  sendMessage(Message),发送消息,消息中可以携带参数;

  sendMessageAtTime(Message, long),未来某一时间点发送消息;

  sendMessageDelayed(Message, long),延时Nms发送消息。

 

       2、计划任务,在未来执行某任务,使用的方法为postXXX();。

 

  android.os.Handler对象通过下面的方法执行计划任务:

  post(Runnable),提交计划任务马上执行;

  postAtTime(Runnable, long),提交计划任务在未来的时间点执行;

  postDelayed(Runnable, long),提交计划任务延时Nms执行。

 

       使用一个例子简单的来介绍一下Handler。

       示例1:一个应用程序中有2个按钮(start、end),当点击start按钮时,执行一个线程,这个线程在控制台输出一串字符串,并且每隔3秒再执行一次线程,直到点击end按钮为止,线程停止。

       下图为这个应用程序的界面:

       下图为执行程序时控制台的输出:

 

      开发步骤:

      1、新建一个Android应用程序

      2、在布局文件中添加2个Button控件标签,并为其设置属性和值

      3、在Activity中,声明控件变量并根据id获得控件对象

      4、在Activity中,创建一个Handler对象

      5、在Activity中,创建一个Runnable对象

      a) 以匿名内部类的方式

      b) 将要执行的操作写在Runnable对象中的run()方法中

      i. 打印出一句话

      ii. 调用Runnable对象的postDelayed()方法

      6、在Activity中,编写start按钮需要的监听器,并绑定。

      在这个监听器的Onclick()方法中,调用Handler的post()方法,将要执行的线程对象放到队列当中。

      7、在Activity中,编写end按钮需要的监听器,并帮定。

      在这个监听器的Onclick()方法中,调用Handler的removeCallbacks ()方法,删除队列当中未执行的线程对象。

      下面是Activity的代码:

package android.handler;        

import android.app.Activity;     

import android.os.Bundle;     

import android.os.Handler;     

import android.view.View;      

import android.view.View.OnClickListener;     

import android.widget.Button;       

public class HandlerTest extends Activity {     

    /** Called when the activity is first created. */    

    private Button startButton;     

    private Button endButton;     

    @Override    

    public void onCreate(Bundle savedInstanceState) {     

        super.onCreate(savedInstanceState);     

        setContentView(R.layout.main);     

        //根据id获得控件对象     

        startButton = (Button)findViewById(R.id.startButton);     

        endButton = (Button)findViewById(R.id.endButton);     

        //为控件设置监听器     

        startButton.setOnClickListener(new StartButtonListener());     

        endButton.setOnClickListener(new EndButtonListener());     

    }     

    class StartButtonListener implements OnClickListener{     

        public void onClick(View v) {     

            //调用Handler的post()方法,将要执行的线程对象放到队列当中     

            handler.post(updateThread);     

        }      

    }     

    class EndButtonListener implements OnClickListener{     

        public void onClick(View v) {     

            //调用Handler的removeCallbacks()方法,删除队列当中未执行的线程对象     

            handler.removeCallbacks(updateThread);     

        }           

    }         

    //创建Handler对象     

    Handler handler = new Handler();     

    //新建一个线程对象     

    Runnable updateThread = new Runnable(){     

        //将要执行的操作写在线程对象的run方法当中     

        public void run(){     

            System.out.println("updateThread");     

            //调用Handler的postDelayed()方法     

            //这个方法的作用是:将要执行的线程对象放入到队列当中,待时间结束后,运行制定的线程对象     

            //第一个参数是Runnable类型:将要执行的线程对象     

            //第二个参数是long类型:延迟的时间,以毫秒为单位     

            handler.postDelayed(updateThread, 3000);     

        }     

    };     

}   

 

示例2:一个应用程序中有一个进度条和一个按钮,当点击按钮后,每隔一秒钟进度条前进一部分。

       开发步骤:

       1、新建一个Android应用程序

       2、在布局文件中添加一个progressBar和一个Button,并为其设置属性和值

       3、在Activity中,声明控件变量并根据id获得控件对象

       4、创建线程对象

       a)通过匿名内部类的方式

       b)在编写完了5、6步之后再来继续编写这个线程对象里的操作

       i. 声明一个变量用来设置进度条的进度

       ii. 重写线程类的run方法(),里面编写要执行的操作

 

       1)打印一个字符串

       2)进度条的值增加

       3)得到一个消息对象

       4)设置消息对象arg1的值

       5)让线程休眠一秒钟

       6)将消息对象放入到消息队列中

       7)判断,如果进度条的值等于100,则将线程对象从队列中移除。

       5、 创建Handler对象

       a) 与示例1不同的地方是,这里是通过匿名内部类的方式来声明的,而示例1是直接new出来的对象。

       b) 重写Handler对象的handlerMessage(Message msg)方法。

       i. 这个方法传入了一个Message对象,即消息对象,首先设置进度条的进度(这个值是Messag对象里面的一个成员变量arg1)。

       ii. 将要执行的线程对象放入到队列当中。

       6、 编写Button需要的监听器,并绑定

       a) 设置进度条为显示状态。

       b) 将要执行的线程对象放入到队列当中。

       下面是Activity的代码:

package android.handler;     

import android.app.Activity;     

import android.os.Bundle;     

import android.os.Handler;     

import android.os.Message;     

import android.view.View;     

import android.view.View.OnClickListener;     

import android.widget.Button;     

import android.widget.ProgressBar;     

    

public class ProgressBarHandlerTest extends Activity {     

    /** Called when the activity is first created. */    

    private ProgressBar progressBar;     

    private Button startButton;     

    @Override    

    public void onCreate(Bundle savedInstanceState) {     

        super.onCreate(savedInstanceState);     

        setContentView(R.layout.main);     

        progressBar = (ProgressBar)findViewById(R.id.progressbar);     

        startButton = (Button)findViewById(R.id.startButton);      

        startButton.setOnClickListener(new ProgressBarOnClickListener());     

    }     

    class ProgressBarOnClickListener implements OnClickListener{     

        public void onClick(View v) {     

            //设置进度条为可见状态     

            progressBar.setVisibility(View.VISIBLE);     

            updateBarHandler.post(updateThread);     

        }     

    }     

    //使用匿名内部类来复写Handler当中的handlerMessage()方法     

    Handler updateBarHandler = new Handler(){     

        @Override    

        public void handleMessage(Message msg) {     

            progressBar.setProgress(msg.arg1);     

            updateBarHandler.post(updateThread);    //将要执行的线程放入到队列当中     

        }     

    };     

    //线程类,该类使用匿名内部类的方式进行声明     

    Runnable updateThread = new Runnable(){     

        int i = 0;     

        public void run() {     

            // TODO Auto-generated method stub      

            System.out.println("Begin Thread");     

            i+=10;     

            //得到一个消息对象,Message类是android系统提供的     

            Message msg = updateBarHandler.obtainMessage();     

            //将Message对象的arg1参数的值设置为i     

            msg.arg1 = i;   //用arg1、arg2这两个成员变量传递消息,优点是系统性能消耗较少     

            try{     

                Thread.sleep(1000); //让当前线程休眠1000毫秒     

            }catch(InterruptedException ex){     

                ex.printStackTrace();     

            }     

            //将Message对象加入到消息队列当中     

            updateBarHandler.sendMessage(msg);     

            //如果i的值等于100     

            if (i == 100){     

                //将线程对象从队列中移除     

                updateBarHandler.removeCallbacks(updateThread);      

            }     

        }     

    };     

}   

 

9.4. PendingIntent(操作意图)

Android详细教程(基础篇):二十六、Android组件通信,Intent详解、消息机制(Message、Handler、Looper)详解、 PendingIntent详解

9.4.1. 认识PendingIntent

Android详细教程(基础篇):二十六、Android组件通信,Intent详解、消息机制(Message、Handler、Looper)详解、 PendingIntent详解

9.4.2. PendingIntent和Intent的区别

Intent的主要功能是完成:一个Activity跳转到其他的Activity或者是Service的操作,表示的是一种操作的意图。

PendingIntent表示的是暂不执行的一种意图。是一种在产生某一事件之后才操作的一种Intent对象。

  • Intent:立即执行
  • 表示的是暂缓执行,在遇到特殊条件后才执行

9.4.3. PendingIntemt的使用

Android详细教程(基础篇):二十六、Android组件通信,Intent详解、消息机制(Message、Handler、Looper)详解、 PendingIntent详解

9.4.3.1. 范例一:发送通知(Notification、NotificationManager的使用)

Notification---表示的是一种提示用户操作的组件

NotificationManager----表示发送通知的操作类

Android详细教程(基础篇):二十六、Android组件通信,Intent详解、消息机制(Message、Handler、Looper)详解、 PendingIntent详解

Notification表示通知,NotificationManager表示对通知的操作(发送通知)、管理

Activity:

package com.makyan.demo;

import android.app.Activity;

import android.app.Notification;

import android.app.NotificationManager;

import android.app.PendingIntent;

import android.os.Bundle;

public class NotificationManagerActivity extends Activity {

            protected void onCreate(Bundle savedInstanceState) {

                       super.onCreate(savedInstanceState);

                       setContentView(R.layout.activity_notification_manager);

                       NotificationManager notificationManager = (NotificationManager) super.getSystemService(NOTIFICATION_SERVICE);

                       Notification notification = new Notification(R.drawable.as,"来自杨雄Android工作室的消息",System.currentTimeMillis());//立即发送

                       PendingIntent intent = PendingIntent.getActivity(this,0, super.getIntent(), PendingIntent.FLAG_UPDATE_CURRENT);

                       notification.setLatestEventInfo(this, "来自杨雄Android工作室的消息", "www://makyan.com", intent);

                       notificationManager.notify("makyan", R.drawable.as, notification);

            }

}

 

Android详细教程(基础篇):二十六、Android组件通信,Intent详解、消息机制(Message、Handler、Looper)详解、 PendingIntent详解

9.4.3.2. 范例二:发送短信(SMSManager的使用):

public final class

SmsManager

extends Object

java.lang.Object

   

android.telephony.SmsManager

 

 

Android详细教程(基础篇):二十六、Android组件通信,Intent详解、消息机制(Message、Handler、Looper)详解、 PendingIntent详解

发送文字信息:

public void sendTextMessage (String destinationAddress, String scAddress, String text, PendingIntent sentIntent, PendingIntent deliveryIntent)

参数详解:

String destinationAddress:表示的是收件人的地址

String scAddress:设置短信的号码,如果为null默认为手机中心号码

String text:短信的内容

PendingIntent sendIntent:当信息发出之后,通过PendingIntent来接受成功或失败的信息报告,如果此参数为空,则检查所有未知的应用程序,这样会导致时间比较长一些

PendingIntent deliveryIntent:当信息发送到收件处时,该PendingIntent触发

Activity:

package com.makyan.demo;

import java.util.Iterator;

import java.util.List;

import android.app.Activity;

import android.app.PendingIntent;

import android.os.Bundle;

import android.telephony.SmsManager;

import android.widget.Toast;

public class SmsManagerActivity extends Activity {

            protected void onCreate(Bundle savedInstanceState) {

                       super.onCreate(savedInstanceState);

                       setContentView(R.layout.activity_sms_manager);

                       String context = "新长征路上的摇滚" +

                                                                      " " +

                                                                      "听说过没见过两万五千里" +

                                                                      "有的说没的做怎知不容易" +

                                                                      "埋着头向前走寻找我自己" +

                                                                      "走过来走过去没有根据地" +

                                                                      "想什么做什么是步枪和小米" +

                                                                      "道理多总是说是大炮轰炸机" +

                                                                      "汗也流泪也落心中不服气" +

                                                                      "藏一藏躲一躲心说别着急" +

                                                                      "噢一 ";

                       SmsManager smsManager = SmsManager.getDefault();

                       PendingIntent intent = PendingIntent.getActivity(this,0, super.getIntent(),PendingIntent.FLAG_UPDATE_CURRENT);

                       if(context.length() > 70){

                                   List<String> list = smsManager.divideMessage(context);

                                   Iterator it = list.iterator();

                                   while(it.hasNext()){

                                               String msg = (String) it.next();

                                               smsManager.sendTextMessage("18798890583", null, msg, intent, null);

                                   }

                       }else{

                                   smsManager.sendTextMessage("18798890583", null, context, intent, null);

                       }

                       Toast.makeText(this, "短信发送成功", Toast.LENGTH_LONG).show();

            }

}

 

注意,需配置发送短信的权限:

<uses-permission android:name="android.permissions.SEND_SMS" />

9.5. AppWidget (桌面组件)

9.5.1. AppWidget的基本概念

就是将一些组件设置到桌面上进行显示,以后直接通过桌面上的一些软件窗口,实现对程序的控制。

开发AppWidget程序,需appWidget包中的几个类的支持:

Android详细教程(基础篇):二十六、Android组件通信,Intent详解、消息机制(Message、Handler、Looper)详解、 PendingIntent详解

Android详细教程(基础篇):二十六、Android组件通信,Intent详解、消息机制(Message、Handler、Looper)详解、 PendingIntent详解

Android详细教程(基础篇):二十六、Android组件通信,Intent详解、消息机制(Message、Handler、Looper)详解、 PendingIntent详解

Android详细教程(基础篇):二十六、Android组件通信,Intent详解、消息机制(Message、Handler、Looper)详解、 PendingIntent详解

范例一:添加自己的AppWidget

定义AppWidgetProvider的子类:

AppWidgetProvider的继承结构:

public class

AppWidgetProvider

extends BroadcastReceiver

java.lang.Object

   

android.content.BroadcastReceiver

 

   

android.appwidget.AppWidgetProvider

 

根据AppWidgetProvider的继承结构,它是BroadcastReceiver的子类,所以,定义了AppWidgetProvider时,就必须要在AndroidMainfest.xml中注册

package com.makyan.demo;

import android.appwidget.AppWidgetManager;

import android.appwidget.AppWidgetProvider;

import android.content.Context;

import android.content.Intent;

public class MyAppWidgetProvider extends AppWidgetProvider {

            @Override

            public void onDeleted(Context context, int[] appWidgetIds) { // 删除时触发

                       System.out.println("*** MyAppWidget onDeleted()");

                       super.onDeleted(context, appWidgetIds);

            }

            @Override

            public void onDisabled(Context context) {                                                                     // 删除时触发

                       System.out.println("*** MyAppWidget onDisabled()");

                       super.onDisabled(context);

            }

            @Override

            public void onEnabled(Context context) {                                                          // 启动时触发

                       System.out.println("*** MyAppWidget onEnabled()");

                       super.onEnabled(context);

            }

            @Override

            public void onReceive(Context context, Intent intent) {            // 处理广播

                       System.out.println("*** MyAppWidget onReceive()");

                       super.onReceive(context, intent);

            }

            @Override

            public void onUpdate(Context context,

                       AppWidgetManager appWidgetManager, int[] appWidgetIds) {         // 更新时触发       

                       System.out.println("*** MyAppWidget onUpdate()");

                       super.onUpdate(context, appWidgetManager, appWidgetIds);

            }

}

 

定义桌面组件makyan_appwidget.xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout

            xmlns:android="http://schemas.android.com/apk/res/android"

            android:orientation="vertical"

            android:layout_width="fill_parent"

            android:layout_height="fill_parent">

            <ImageView

                android:id="@+id/img"

                       android:src="@drawable/as"

                       android:layout_width="fill_parent"

                       android:layout_height="wrap_content" />

            <Button

                android:id="@+id/but"

                       android:layout_width="fill_parent"

                       android:layout_height="wrap_content"

                       android:text="杨雄android工作室"      

                       android:layout_gravity="center_horizontal" />

</LinearLayout>

 

设置桌面显示的appwidget-provider配置文件,定义在“res/xml”下面:

provider_appwidget.xml

<?xml version="1.0" encoding="utf-8"?>

<appwidget-provider

            xmlns:android="http://schemas.android.com/apk/res/android"

            android:minHeight="80px"

            android:minWidth="300px"

            android:updatePeriodMillis="6000"

            android:initialLayout="@layout/makyan_appwidget">

</appwidget-provider>

将AppWidgetProvider在AndroidMainfest中注册

<receiver android:name=".MyAppWidgetProvider">

            <intent-filter>

                       <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />

            </intent-filter>

            <meta-data

                       android:name="android.appwidget.provider"

                       android:resource="@xml/provider_appwidget" />

</receiver>

 

9.5.2. 使用AppWidget跳转到Activity

Android详细教程(基础篇):二十六、Android组件通信,Intent详解、消息机制(Message、Handler、Looper)详解、 PendingIntent详解

也就是说,现在的桌面上的Appwidget组件如果要想设置事件处理操作,那么就必须依靠AppWidgetManager类完成,而且要在onUpdate()方法中完成,因为一旦AppWidget添加组件只有,一定会执行onUpdate()方法。

范例二:使用AppWidget跳转到Activity

AppWidgetProvider:

package com.makyan.demo;

import android.app.PendingIntent;

import android.appwidget.AppWidgetManager;

import android.appwidget.AppWidgetProvider;

import android.content.Context;

import android.content.Intent;

import android.widget.RemoteViews;

public class MyAppWidgetProvider extends AppWidgetProvider {

            @Override

            public void onUpdate(Context context, AppWidgetManager appWidgetManager,

                                   int[] appWidgetIds) {                                                                                            // 更新时触发

                       for (int x = 0; x < appWidgetIds.length; x++) {                  // 更新所有显示的AppWidget

                                   Intent intent = new Intent(context, AppWidgetActivity.class); // 设置操作要执行的Activity

                                   PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,

                                                          intent, PendingIntent.FLAG_UPDATE_CURRENT); // 设置准备执行的Intent

                                   RemoteViews remote = new RemoteViews(context.getPackageName(),

                                                          R.layout.makyan_appwidget);                                                     // 定义要操作的RemoteViews

                                   remote.setOnClickPendingIntent(R.id.but, pendingIntent); // 设置按钮的单击事件

                                   appWidgetManager.updateAppWidget(appWidgetIds[x], remote); // 更新远程视图

                       }

            }

}

其他配置文件和范例一相同

 

范例三:使用AppWidget进行广播

Android详细教程(基础篇):二十六、Android组件通信,Intent详解、消息机制(Message、Handler、Looper)详解、 PendingIntent详解

 

AppWidgetProvider:

package com.makyan.demo;

import android.app.PendingIntent;

import android.appwidget.AppWidgetManager;

import android.appwidget.AppWidgetProvider;

import android.content.ComponentName;

import android.content.Context;

import android.content.Intent;

import android.widget.RemoteViews;

public class MyAppWidgetProvider extends AppWidgetProvider {

            @Override

            public void onReceive(Context context, Intent intent) {

                       if ("org.lxh.action.MYAPPWIDGET_UPDATE".

                                               equals(intent.getAction())) {                                  // 判断是否是指定的Action

                                   RemoteViews remote = new RemoteViews(context.getPackageName(),

                                                          R.layout.makyan_appwidget);                              // 定义RemoteViews

                                   remote.setImageViewResource(R.id.img, R.drawable.as);         // 设置图片

                                   remote.setTextViewText(R.id.but, "www.makyan.cn");  // 更新组件文字

                                   AppWidgetManager appWidgetManager = AppWidgetManager

                                                          .getInstance(context);                                            // 取得AppWidgetManager

                                   ComponentName componentName = new ComponentName(context,

                                                          AppWidgetActivity.class);                                                  // 定义使用的组件

                                   appWidgetManager.updateAppWidget(componentName,

                                                          remote);                                                                               // 更新组件

                       } else {

                                   super.onReceive(context, intent) ;                        // 父类onReceive()

                       }

            }

            @Override

            public void onUpdate(Context context, AppWidgetManager appWidgetManager,

                                   int[] appWidgetIds) {                                                                     // 更新时触发

                       Intent intent = new Intent();                                                         // 设置操作要执行的Intent

                       intent.setAction("org.lxh.action.MYAPPWIDGET_UPDATE");

                       PendingIntent pendingIntent = PendingIntent.getBroadcast(

                                               context, 0,     intent,

                                               PendingIntent.FLAG_UPDATE_CURRENT);           // 设置准备执行的Intent

                       RemoteViews remote = new RemoteViews(context.getPackageName(),

                                               R.layout.makyan_appwidget);                                          // 定义要操作的RemoteViews

                       remote.setOnClickPendingIntent(R.id.but,

                                               pendingIntent);                                                                  // 设置按钮的单击事件

                       appWidgetManager.updateAppWidget(appWidgetIds,

                                               remote);                                                                                         // 更新远程视图

            }

}

其他配置跟范例一相同