四大组件---BroadcastReceiver

630 阅读3分钟

四大组件---BroadcastReceiver

一、为什么要有广播接收者

【1】 android系统内部已经定义好一些广播事件,外拨电话,短信到来,sd卡状态,电池电量

【2】 使用broadcaseReceiver接收系统已经定义好的事件

【3】 定义广播接收者的目的是为了方便开发者进行开发

【4】 类型于java中的观察者模式

二、系统广播例子

【1】 外拨电话(ip拨号器):

1.定义一个外拨的广播接收者,OutgoingReceiver继承BroadcastReceiver
2.在清单文件中注册
	<receiver android:name=".OutGoingCallReceiver">
        <intent-filter>
            <action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
        </intent-filter>
    </receiver> 
	还必须申请权限
	<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
3.如果是6.0以上的,还需要动态申请权限Manifest.PROCESS_OUTGOING_CALLS
4.在java文件中,获取将要拨打的号码,将号码修改,再设置回去
/**
 * 接收外拨号码
 */
override fun onReceive(context: Context?, intent: Intent?) {
    // 获取号码
    val resultData = resultData
    println("resultData:$resultData")
    // 加上区号
    setResultData("0754$resultData")
}

【2】 sd卡

1.定义一个监听sd卡的广播接收者
2.在清单文件中注册该广播接收者
	<receiver android:name=".SdReceiver">
        <intent-filter>
            <action android:name="android.intent.action.MEDIA_MOUNTED"/>
            <action android:name="android.intent.action.MEDIA_UNMOUNTED"/>

            <!--需要配置一个data 约束类型是file,因为sd卡中的数据都是file-->
            <data android:scheme="file"/>
        </intent-filter>
    </receiver>

【3】 短信接收

1.定义一个短信接收的广播
2.在清单文件中注册该广播,添加意图过滤器
	<intent-filter>
        <action android:name="android.provider.Telephony.SMS_RECEIVED"/>
    </intent-filter>
	此action已经被谷歌工程师屏蔽了,但是功能还是存在的
3.添加短信接收的权限
	<uses-permission android:name="android.permission.RECEIVE_SMS"/>
	此权限需要动态申请
4.java代码
	class SmsReceiver : BroadcastReceiver() {
    // 短信到来的时候执行
    override fun onReceive(context: Context?, intent: Intent?) {
        val pdus = intent?.extras?.get("pdus")
        if (pdus is Array<*>) {
            pdus.forEach {
                val message = SmsMessage.createFromPdu(it as ByteArray?)
                val messageBody = message.messageBody
                val originatingAddress = message.originatingAddress
                Toast.makeText(context, "接收到短信:\n$originatingAddress:$messageBody", Toast.LENGTH_LONG)
                    .show()
            	}
        	}
    	}
	}

【4】 app的安装和卸载

1.定义一个接收app的安装和卸载的广播
2.在清单文件中注册该广播,添加意图过滤器
	<intent-filter>
        <action android:name="android.intent.action.PACKAGE_ADDED"/>
        <action android:name="android.intent.action.PACKAGE_REMOVED" />

        <data android:scheme="package"/>
    </intent-filter>
	注意:此广播需要配置data中的scheme,值为package
3.java代码
	class AppStateReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        when (intent?.action) {
            "android.intent.action.PACKAGE_ADDED" -> {
                println("add")
            }

            "android.intent.action.PACKAGE_REMOVED" -> {
                println("remove")
            }
       	 }
    	}	
	}
4.注意:这个广播属于隐式广播,在android8.0以上对这些隐式广播作了限制,在清单文件中静态注册是无效果的,需要动态注册,如果非要进行静态注册的话,需要将targetSdkVersion设在26以下
5.动态注册:
	val intentFilter = IntentFilter()
    intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED)
    intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED)
    intentFilter.addDataScheme("package")
    registerReceiver(appStateReceiver, intentFilter)

【5】 开机启动

1.定义一个接收开机启动的广播接收者
2.在清单文件中注册该广播接收者,然后添加意图过滤器
	<intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED"/>
    </intent-filter>
3.还需要添加权限
	<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
	此权限不需要动态申请

三、自定义广播

1.无序广播

android 8.0以上需要
intent.component= ComponentName(this,"com.wzh.a02_broadcastreceiverdemo.order_broardcastreceiver.ProvinceReceiver")

sendBroadcast(intent),不管有没有接收者,都会发送 不可以被中止,数据不可以被修改

2.有序广播

   /**
     * intent
     *
     * receiverPermission   接收的权限
     *
     * resultReceiver   最终的receiver,不需要在清单文件中配置
     *
     * scheduler    handle
     *
     * initialCode  初始化码
     *
     * initialData  初始化数据
     *
     * initialExtras    额外的数据
     */
sendOrderedBroadcast(intent4, null, null, null, 1, "发送大米了", null)

有序广播可以被中止,数据可以被修改 android 8.0以上,发送有序广播,暂时没有合适的解决方案

四、特殊的广播接收者

操作比较频繁的广播事件,屏幕的锁屏和解锁,电池电量的变化,这些广播接收者在清单文件中注册是无效的

android.intent.action.SCREEN_ON
android.intent.action.SCREEN_OFF
android.intent.action.BATTERY_CHANGED
android.intent.action.CONFIGURATION_CHANGED
android.intent.action.TIME_TICK