需求:
写一个Demo,监听开机广播事件
需要创建一个继承自
BroadcastReceiver
的类,用于处理开机广播
public class BootReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// TODO: This method is called when the BroadcastReceiver is receiving
// an Intent broadcast.
if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
Log.d("BootReceiver~1", "Device has booted");
// 这里可以启动服务或执行其他操作
}
}
}
1.MainActivity类实现功能
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
// 断言方法,出现异常报错
public static void assertTrue(String message, boolean condition) {
if (!condition) {
throw new AssertionError(message);
}
}
public void testBootComplated_A() {
ConditionVariable getBook2 = new ConditionVariable();
BootReceiver receiver = new BootReceiver();
// 主动发一个ACTION_BOOT_COMPLETED广播
Intent intent = new Intent(Intent.ACTION_BOOT_COMPLETED);
receiver.onReceive(getApplicationContext(), intent);
if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
Log.d("BootReceiver~2", "Device has booted");
// 这里可以启动服务或执行其他操作
getBook2.open(); // 更新状态
}
// 这里,如果getBook2.block(10000)函数返回false,就会抛出异常
assertTrue("值不匹配1", getBook2.block(10000));
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 测试这个方法
testBootComplated_A();
}
@Override
protected void onDestroy() {
super.onDestroy();
// 取消注册
// unregisterReceiver(bootReceiver);
}
2.在 AndroidManifest.xml 中注册 Receiver
接下来,在 AndroidManifest.xml
中注册这个 BroadcastReceiver
并请求相关权限
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.demo0923">
<!-- 声明使用该广播的权限 -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<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/Theme.Demo0923">
<receiver
android:name=".BootReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
3.ConditionVariable
类
ConditionVariable
是 Android 提供的一个用于线程间协调的类。open
方法用于将条件状态设置为已打开,并通知等待线程。以下是该方法的基本用法和上下文。
// 创建 ConditionVariable 实例:
ConditionVariable condition = new ConditionVariable();
//等待条件:
new Thread(() -> {
condition.block(); // 阻塞直到条件被打开
// 条件满足后执行的代码
}).start();
// 调用 open 方法:
// 在某些条件下
condition.open(); // 解除等待状态
说明
-
block()
:用于等待条件,线程会在此方法中阻塞,直到open
被调用。 -
线程协调:
open
方法使得其他等待的线程可以继续执行,通常用于在某个条件满足时的线程同步。
这种机制常用于处理需要等待特定条件的多线程场景。
如果有两个 ConditionVariable
实例,你可以用它们分别控制不同的线程或不同的条件。具体使用时,你可以在一个线程中等待一个条件,在另一个线程中打开对应的条件。以下是一个简单的示例:
示例代码
import android.os.ConditionVariable;
public class TwoConditionVariablesExample {
public static void main(String[] args) {
ConditionVariable condition1 = new ConditionVariable();
ConditionVariable condition2 = new ConditionVariable();
// 第一个线程等待 condition1
new Thread(() -> {
System.out.println("线程1开始等待...");
condition1.block();
System.out.println("线程1继续执行!");
}).start();
// 第二个线程等待 condition2
new Thread(() -> {
System.out.println("线程2开始等待...");
condition2.block();
System.out.println("线程2继续执行!");
}).start();
// 模拟一些操作后打开 condition1
new Thread(() -> {
try {
Thread.sleep(2000);
System.out.println("准备打开条件1...");
condition1.open();
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
// 模拟一些操作后打开 condition2
new Thread(() -> {
try {
Thread.sleep(4000);
System.out.println("准备打开条件2...");
condition2.open();
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
}
-
线程1等待
condition1
。 -
线程2等待
condition2
。 -
分别在不同的线程中打开这两个条件,线程1将在2秒后继续,线程2将在4秒后继续。
4.输出结果
如果启动该应用没有监听到系统开机广播,则这个testBootComplated_A 的 断言 assertTrue("值不匹配1", getBook2.block(10000));
2024-09-28 14:46:54.098 7583-7583/com.example.demo0923 E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.demo0923, PID: 7583
java.lang.AssertionError: 值不匹配1
at com.example.demo0923.MainActivity.assertTrue(MainActivity.java:21)
at com.example.demo0923.MainActivity.testBootComplated_A(MainActivity.java:59)
at com.example.demo0923.MainActivity.onCreate(MainActivity.java:78)
at android.app.Activity.performCreate(Activity.java:8000)
at android.app.Activity.performCreate(Activity.java:7984)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3422)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
2024-09-28 14:46:54.170 7583-7583/com.example.demo0923 I/Process: Sending signal. PID: 7583 SIG: 9
综上,如果应用没有接收到ACTION_BOOT_COMPLETED这个广播,就会报断言异常错误, 程序挂掉;如果接收到ACTION_BOOT_COMPLETED广播,程序正常执行