记android学习之路----Broadcast Receiver

Broadcast Receiver—大喇叭

Broadcast Receiver的一些理解

  1:and中的大喇叭,四大组件之一;
  2:分类:按照接收消息的机制不同分为标准广播(和现实生活中的广播一样),顺序广播;
按照广播范围不同可分为:全局广播,应用内广播;
  3:使用:
    1.同一app内部的同一组件内的消息通信(单个或多个线程之间);(一般不用)

   2.同一app内部的不同组件之间的消息通信(单个进程);(一般不用)

   3.同一app具有多个进程的不同组件之间的消息通信;

   4.不同app之间的组件之间消息通信;

   5.Android系统在特定情况下与App之间的消息通信。

机制:

标准广播
这里写图片描述

标准广播机制中:广播发送者会将广播发往指定的地址,只要注册了该地址的广播都会收到消息,没有谁能够阻止广播继续分发;

顺序广播
这里写图片描述
在顺序广播中,接收者是有优先级别的,优先级高的能够先接收广播,并由该接收着向下继续分发,任一级别的接收者都有权力终止广播的继续分发,或者修改广播信息之后分发;

标准版广播:

  1:发送广播:

        public void send(String value){
            Intent intent = new Intent("and.intent.action.MY_BROADCAST");
            intent.putExtra("msg",value);
            sendBroadcast(intent);
        }

广播信息是通过隐式intetnt发送的,在创建intetn对象的时候必须传入指定的广播地址作为参数;表示将该广播信息发往指定的广播地址!

  2:接收广播:
  

        public class MyReceiver extends BroadCastReceiver{
            public void onReceive(Context context,Intent intent){
                //通过intent对象解析出广播消息
                String string = intent.getStringExtra("msg");
            }
        }

  3:注册网络广播地址:
    1:静态注册
      方式:在注册文件中直接写死的方式;
      特点:常驻型;开机之后无论应用是否启动,如果该广播地址被发送了消息,则该广播接收者即可接收到消息;
      

        <receiver and:name="package_name.my_receiver">
                <intent-filter>
                <action and:name="and.intent.action.MY_BROADCAST"> 
                <category and:name="and.intent.category.DEFAULT">
                </intent-filter>
            </receiver>

参数说明:
action:广播地址。可自定义,可使用系统的地址;intetn也就是通过这个参数的内容来匹配广播接收者的

   2:动态注册
      方式:在activity中调用函数注册的方式:
      特点:可自由在需要的地方注册,在不需要的地方解除注册;一般是在onCreat()中注册,在onDestory()中解除注册;
      并且只有在应用启动的时候才能接收到广播消息,当应用关闭之后将无法获取广播消息;

    注册:

        MyReceiver mr = new MyReceiver();
        IntentFilter filter = new IntentFilter();
        filter.addAction("MY_BROADCAST_RECEIVER");
        registerReceiver(mr,filter);

   解除注册:

            public void onDestory(){
                super.onDestory();
                //解除注册
                unregisterReceiver(myreceiver);
            }

实例:
标准版静态注册
AndroidManifest.xml:

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

activity_a.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    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="com.example.lk.myactivityceshi.ActivityA">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="ActivityA页面"
        android:textSize="75dp"
        android:id="@+id/textView"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="63dp"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="发送标准广播---静态注册"
        android:textSize="50dp"
        android:id="@+id/buttona"
        android:layout_marginBottom="63dp"
        android:layout_alignParentBottom="true"
        android:layout_alignParentStart="true"/>
</RelativeLayout>

ActivityA.java:

package com.example.lk.myactivityceshi;

import android.app.Activity;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class ActivityA extends Activity {
    Button button;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_a);
        button = (Button) findViewById(R.id.buttona);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                send("标准广播!!!静态注册");
            }
        });
    }

    //发送广播
    public void send(String str){
        Intent intent = new Intent("MY_BROADCAST_RECEIVER");
        intent.putExtra("msg",str);
        sendBroadcast(intent);
    }

}

这里写图片描述
标准版动态注册

activity_a.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    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="com.example.lk.myactivityceshi.ActivityA">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="ActivityA页面"
        android:textSize="75dp"
        android:id="@+id/textView"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="63dp"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="发送标准广播---动态注册"
        android:textSize="50dp"
        android:id="@+id/buttona"
        android:layout_marginBottom="63dp"
        android:layout_alignParentBottom="true"
        android:layout_alignParentStart="true"/>
</RelativeLayout>

ActivityA.java:

package com.example.lk.myactivityceshi;

import android.app.Activity;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class ActivityA extends Activity {
    Button button;
    MyReceiver mr;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_a);
        button = (Button) findViewById(R.id.buttona);
        //动态注册
         mr = new MyReceiver();
        IntentFilter filter = new IntentFilter();
        filter.addAction("MY_BROADCAST_RECEIVER");
        registerReceiver(mr,filter);

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                send("标准广播!!!动态注册");
            }
        });
    }

    //发送广播
    public void send(String str){
        Intent intent = new Intent("MY_BROADCAST_RECEIVER");
        intent.putExtra("msg",str);
        sendBroadcast(intent);
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(mr);
    }
}

结果:
这里写图片描述

顺序广播:

   1:发送广播:

        public void send(String str){
            Intent intent = new Intent("and.intent.action.MY_BROADCAST");
            intent.putExtra("msg",str);
            //注意这里是sendOrderBroadcast();
          sendOrderBroadcast(intent,"scott.permission.MY_BROADCAST_PERMISSION");
            //第二个参数是权限参数,如果为null则表示不要求接收者指定权限;否则,要求接收这必须指定权限;
        }

注:sendboradcast()中第二个参数是权限;如果不指定该权限,则注册了该地址的广播接收者均能收到广播(在不被截断的情况下)!如果指定了权限则要求注册了改地址的广播接收者还要具备该权限,否则将接收不到消息;
如果加入了此权限,当然不能忘了在注册文件中声明该权限:

<permission android:name="scott.permission.MY_BROADCAST_PERMISSION" /> 

   2:接收广播:

     public class MyReceiver extends BroadCastReceiver{
            public void onReceive(Context context,Intent intent){
                //接收广播消息
                String recvMsg = intent.getStringExtra("msg");
                //正常向下分发消息:
                Bundle bundle1 = new Bundle();
                bundle1.putExtras('msg1',recvMsg);
                setResultExtras (Bundle extras);
                //修改广播信息,再下发:
                Bundle bundle2 = new Bundle();
                bundle2.putExtras('msg2',"消息已被修改"+recvMsg);
                setResultExtras (Bundle extras)
                //截断广播,禁止继续下发
                abortBroadcast();
            }
        }

注册:
注:因为顺序模式的广播接收者是有优先级顺序的,因此在注册的时候要注明优先级 android:priority=”“;优先级参数范围在-1000~1000;数值越大级别越高;
代码:

            <receiver and:name="package_name.my_receiver" and:priority="50">
                <intent-filter>
                <action and:name="and.intent.action.MY_BROADCAST"> 
                <category and:name="and.intent.category.DEFAULT">
                </intent-filter>
            </receiver>

权限问题:
上面说过了;在有序广播中是可以指定接收该消息的权限的;如果广播发送者制定了权限,则接收者想要接收到消息必须申请该权限;
代码:

<uses-permission and:name="MY_PREMISSION"></uses-permisson>

//实例:
顺序版无权限
MyReceiver.java:

package com.example.lk.myactivityceshi;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;

/**
 * Created by Administrator on 2016/11/21 0021.
 */
public class MyReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String str = intent.getStringExtra("msg");
        //在这我们先测试终止广播分发的情况:
        Bundle bundle = new Bundle();
        bundle.putString("msg2", "信息由MyReceiver转发" + str);
        abortBroadcast();
        Log.i("broad","MyReceiver----"+str);
    }
}

MyReceiverTwo.java

package com.example.lk.myactivityceshi;

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

/**
 * Created by Administrator on 2016/11/21 0021.
 */
public class MyReceiverTwo extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String str = intent.getStringExtra("msg");
        Log.i("broad", "MyReceiverTwo----" + str);
    }
}

AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.example.lk.myactivityceshi"
          xmlns:android="http://schemas.android.com/apk/res/android">

    <application
        android:icon = "@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".ActivityA">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <activity android:name=".ActivityB">
            <intent-filter>
                <action android:name="android.intent.action.VIEW"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <data android:scheme="http"/>
            </intent-filter>
        </activity>
        <receiver android:name=".MyReceiver">
            <!-- 注意这里的优先级,设为100 -->
            <intent-filter android:priority="100">
                <action android:name="MY_BROADCAST_RECEIVER"></action>
                <category android:name="android.intent.category.DEFAULT"></category>
            </intent-filter>
        </receiver>
        <receiver android:name=".MyReceiverTwo" >
            <!-- 注意这里的优先级,设为10 -->
            <intent-filter android:priority="10">
                <action android:name="MY_BROADCAST_RECEIVER"></action>
                <category android:name="android.intent.category.DEFAULT"></category>
            </intent-filter>
        </receiver>
    </application>

</manifest>

结果:
这里写图片描述
结果很明显:广播并未向下分发;

第二种情况:
我们改变广播内容之后向下分发:
主要是在MyReceiver.java中设置:
MyReceiver.java:

public class MyReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String str = intent.getStringExtra("msg");
        //在这我们改变信息之后向下分发
        Log.i("broad","MyReceiver----"+str);
        Bundle bundle = new Bundle();
        str += "信息由MyReceiver转发";
        bundle.putString("msg2", str);
        setResultExtras(bundle);

    }
}

MyReceiverTwo.java:

public class MyReceiverTwo extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        //先获取系统发送的广播
        String str = intent.getStringExtra("msg");
        Log.i("broad", "MyReceiverTwo1----" + str);
        //再获取MyReceiver更改之后的广播
        String str2 = getResultExtras(true).getString("msg2");
        Log.i("broad", "MyReceiverTwo2----" + str2);
    }
}

结果如下:
这里写图片描述

顺序版有权限
主要代码和上述无权限的一样,区别在一下几个方面:
MyReceiver.java的send()方法:

    public void send(String str){
        Intent intent = new Intent("MY_BROADCAST_RECEIVER");
        intent.putExtra("msg", str);
        //第二个参数声明要接收该广播所需要的权限,必须以包名.权限名为格式,否则将无法识别!
        sendOrderedBroadcast(intent,"com.example.lk.myactivityceshi.have_permission");
    }

AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.example.lk.myactivityceshi"
          xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 这里要声明接收者所需要的权限 -->
    <permission android:name="com.example.lk.myactivityceshi.have_permission" android:protectionLevel="normal"></permission>
    <application
        android:icon = "@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".ActivityA">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <activity android:name=".ActivityB">
            <intent-filter>
                <action android:name="android.intent.action.VIEW"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <data android:scheme="http"/>
            </intent-filter>
        </activity>
        <receiver android:name=".MyReceiver">
            <intent-filter android:priority="100">
                <action android:name="MY_BROADCAST_RECEIVER"></action>
                <category android:name="android.intent.category.DEFAULT"></category>
            </intent-filter>
        </receiver>
        <receiver android:name=".MyReceiverTwo" >
            <intent-filter android:priority="10">

                <action android:name="MY_BROADCAST_RECEIVER"></action>
                <category android:name="android.intent.category.DEFAULT"></category>
            </intent-filter>
        </receiver>
    </application>
           <!-- 这里给receiver添加权限 -->
<uses-permission android:name="com.example.lk.myactivityceshi.have_permission"/>
</manifest>

测试结果如下:
这里写图片描述

应用内广播:

上述两种广播在整个系统不同应用间均可分发消息,而应用内广播则只能在应用内部分发消息;
此时用到了:LoadBordCastManger类来管理本地广播:

1:发送广播:
    LoadBordCastManger mLoadBroadCast = LoadBordCastManger.getInstance(this);
    发送方法使用mLoadBroadCast.sendBoradCast(intent);
    public void send(String str){
    Intent intent = new Intent(“and.intent.action.MY_BROADCAST);
    intent.putExtra(“msg”,str);
    //注意这里是mLoadBroadCast.sendBoradCast(intent);需要通过LoadBordCastManger类实例来发送广播
    mLoadBroadCast.sendBoradCast(intent);
}

2:接收广播:

        public class MyReceiver extends BroadCastReceiver{
            public void onReceive(Context context,Intent intent){
                //通过intent对象解析出广播消息
                String string = intent.getStringExtra("msg");
            }
        }

注册广播:

            MyReceiver myreceiver = new MyReceiver();
            IntentFilter filter = new IntentFilter();
            filter.addAction("android.intent.action.MY_BROADCAST")
            //如果category不是default的话同样也要添加category
            mLoadBroadCast.registerReceiver(myreceiver,filter);

解除注册

            public void onDestory(){
                super.onDestory();
                //解除注册
                mLoadBroadCast.unregisterReceiver(myreceiver);
            }

实例:应用内广播;

MainActivity.java:

package com.example.lk.broadcastshili;

import android.content.Intent;
import android.content.IntentFilter;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {
    Button button;
    LocalBroadcastManager localBroadcastManger;
    LocalBroadcast localBroadcast;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //注册应用内广播广播
        localBroadcastManger = LocalBroadcastManager.getInstance(this);
        localBroadcast = new LocalBroadcast();
        IntentFilter  intentFilter = new IntentFilter();
        intentFilter.addAction("android.intent.action.MY_BROADCAST_LOCAL");
        localBroadcastManger.registerReceiver(localBroadcast, intentFilter);

        //给按钮添加点击事件
        button = (Button) findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                send();
            }
        });
    }

    //发送广播
    public void send(){
        Intent intent = new Intent("android.intent.action.MY_BROADCAST_LOCAL");

        intent.putExtra("msg","broadcast local!");

        //在此处需要通过manger来发送广播
        localBroadcastManger.sendBroadcast(intent);
    }

    //在onDestory中杰出广播注册
    public void onDestory(){
        localBroadcastManger.unregisterReceiver(localBroadcast);
    }

}

AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.example.lk.broadcastshili"
          xmlns:android="http://schemas.android.com/apk/res/android">
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>

    <!-- 此处需要注册-->
        <receiver android:name=".LocalBroadcast">
            <intent-filter >
                <action android:name="android.intent.action.MY_BROADCAST_LOCAL">
                </action>
            </intent-filter>
        </receiver>
    </application>

</manifest>

LocalBroadcast.java:

package com.example.lk.broadcastshili;

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

public class LocalBroadcast extends BroadcastReceiver {
    @Override
    //接收消息和其他形式的广播是一致的
    public void onReceive(Context context, Intent intent) {
        String strmsg = intent.getStringExtra("msg");
        Log.i("local", strmsg);
    }
}

结果如下:
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值