zoukankan      html  css  js  c++  java
  • Android中BroadcastReceiver的使用

    1、Android中广播分为静态注册和动态注册

    2、下面是一个简单静态注册的例子

    • 创建一个继承BroadcastReceiver的子类
    public class DeviceBootReceiver extends BroadcastReceiver {
    
        private static final String TAG = DeviceBootReceiver.class.getName();
        
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.d(TAG, "开机了:" + intent.getAction());
        }
    }
    

    该类的功能用于接收手机开机的广播。

    • AndroidManifest.xml中注册该组件
    <receiver android:name=".DeviceBootReceiver">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>
    

    action标签中的值用于匹配广播的类型,这里是开机广播。
    这样当手机开机时,便会收到来自系统的消息。

    同样,我们也可以监听应用安装,应用卸装,USB插拔等系统广播。只是action的值稍有不同。

    <receiver android:name=".OtherStateReceiver">
        <intent-filter>
            <!--电量过低-->
            <action android:name="android.intent.action.BATTERY_LOW" />
            <!--USB连接-->
            <action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
            <!--USB断开-->
            <action android:name="android.intent.action.ACTION_POWER_DISCONNECTED" />
            <!--软件包安装-->
            <action android:name="android.intent.action.PACKAGE_ADDED" />
            <!--软件包卸装-->
            <action android:name="android.intent.action.PACKAGE_REMOVED" />
        </intent-filter>
    </receiver>
    

    上面除了开机广播,其他广播这样注册能成功的前提是 API Level < 26(Android8.0以下)
    。Google为了防止接收者程序常驻内存消耗资源,禁止了一些Manifest declared receiver。我们想要继续监听,就要使用动态注册的方式。

    3、下面是一个动态注册的例子:

    public class SystemBroadcastReceiverActivity extends AppCompatActivity {
    
        private SystemBroadcastReceiver receiver;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_system_broadcast_receiver);
    
            IntentFilter filter = new IntentFilter();
            //USB连接
            filter.addAction(Intent.ACTION_POWER_CONNECTED);
            //USB断开
            filter.addAction(Intent.ACTION_POWER_DISCONNECTED);
            receiver = new SystemBroadcastReceiver();
            registerReceiver(receiver, filter);
        }
    
        private class SystemBroadcastReceiver extends BroadcastReceiver {
    
            @Override
            public void onReceive(Context context, Intent intent) {
                System.out.println(intent.getAction());
            }
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            unregisterReceiver(receiver);
        }
    }
    

    然后在AndroidManifest.xml注册该Activity即可。

    4、自定义广播

    前面说的都是接收系统广播,我们也可以发送自定义的广播,然后在同一个应用或不同应用中接收。

    下面是一个静态注册的自定义广播:
    • 建立一个Activity,提供一个Button,点击后发送广播
    public class CustomSenderActivity extends AppCompatActivity {
    
        public static final String BROADCAST_ACTION = "com.hncj.android.manifest.CustomSenderActivity";
        public static final String BROADCAST_CONTENT = "broadcast_content";
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_custom_sender);
        }
    
        @SuppressLint("WrongConstant")
        public void sendBroadcast(View view) {
            Intent intent = new Intent();
            intent.setAction(BROADCAST_ACTION);
            intent.putExtra(BROADCAST_CONTENT, "我发送了广播,你看收没收到?");
            
            //解决API26及以上的Android静态注册的Receiver收不到广播
            //第一种解决方案:设置标志 Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
            intent.addFlags(0x01000000); //不论是一个应用自己发自己收还是一个应用发一个应用收,都可以实现效果
    
            //第二种解决方案:指定包名(这里是一个应用,自己发,自己收,都在一个包下)
            //intent.setPackage(getPackageName());  //如果是给另一个应用发广播 则写成intent.setPackage("另一个项目应用接收者的包名");
    
            //第三种解决方案: 明确指定包名,类名
            //intent.setComponent(new ComponentName(this, CustomReceiver.class)); //如果是给另一个应用发广播 则写成 intent.setComponent(new ComponentName("另一个应用接收者包名", "另一个应用接收者类名"));
    
            //发送广播
            sendBroadcast(intent);
        }
    }
    
    • 布局文件
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:orientation="vertical"
        android:padding="40dp">
    
        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:onClick="sendBroadcast"
            android:background="#008080"
            android:textSize="30dp"
            android:text="发送广播"></Button>
    </LinearLayout>
    
    • 接收者
    public class CustomReceiver extends BroadcastReceiver {
    
        private static final String TAG = CustomReceiver.class.getName();
    
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            Log.d(TAG, "我收到了来自" + action + "的广播");
        }
    }
    
    • AndroidManifest.xml文件
    <activity android:name=".manifest.CustomSenderActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    
    <receiver android:name=".manifest.CustomReceiver">
        <intent-filter>
            <action android:name="com.hncj.android.manifest.CustomSenderActivity" />
        </intent-filter>
    </receiver>
    

    这里的一个接收者是在当前项目,还有一个接收者在另一个项目,代码基本是一致的。
    相关的API:

    发送有序广播:

    <!--广播中携带数据-->
    Bundle bundle = new Bundle();
    bundle.putString("username", "nacy");
    sendOrderedBroadcast(intent, null, null, null, Activity.RESULT_OK, null, bundle);
    

    为接收者设置优先级:(-1000-1000),即定义哪个接收者先收到,优先级越大,越早收到广播

    <receiver android:name=".manifest.CustomReceiver">
        <!--priority可以设置优先级-->
        <intent-filter android:priority="9">
            <action android:name="com.hncj.android.manifest.CustomSenderActivity" />
        </intent-filter>
    </receiver>
    

    终止广播:

    <!--广播不再向下传递-->
    abortBroadcast();
    

    取出广播中的数据:

    //取出Bundle对象,类似于一个map
     Bundle bundle = getResultExtras(true);
    

    设置接收者权限:(谁能收到)

    • 先在发送方AndroidManifest.xml中声明一个权限(包名+权限名)
    <permission android:name="com.hncj.android.RECEIVER_PERMISSION" />
    
    • 发送时定义接收者需要拥有的权限:
    sendOrderedBroadcast(intent, Manifest.permission.RECEIVER_PERMISSION, null, null, Activity.RESULT_OK, null, bundle);
    
    • 接收者需要在AndroidManifest.xml使用权限:
    <uses-permission android:name="com.hncj.android.RECEIVER_PERMISSION" />
    

    设置发送者权限:(谁能给我发)

    • 先在接收方AndroidManifest.xml声明一个权限
    <permission android:name="com.hncj.android.SENDER_PERMISSION" />
    
    • 在Receiver标签中说明发送者要拥有的权限:
    <receiver android:name=".manifest.CustomReceiver" android:permission="com.hncj.android.SENDER_PERMISSION">
        <intent-filter android:priority="9">
            <action android:name="com.hncj.android.manifest.CustomSenderActivity" />
        </intent-filter>
    </receiver> 
    
    • 在发送方AndroidManifest.xml中使用权限
    <uses-permission android:name="com.hncj.android.SENDER_PERMISSION" />
    

    还有动态注册的自定义广播,与上面提到的动态注册的例子差不多,只是自定义action的内容。

  • 相关阅读:
    Autoit 使用
    小狼毫安装五笔输入法
    MIT 6.824 MapReduce
    基于JDBC封装数据库基本CURD操作
    利用反射特性完成对象的拷贝
    基于HTTP协议和HttpURLConnection完成网上资源的爬取
    应用多线程解决文件拷贝加进度条项目
    java动态代理详解
    [转]String、StringBuffer与StringBuilder之间区别
    “内聚性”和“耦合性”
  • 原文地址:https://www.cnblogs.com/wotoufahaiduo/p/11639140.html
Copyright © 2011-2022 走看看