一,对手机系统事件进行监听
场景:对手机充电和断电进行监听
手机充电和断电已经被系统写成广播并发布到消息处理中心(ActivityManagerService),那我们做的就是去对这个广播进行监听。
充电和断电是两个广播事件
1,分别写两个广播接收者
新建两个java类
public class PowerOffBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"断电了",Toast.LENGTH_SHORT).show();
Log.d("BroadcastReceiver","断电了");
}
}
public class PowerOnBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"充上电了",Toast.LENGTH_LONG).show();
Log.d("BroadcastReceiver","充上电了");
}
}
2,在mainfest中对广播进行注册监听
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myndktest">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
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=".PowerOnBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.ACTION_POWER_CONNECTED"></action>
</intent-filter>
</receiver>
<receiver android:name=".PowerOffBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"></action>
</intent-filter>
</receiver>
</application>
</manifest>
不用在MainActivity中写啥,接收者就能接收到广播发布者(系统)发布的广播
测试结果:
1,当应用进程在主界面活动时
能看到log结果,也能看到弹出的Toast
2,当按home键时,应用进程没有被kill,可以看到log结果,但是不能看到toast
(因为toast依赖于context,而context依赖于应用进程)
3,当杀掉应用进程的时候,log和toast都看不到了
猜测可能的流程:
1,首先系统在ActivityManagerService那里注册好关于充电断电的广播
2,当拔掉或者插上的时候,系统能感知到,所以就发布广播,通知那些注册监听这个广播的Receiver
3,前面的两个Receiver就通过onReceive()方法接收到了消息(前提是它依赖的应用进程是活动状态)
二,自定义一个广播
使用场景:当某个对象完成一项任务时,可以通过广播的方式去提醒其他接收者,然后这些接收者收到消息后决定是否进行后续处理。
public class BroadcastReceiverOne extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.d("BroadcastReceiver","我是接收一号,我收到了NotifyBroadcast的广播");
}
}
public class BroadcastReceiverTwo extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.d("BroadcastReceiver","我是接收二号,我收到了NotifyBroadcast的广播");
}
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.myndktest">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
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=".BroadcastReceiverOne">
<intent-filter>
<action android:name="NotifyBroadcast"></action>
</intent-filter>
</receiver>
<receiver android:name=".BroadcastReceiverTwo">
<intent-filter>
<action android:name="NotifyBroadcast"></action>
</intent-filter>
</receiver>
</application>
</manifest>
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn_send=(Button)findViewById(R.id.btn_send);
btn_send.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//假设当完成一项任务后,在这里通过intent对接收者发送广播
Intent intent=new Intent();
intent.setAction("NotifyBroadcast");
sendBroadcast(intent);
}
});
}
}
结果:对NotifyBroadcast这个广播的接收者都收到了消息
D/BroadcastReceiver: 我是接收二号,我收到了NotifyBroadcast的广播
D/BroadcastReceiver: 我是接收一号,我收到了NotifyBroadcast的广播
3,广播模型
4,不同应用之间发送广播
(1)在发送广播的进程里
package com.example.ndktest2;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn_send=(Button)findViewById(R.id.btn_send);
btn_send.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=new Intent();
intent.setAction("AnotherProcess");
sendBroadcast(intent);
}
});
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/btn_send"
android:layout_marginTop="50dp"
android:text="点击向另一个进程发送广播"
></Button>
</LinearLayout>
(2)在接收广播的进程里
package com.example.myndktest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class ReceiveAnotherProcessBroadcast extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.d("Broadcast","我在com.example.myndktest进程,我接收到了另外一个进程的广播");
Log.d("Broadcast","context="+context.getPackageName()+" intent="+intent.toString());
}
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.myndktest">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
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=".ReceiveAnotherProcessBroadcast">
<intent-filter>
<action android:name="AnotherProcess"></action>
</intent-filter>
</receiver>
</application>
</manifest>
测试前提:不能让接收广播进程被kill。可以让它处于pause状态
结果:
我在com.example.myndktest进程,我接收到了另外一个进程的广播
context=com.example.myndktest intent=Intent { act=AnotherProcess flg=0x800010 cmp=com.example.myndktest/.ReceiveAnotherProcessBroadcast }