Broadcast Receivers 的广播学习

BroadcastReceiver也就是“广播接收者”的意思,顾名思义,它就是用来接收来自系统和应用中的广播。

在Android系统中,广播体现在方方面面,例如当开机完成后系统会产生一条广播,接收到这条广播就能实现开机启动服务的功能;当网络状态改变时系统会产生一条广播,接收到这条广播就能及时地做出提示和保存数据等操作;当电池电量改变时,系统会产生一条广播,接收到这条广播就能在电量低时告知用户及时保存进度,等等。

Android中的广播机制设计的非常出色,很多事情原本需要开发者亲自操作的,现在只需等待广播告知自己就可以了,大大减少了开发的工作量和开发周期。而作为应用开发者,就需要数练掌握Android系统提供的一个开发利器,那就是BroadcastReceiver。下面我们就对BroadcastReceiver逐一地分析和演练,了解和掌握它的各种功能和用法。

首先,我们来演示一下创建一个BroadcastReceiver,并让这个BroadcastReceiver能够根据我们的需要来运行。

要创建自己的BroadcastReceiver对象,我们需要继承android.content.BroadcastReceiver,并实现其onReceive方法。下面我们就创建一个名为MyReceiver广播接收者:

package com.scott.receiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

public class MyReceiver extends BroadcastReceiver {
    
    private static final String TAG = "MyReceiver";
    
    @Override
    public void onReceive(Context context, Intent intent) {
        String msg = intent.getStringExtra("msg");
        Log.i(TAG, msg);
    }

}

在onReceive方法内,我们可以获取随广播而来的Intent中的数据,这非常重要,就像无线电一样,包含很多有用的信息。

在创建完我们的BroadcastReceiver之后,还不能够使它进入工作状态,我们需要为它注册一个指定的广播地址。没有注册广播地址的BroadcastReceiver就像一个缺少选台按钮的收音机,虽然功能俱备,但也无法收到电台的信号。下面我们就来介绍一下如何为BroadcastReceiver注册广播地址。

静态注册

静态注册是在AndroidManifest.xml文件中配置的,我们就来为MyReceiver注册一个广播地址:

<receiver android:name=".MyReceiver">
            <intent-filter>
                <action android:name="android.intent.action.MY_BROADCAST"/>
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </receiver>

配置了以上信息之后,只要是android.intent.action.MY_BROADCAST这个地址的广播,MyReceiver都能够接收的到。注意,这种方式的注册是常驻型的,也就是说当应用关闭后,如果有广播信息传来,MyReceiver也会被系统调用而自动运行。

动态注册

动态注册需要在代码中动态的指定广播地址并注册,通常我们是在Activity或Service注册一个广播,下面我们就来看一下注册的代码:

MyReceiver receiver = new MyReceiver();
        
IntentFilter filter = new IntentFilter();
filter.addAction("android.intent.action.MY_BROADCAST");
        
registerReceiver(receiver, filter);

注意,registerReceiver是android.content.ContextWrapper类中的方法,Activity和Service都继承了ContextWrapper,所以可以直接调用。在实际应用中,我们在Activity或Service中注册了一个BroadcastReceiver,当这个Activity或Service被销毁时如果没有解除注册,系统会报一个异常,提示我们是否忘记解除注册了。所以,记得在特定的地方执行解除注册操作:

@Override
protected void onDestroy() {
    super.onDestroy();
    unregisterReceiver(receiver);
}

执行这样行代码就可以解决问题了。注意,这种注册方式与静态注册相反,不是常驻型的,也就是说广播会跟随程序的生命周期。

我们可以根据以上任意一种方法完成注册,当注册完成之后,这个接收者就可以正常工作了。我们可以用以下方式向其发送一条广播:

    public void send(View view) {
        Intent intent = new Intent("android.intent.action.MY_BROADCAST");
        intent.putExtra("msg", "hello receiver.");
        sendBroadcast(intent);
    }

注意,sendBroadcast也是android.content.ContextWrapper类中的方法,它可以将一个指定地址和参数信息的Intent对象以广播的形式发送出去。

点击发送按钮,执行send方法,控制台打印如下:

看到这样的打印信息,表明我们的广播已经发出去了,并且被MyReceiver准确无误的接收到了。

上面的例子只是一个接收者来接收广播,如果有多个接收者都注册了相同的广播地址,又会是什么情况呢,能同时接收到同一条广播吗,相互之间会不会有干扰呢?这就涉及到普通广播和有序广播的概念了。

普通广播(Normal Broadcast)

普通广播对于多个接收者来说是完全异步的,通常每个接收者都无需等待即可以接收到广播,接收者相互之间不会有影响。对于这种广播,接收者无法终止广播,即无法阻止其他接收者的接收动作。

有序广播(Ordered Broadcast)

有序广播比较特殊,它每次只发送到优先级较高的接收者那里,然后由优先级高的接受者再传播到优先级低的接收者那里,优先级高的接收者有能力终止这个广播。

--------------------

显示的效果图:

编写的代码:

package com.eoeandroid.broadcastreceiver;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class HelloBroadcastReceiver extends BroadcastReceiver {
    
    private Context context;

    @Override
    public void onReceive(Context context, Intent intent) {
        this.context = context;
        showNotification(intent);
    }

    private void showNotification(Intent intent) {
        NotificationManager notificationManager = (NotificationManager) context
                .getSystemService(Context.NOTIFICATION_SERVICE);

        Notification notification = new Notification(R.drawable.ic_launcher,
                intent.getExtras().getString("content"),
                System.currentTimeMillis());

        PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
                new Intent(context, MainActivity.class), 0);
        
        notification.setLatestEventInfo(context,
                intent.getExtras().getString("content"), null, pendingIntent);
        
        notificationManager.notify(R.layout.main, notification);
    }
}

注册广播:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.eoeandroid.broadcastreceiver"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="10" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        
        <receiver android:name=".HelloBroadcastReceiver">
           <intent-filter> 
               <action android:name="com.eoeandroid.action.BroadcastReceiverTest"/>
           </intent-filter>
        </receiver>
        
    </application>
    
</manifest>

xml布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <EditText 
        android:id="@+id/et_broadcastContent"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:hint="请输入广播内容"
        />
    <Button
        android:id="@+id/btn_sendBroadcast"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="发送广播" />

</LinearLayout>

MainActiviy.java

package com.eoeandroid.broadcastreceiver;

import android.app.Activity;
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.Toast;

public class MainActivity extends Activity {
    private Context mContext;
    private Button btnSendBroadcast;
    private TextView etBroadcastContent;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mContext = this;

        btnSendBroadcast = (Button) findViewById(R.id.btn_sendBroadcast);
        btnSendBroadcast.setOnClickListener(new SendBroadcastClickListener());

        etBroadcastContent = (TextView) findViewById(R.id.et_broadcastContent);
    }

    private class SendBroadcastClickListener implements OnClickListener {
        @Override
        public void onClick(View v) {
            String content = etBroadcastContent.getText().toString().trim();
            if (content.length() < 1) {
                Toast.makeText(mContext, etBroadcastContent.getHint(), 1).show();
                return;
            }
            Intent intent = new Intent();
            intent.setAction("com.eoeandroid.action.BroadcastReceiverTest");
            intent.putExtra("content", content);
            sendBroadcast(intent);
        }
    }
}
原文地址:https://www.cnblogs.com/zhoujn/p/4311294.html