关闭

广播和广播接收者

标签: androidbroadcastbroadcastreceiver
184人阅读 评论(1) 收藏 举报
分类:

Broadcasts

Android应用程序可以发送或接收来自Android系统和其他Android应用的广播消息,类似于发布-订阅设计模式。当发生感兴趣的事件时,这些广播就会被发送。例如,Android系统在发生各种系统事件时发送广播,比如系统启动或设备开始充电时。应用还可以发送定制的广播,例如,通知其他应用程序可能感兴趣的东西(例如,一些新数据已经被下载)。应用程序可以注册接收特定的广播。当广播被发送时,系统会自动将广播发送给那些订阅了特定类型的广播的应用。

System broadcasts

当系统发生各种系统事件时,系统会自动发送广播,例如当系统切换到飞机模式时。系统广播被发送到所有订阅该事件的应用程序。发送的广播消息采用Intent进行包裹,其中可以包括,action、extra等信息。详情见Intent。

备注:Android7.0及以上系统版本将不会再发送ACTION_NEW_PICTURE、ACTION_NEW_VIDEO广播。同时,在清单文件中注册CONNECTIVITY_ACTION广播接收者是无效的。从Android8.0(API级别26)开始,系统对已声明的广播接收者施加了额外的限制。如果你的应用程序的目标是API级别的26或更高,你就不能使用manifest来为大多数隐式广播(不是专门针对你的应用的广播)声明一个广播接收者。

Receiving broadcasts

通过注册广播接收者可以接收广播,注册广播接收者有两种方式:在清单文件中注册和Context—registered。。

清单文件注册广播接受者:当安装应用程序时,系统包管理器会注册广播接收者。然后,接收者就会成为你的应用的一个独立入口点,这意味着如果该应用目前还没有运行,系统就可以启动应用并发布广播。

代码示例:

<receiver android:name=".MyBroadcastReceiver"  android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED"/>
        <action android:name="android.intent.action.INPUT_METHOD_CHANGED"/>
    </intent-filter>
</receiver>

 

public class MyBroadcastReceiver extends BroadcastReceiver {
    private staticfinal String TAG= "MyBroadcastReceiver";
    @Override
    public void onReceive(Context context,Intent intent){
        StringBuilder sb = new StringBuilder();
        sb.append("Action: "+ intent.getAction()+ "\n");
        sb.append("URI: "+ intent.toUri(Intent.URI_INTENT_SCHEME).toString()+ "\n");
        String log = sb.toString();
        Log.d(TAG, log);
        Toast.makeText(context, log,Toast.LENGTH_LONG).show();
    }
}

 

Context-registered: Context-registered的接收者可以接收广播,只要它们的注册Context是有效的。例如,如果您在Activity中注册接收者,那么只要该Activity没有被Destory,您就可以接收广播。如果您在Application Context中注册,那么只要应用程序在运行,就会接收到广播。

代码示例:

BroadcastReceiver br = new MyBroadcastReceiver();

IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
intentFilter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
this.registerReceiver(br, filter);

 

确保,当您不再需要接收该广播或者是Context不再有效时,调用unregisterReceiver(android.content.BroadcastReceiver)方法停止接收广播。

备注:register 和unregister广播接收者要成对出现,如果你在onCreate()中注册,那你在onDestory()中取消注册。在onResume()中注册在onPause()中取消注册(以防止多次注册)。但是,不要再onSaveInstanceState(Bundle)方法中取消注册,因为它不一定执行。

Sending broadcast方式发送有序广播sendOrderedBroadcast(Intent,String),广播接收者依次接收到该广播,接收该广播的优先顺序取决于定义的android:priority,同时,广播接收者在接到广播的时候可以终止广播的向下继续传播或者是对广播数据进行封装下发。当接收者的优先级相同时,它们接收到广播的顺序是随机的。发送无序广播sendBroadcast(Intent) ,以未定义的顺序向所有接收者发送广播。这就是所谓的正常广播。这是更有效的方法,但这意味着接收者不能读取其他接收者的结果,传播从广播中接收的数据,或者中止广播。发送本地广播LocalBroadcastManager.sendBroadcast,发送和接收广播只在该APP中,不用担心安全问题以及不用进行跨进程通信。

Intent intent = new Intent();
intent.setAction("com.example.broadcast.MY_NOTIFICATION");
intent.putExtra("data","Notice me senpai!");
sendBroadcast(intent);

Effects on process state

当BroadcastRecerver在执行onRecerver()方法时,应用程序是一个前台进程,当onRecerver()执行完时,并且,应用程序只在清单文件中定义了BroadcastRecerver,该应用程序的优先级就会降低。在内存比较低的情况下,该应用程序有可能被杀死。因此,在onRecerver()方法中,不能定义长时间在后台运行的线程,在onRecerver()方法返回时,内存低的情况下,有可能被杀死。为了避免这种情况的发生,你可以调用goAsync()方法(如果你的应用程序需要更多的时间执行后台线程或者是执行JobService使用JobScheduler),因此,系统知道应用程序在持续工作。

public class MyBroadcastReceiver extends BroadcastReceiver {
    private staticfinal String TAG= "MyBroadcastReceiver";

    @Override
    public void onReceive(finalContext context,final Intent intent){
        final PendingResult pendingResult= goAsync();
        AsyncTask<String,Integer, String> asyncTask = new AsyncTask<String,Integer, String>() {
            @Override
            protected String doInBackground(String...params) {
                StringBuilder sb = new StringBuilder();
                sb.append("Action: "+ intent.getAction()+ "\n");
                sb.append("URI: "+ intent.toUri(Intent.URI_INTENT_SCHEME).toString()+ "\n");
                Log.d(TAG, log);
                // Must call finish() so theBroadcastReceiver can be recycled.
                pendingResult.finish();
                return data;
            }
        };
        asyncTask.execute();
    }
}

Security considerations and best practices

1、如果您不需要向应用程序之外的组件发送广播,那么就可以使用本地广播的LocalBroadcastManager发送和接收本地广播。LocalBroadcastManager的效率更高(不需要进程间通信),并且允许您避免考虑任何与其他应用程序相关的安全问题,这些应用程序可以接收或发送您的广播。在你的应用中,本地广播可以作为通用的发布/订阅事件总线,而不需要任何系统范围的广播。

2、有些广播只能采用Context-Register的注册方式,不能采用在清单文件中的定义方式。因为如果许多应用在它们的清单上注册了相同的广播,它可能会导致系统启动大量的应用程序,从而对设备性能和用户体验产生重大影响。例如,CONNECTIVITY_ACTION广播只传递给Context-Register的接收者。

3、不要使用隐式的意图来传播敏感信息。任何注册接收广播的应用程序都可以读取这些信息。有三种方法可以控制谁可以接收你的广播:

1、发送广播时定义权限。

2、采用setPackage(String)指定广播发送给指定包名的应用程序。

3、发送本地广播。

发送权限广播:

发送广播时,定义权限,只有那些在他们的清单中要求获得许可的接收者(并且危险权限要得到用户许可)才可以接受广播。例如,以下代码发送一个广播:

sendBroadcast(newIntent("com.example.NOTIFY"),
              Manifest.permission.SEND_SMS);

要接收广播,接收者应用程序必须请求许可,如下所示:

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

您可以指定一个现有的系统权限,比如SEND_SMS,或者使用元素的作用定义一个定制的权限。

备注::在安装应用程序时,会注册自定义权限。定义自定义权限的应用程序必须安装在使用它的应用程序之前。

当你注册一个广播接收者时,任何应用都可以向你的应用程序接收者发送潜在的恶意广播。有三种方式限制你的应用程序接收到的广播:

1、在定义广播接收者的时候,可以定义权限。

2、在清单文件中定义接收者时,android:export属性设置为false,可以阻止其接收到其他应用发送的广播。

3、也可以定义本地广播LocalBroadcastManager。

接收权限广播:

如果您在注册广播的时候指定一个权限 (要么registerReceiver(BroadcastReceiver,IntentFilter、接收者)或在<receiver>标记在你的清单),那么只有广播请求许可的< uses-permission >标记的清单(如果权限是危险的需要用户授予权限)发送的才可以收到。

<receiver android:name=".MyBroadcastReceiver"
          android:permission="android.permission.SEND_SMS">
    <intent-filter>
        <action android:name="android.intent.action.AIRPLANE_MODE"/>
    </intent-filter>
</receiver>

 

IntentFilter filter = new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED);
registerReceiver(receiver, filter,Manifest.permission.SEND_SMS,null );

 

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

                                                                                      

0
0
查看评论

BroadcastReceiver广播接收者的两种注册方式

广播是android四大组件之一,在我们的应用开发中也占据着重要的地位,我们在很多时候和很多场景中都需要使用到广播,那么接下来我们就说一下广播接收者的两种注册方式: 第一种:在androidmanifest.xml中注册。 在配置文件中注册的接收者的特点是即使应用程序已被关闭,该接收者依然可...
  • lobiner
  • lobiner
  • 2016-11-23 10:33
  • 2227

动态注册广播接收者

通过broadcast(广播)的形式 当我们的进度发生变化的时候我们发送一条广播,然后在Activity的注册广播接收器,接收到广播之后更新ProgressBar,代码如下 package com.example.communication; import android.app.Ac...
  • u012246458
  • u012246458
  • 2016-01-26 15:03
  • 3206

Android中广播接收者的注册与释放

Android中常常利用广播机制来在各个组件之间传递消息,例如在Activity和Service之间。 在Activity中注册广播接收者,来接收来自Service的广播:public class LoginReceiver extends BroadcastReceiver { ...
  • whurs
  • whurs
  • 2015-04-06 16:44
  • 1545

广播接收者--Broadcast

什么是Broadcast BroadcastReceiver是安卓中的四大组件之一。 广播接收器,也被称为全局事件,或系统事件。 当Android系统中任何程序有动作时,如果想通知其他程序,采用广播的方式进行传播是非常有效的。广播从理论上说,可以将一个动作传播给任意多个程序(当...
  • a765717
  • a765717
  • 2016-04-11 08:52
  • 2197

在广播接收者里面启动Activity

public class MyReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { //激活OtherActivity In...
  • zhouxuebao87
  • zhouxuebao87
  • 2015-07-12 21:24
  • 341

注册广播接收者两种方式的区别,及优缺点

转载部分内容:http://blog.csdn.net/superjunjin/article/details/7860025 首先写一个类要继承BroadcastReceiver 第一种:在清单文件中声明,添加    第...
  • zsf5201314z
  • zsf5201314z
  • 2016-07-11 14:13
  • 2413

广播接收者和自定义广播

广播接收者和自定义广播广播接收者监听广播的步骤 定义一个类,这个类继承BroadCastReceiver,实现它的onReceive()方法SdcardReceive extends BroadcastReceiver去清单文件中注册这个类,添加意图过滤器//广播也和activity一样需要注册 &...
  • csdn_liuwen
  • csdn_liuwen
  • 2015-09-11 15:24
  • 2525

android_广播者_只能用代码注册(动态注册)的广播接收者_监听屏幕的状态

在系统里面有这样的广播接收者,它们出现的频率极高, 如果可以在清单文件里面注册广播接收者,那么就会造成一种后果,一旦广播到来,那么将会有一大批的应用随之启动。 如: 屏幕锁屏和点亮、电池电量变更. 那么这样一大批的应用启动,用户手机就很不流畅了.所以,如果想监听这些广播,就需要 使用代码注册pu...
  • xdd_lmd
  • xdd_lmd
  • 2016-03-18 02:28
  • 1424

android ,关于广播接收者的两种不同方式的用法及区别

(1)代码中动态注册 步骤如下: 实例化自定义的广播接收者实例化意图过滤器,并设置要过滤的广播类型(如,我们接收收到短信系统发出的广播)使用Context的registerReceiver(BroadcastReceiver, IntentFilter, String, Handler)方法...
  • sinat_30474567
  • sinat_30474567
  • 2016-06-12 15:26
  • 1036

android之BroadcastReceiver(广播接收者)

BroadcastReceiver本意是广播接收者。这个也是android四大组件之一,广播其实我们也不难理解它,打个简单的比方,比如我们上课时,只要听到下课的铃声,这说明就要下课。在安卓中,广播是全局性的,每个应用都有可能接受到。下面就学习下怎么用广播接受者: 接下来我们就学习以下知识 静态注册广...
  • song_shui_lin
  • song_shui_lin
  • 2016-10-05 23:14
  • 5353
    个人资料
    • 访问:1459次
    • 积分:115
    • 等级:
    • 排名:千里之外
    • 原创:10篇
    • 转载:1篇
    • 译文:0篇
    • 评论:1条
    文章分类
    文章存档