Android学习10-Android组件通讯 (7) 广播机制:Broadcast
一、 广播:
广播也是一种信息的发送机制,在 Android 手机中存在着各种各样的广播信息,如手机刚启动时的提示信息、电池不足的警报信息和来电信息等,都会通过广播的形式发给用户,而处理的形式由用户自己决定。在 Android 系统中,开发者可以定义自己的广播机制,但是所有的广播组件都是以一个类的形式出现,而且这个类必须继承自 BroadcastReceiver 类,而后还需要想 Android 系统注册。
当用户需要进行广播时,可以通过 Activity 程序中的 sendBroadcast() 方法触发所有的广播组件,而每一个广播组件在进行广播启动之前,也必须判断用户所传递的广播操作是否是指定的 Action 类型,如果是,则进行广播的处理。
在 Android 系统中,每启动一个广播都需要重新实例化一个新的广播组件对象,并自动调用类中的 onReceive() 方法对广播事件进行处理。
MyBroadcastReceiverUtil.java
package com.iflytek.demo; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.widget.Toast; public class MyBroadcastReceiverUtil extends BroadcastReceiver { public MyBroadcastReceiverUtil() { // 构造方法 System.out.println("** 每次广播都会实例化一个新的广播组件进行操作。"); } @Override public void onReceive(Context context, Intent intent) { Toast.makeText(context, "广播已经启动", Toast.LENGTH_SHORT).show(); } }
Broadcast01Activity.java
package com.iflytek.demo; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class Broadcast01Activity extends Activity { private Button mybut = null; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); super.setContentView(R.layout.main); this.mybut = (Button) super.findViewById(R.id.mybut); this.mybut.setOnClickListener(new OnClickListenerImpl()); } private class OnClickListenerImpl implements OnClickListener { @Override public void onClick(View v) { Intent it = new Intent(Intent.ACTION_EDIT); // 操作的过滤,启动Action Broadcast01Activity.this.sendBroadcast(it);// 进行广播 } } }
AndroidManifest.xml中的application节点下多一个receiver节点
<!-- 定义广播处理,android:name指定广播处理类,android:enabled:设置启用广播 --> <receiver android:enabled="true" android:name=".MyBroadcastReceiverUtil" > <!-- 匹配Action操作时的广播 --> <intent-filter > <action android:name="android.intent.action.EDIT" /> </intent-filter> </receiver>
上面程序中所使用的 Action 是由系统定义好的,下面我们对上面的程序进行扩展,使用一个自定义的 Action ,并向广播中传送一些数据,而此时程序中注册 intent-filter 时,将直接利用 Activity 类中的两个方法完成手工注册及收工注销,方法如下:
No. |
方法 |
描述 |
1 |
Public Intent registerReceiver(BroadcastReceiver receiver,IntentFilter filter) |
注册一个 Broadcast 广播,并指定 IntentFilter |
2 |
Public Intent unregisterReceiver(BroadcastReceiver receiver) |
注销注定的 Broadcast 广播 |
注:注册时传的 IntentFilter 与 AndroidManifest.xml 中 intent-filter 节点功能一致, IntentFilter 提供的方法有:
No. |
方法 |
描述 |
1 |
Public IntentFilter() |
创建一个空的 IntentFilter 对象 |
2 |
Public IntentFilter(String action) |
创建一个 IntentFilter 对象,并指定 Action |
3 |
Public final void addAction(String action) |
增加一个要过滤的 Action |
4 |
Public final void addCategory(String category) |
增加一个要过滤的 Category |
5 |
Public final Boolean hasAction(String action) |
判断指定的 Action 是否存在 |
6 |
Public final Boolean hasCategory(String category) |
判断指定的 Category 是否存在 |
Broadcast02Activity.java
package com.iflytek.demo; import android.app.Activity; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class Broadcast02Activity extends Activity { private Button mybut = null; private MyBroadcastReceiverUtil broadUtil = null; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); super.setContentView(R.layout.main); this.mybut = (Button) super.findViewById(R.id.mybut); this.mybut.setOnClickListener(new OnClickListenerImpl());// 设置监听 } private class OnClickListenerImpl implements OnClickListener { @Override public void onClick(View v) { Intent it = new Intent("com.iflytek.action.XDWANG"); // 操作的过滤 it.putExtra("msg", "http://xdwangiflytek.iteye.com"); // 附加信息 IntentFilter filter = new IntentFilter("com.iflytek.action.XDWANG"); Broadcast02Activity.this.broadUtil = new MyBroadcastReceiverUtil(); Broadcast02Activity.this.registerReceiver( Broadcast02Activity.this.broadUtil, filter);// 注册广播 Broadcast02Activity.this.sendBroadcast(it);// 进行广播 } } @Override protected void onStop() { super.unregisterReceiver(Broadcast02Activity.this.broadUtil);// 注销广播 super.onStop(); } }
MyBroadcastReceiverUtil.java
package com.iflytek.demo; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.widget.Toast; public class MyBroadcastReceiverUtil extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) {// 处理广播事件 if ("com.iflytek.action.XDWANG".equals(intent.getAction())) { // 判断是指定的Action String msg = intent.getStringExtra("msg"); // 取得附加信息 Toast.makeText(context, msg, Toast.LENGTH_SHORT).show(); } } }
一、 通过 Broadcast 启动 Service
在前面我们说了 Activity 程序启动 Service 的操作,那么这里我们再来说一下 Broadcas 启动 Service 。
MyServiceUtil.java:
package com.iflytek.demo; import android.app.Service; import android.content.Intent; import android.os.IBinder; public class MyServiceUtil extends Service { @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { System.out.println("*** Service onCreate()"); super.onCreate(); } @Override public void onDestroy() { System.out.println("*** Service onDestroy()"); super.onDestroy(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { System.out.println("*** Service onStartCommand()"); return Service.START_CONTINUATION_MASK; } }
MyBroadcastReceiverUtil.java
package com.iflytek.demo; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; public class MyBroadcastReceiverUtil extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { context.startService(new Intent(context, MyServiceUtil.class)); } }
Broadcast03Activity.java
package com.iflytek.demo; import android.app.Activity; import android.content.Intent; import android.os.Bundle; public class Broadcast03Activity extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); super.setContentView(R.layout.main); Intent it = new Intent("com.iflytek.action.XDWANG"); // 操作的过滤 Broadcast03Activity.this.sendBroadcast(it); } @Override protected void onStop() { super.onStop(); } }
广播(BroadcastReceiver)可以像Activity程序那样通过配置运行,是一个可以直接运行的没有界面的Activity程序,一般开发都是通过Activity启动广播(BroadcastReceiver)或者Service,或者是利用广播(BroadcastReceiver)启动Service,所以当需要在后台启动Service,而又不想显示前台界面时,就使用广播(BroadcastReceiver)。
三、闹钟服务
Android系统中为了实现闹钟的功能,专门提供了Context.ALARM_SERVICE闹钟服务,当通过getSystemService()方法取得此服务时,将返回一个android.app.AlarmManager,其提供的常用方法有:
No. |
常量及方法 |
描述 |
1 |
Public static final int RTC_WAKEUP |
到设置的闹钟时间时,自动唤醒设备 |
2 |
Public void cancel(PendingIntent operation) |
取消闹钟 |
3 |
Public void set(int type,long triggerAtTime,PendingIntent operation) |
设置闹钟 |
4 |
Public void setRepeation(int type,long triggerAtTime,long interval,PendingIntent operation) |
设置闹钟重复响起 |
5 |
Public void setTime(long millis) |
设置时间 |
AlarmMessage.java
package com.iflytek.demo; import java.text.SimpleDateFormat; import java.util.Date; import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; import android.os.Bundle; /** * * @author xdwang * * @create 2012-10-29 下午9:31:39 * * @email:xdwangiflytek@gmail.com * * @description 闹钟提示的Activity程序类 * */ public class AlarmMessage extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); new AlertDialog.Builder(this)// 建立对话框 .setIcon(R.drawable.ic_launcher)// 设置图标 .setTitle("闹钟时间已到!")// 设置对话框标题 .setMessage( "闹钟响起,现在时间:" + new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒") .format(new Date()))// 定义显示文字 .setPositiveButton("关闭", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { AlarmMessage.this.finish();// 关闭对话框后程序结束 } }).show();// 显示对话框 } }
MyAlarmReceiver.java
package com.iflytek.demo; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; /** * * @author xdwang * * @create 2012-10-29 下午9:52:12 * * @email:xdwangiflytek@gmail.com * * @description 定义广播接受类 * */ public class MyAlarmReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Intent it = new Intent(context, AlarmMessage.class);// 定义要操作的Intent it.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);// 传递一个新的任务标记 context.startActivity(it);// 启动Intent } }
Broadcast04Activity.java
package com.iflytek.demo; import java.util.Calendar; import android.app.Activity; import android.app.AlarmManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; import android.widget.TimePicker; import android.widget.TimePicker.OnTimeChangedListener; import android.widget.Toast; public class Broadcast04Activity extends Activity { private AlarmManager alarm = null; // 闹钟服务管理 private Button set = null; private Button delete = null; private TextView msg = null; private TimePicker time = null; private int hourOfDay = 0;// 保存设置的时 private int minute = 0;// 保存设置的分 private Calendar calendar = Calendar.getInstance(); /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); super.setContentView(R.layout.main); this.set = (Button) super.findViewById(R.id.set); this.delete = (Button) super.findViewById(R.id.delete); this.msg = (TextView) super.findViewById(R.id.msg); this.time = (TimePicker) super.findViewById(R.id.time); this.alarm = (AlarmManager) super .getSystemService(Context.ALARM_SERVICE);// 取得闹钟服务 this.set.setOnClickListener(new SetOnClickListener()); this.delete.setOnClickListener(new DeleteOnClickListener()); this.time.setIs24HourView(true);// 24小时制 this.time.setOnTimeChangedListener(new OnTimeChangedListenerImpl());// 设置时间改变监听 } /** * * @author xdwang * * @create 2012-10-29 下午9:59:51 * * @email:xdwangiflytek@gmail.com * * @description * 时间操作的监听,当时间改变后可以及时的将所设置的时间设置到Calendar对象中,然后通过Calendar对象来设置闹钟的响起时间 * */ private class OnTimeChangedListenerImpl implements OnTimeChangedListener { @Override public void onTimeChanged(TimePicker view, int hourOfDay, int minute) { Broadcast04Activity.this.calendar.setTimeInMillis(System .currentTimeMillis());// 设置当前时间 Broadcast04Activity.this.calendar.set(Calendar.HOUR_OF_DAY, hourOfDay);// 设置小时 Broadcast04Activity.this.calendar.set(Calendar.MINUTE, minute);// 设置分钟 Broadcast04Activity.this.calendar.set(Calendar.SECOND, 0);// 设置秒 Broadcast04Activity.this.calendar.set(Calendar.MILLISECOND, 0);// 设置毫秒 Broadcast04Activity.this.hourOfDay = hourOfDay;// 保存设置的小时 Broadcast04Activity.this.minute = minute;// 保存设置的分钟 } } /** * * @author xdwang * * @create 2012-10-29下午10:10:08 * * @email:xdwangiflytek@gmail.com * * @description * 设置闹钟的操作类,首先在PendingIntent类包裹一个要执行闹钟响起的Intent操作,之后将此PendingIntent对象设置到闹钟中 * ,设置成功后会提示用户操作成信息 * */ private class SetOnClickListener implements OnClickListener { @Override public void onClick(View v) { Intent intent = new Intent(Broadcast04Activity.this, MyAlarmReceiver.class);// 指定跳转的Intent intent.setAction("com.iflytek.action.setalarm");// 定义广播的Action PendingIntent sender = PendingIntent.getBroadcast( Broadcast04Activity.this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);// 指定PendingIntent Broadcast04Activity.this.alarm .set(AlarmManager.RTC_WAKEUP, Broadcast04Activity.this.calendar.getTimeInMillis(), sender);// 设置闹钟 Broadcast04Activity.this.msg.setText("闹钟响起的时间是:" + Broadcast04Activity.this.hourOfDay + "时" + Broadcast04Activity.this.minute + "分。");// 提示信息 Toast.makeText(Broadcast04Activity.this, "闹钟设置成功!", Toast.LENGTH_LONG).show();// 显示提示信息 } } /** * * @author xdwang * * @create 2012-10-29 下午10:18:24 * * @email:xdwangiflytek@gmail.com * * @description 闹钟设置成功后也可以删除指定的闹钟 * */ private class DeleteOnClickListener implements OnClickListener { @Override public void onClick(View v) { if (Broadcast04Activity.this.alarm != null) { Intent intent = new Intent(Broadcast04Activity.this, MyAlarmReceiver.class); intent.setAction("com.iflytek.action.setalarm"); PendingIntent sender = PendingIntent.getBroadcast( Broadcast04Activity.this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); Broadcast04Activity.this.alarm.cancel(sender); // 取消 Broadcast04Activity.this.msg.setText("当前没有设置闹钟。"); Toast.makeText(Broadcast04Activity.this, "闹钟删除成功!", Toast.LENGTH_LONG).show(); } } } }
main.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"> <TimePicker android:id="@+id/time" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <TextView android:id="@+id/msg" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="当前没有设置闹钟" /> <Button android:id="@+id/set" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="设置闹钟" /> <Button android:id="@+id/delete" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="删除闹钟" /> </LinearLayout>
AndroidManifest.xml
<activity android:name=".AlarmMessage" /> <!-- android:process=":remote"表示单独开票一个进程处理程序 --> <receiver android:enabled="true" android:name="MyAlarmReceiver" android:process=":remote" > <intent-filter > <action android:name="com.iflytek.action.setalarm" /> </intent-filter> </receiver>