我正在学习Android。我使用以下代码在CustomBroadcastreceiver
中动态注册我的自定义广播接收器MainActivity.java
:
package com.example.bob.broadcastcounterback;
import android.content.ComponentName;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private PackageManager packageManager;
private ComponentName componentName;
private CustomBroadcastreceiver customReceiver;
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
packageManager = getPackageManager();
componentName = new ComponentName(this,CustomBroadcastreceiver.class);
textView = findViewById(R.id.countText);
customReceiver = new CustomBroadcastreceiver(textView);
IntentFilter mIntentFilter = new IntentFilter();
mIntentFilter.addAction(Intent.ACTION_POWER_CONNECTED);
mIntentFilter.addAction("com.example.bob.broadcastcounter");
LocalBroadcastManager.getInstance(this).
registerReceiver(customReceiver,mIntentFilter);
// LocalBroadcastManager.getInstance(this).registerReceiver(customReceiver,new IntentFilter(Intent.ACTION_POWER_CONNECTED));
}
@Override
protected void onStart() {
super.onStart();
// packageManager.setComponentEnabledSetting(
// componentName,
// PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
// PackageManager.DONT_KILL_APP);
}
@Override
protected void onStop() {
super.onStop();
// packageManager.setComponentEnabledSetting(
// componentName,
// PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
// PackageManager.DONT_KILL_APP);
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d("DESTORY CALLED:","destroy");
LocalBroadcastManager.getInstance(this).unregisterReceiver(customReceiver);
}
public void sendBroadcast(View view) {
Intent intent = new Intent("com.example.bob.broadcastcounter");
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
}
CustomBroadcastreceiver.java:
package com.example.bob.broadcastcounterback;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.TextView;
public class CustomBroadcastreceiver extends BroadcastReceiver {
private TextView mTextView;
private int count = 0;
private static final String ACTION_MY_BRODACAST = "com.example.bob.broadcastcounter";
public CustomBroadcastreceiver(){
super();
}
public CustomBroadcastreceiver(TextView mTextView){
this();
this.mTextView = mTextView;
}
@Override
public void onReceive(Context context, Intent intent) {
// TODO: This method is called when the BroadcastReceiver is receiving
// an Intent broadcast.
String intentString = intent.getAction();
switch (intentString){
case Intent.ACTION_POWER_CONNECTED:
Log.d("BroadcastReceiver:",mTextView.toString());
mTextView.setText("power connected!");
// mTextView.setText(++count);
break;
case ACTION_MY_BRODACAST :
mTextView.setText("Custombroadcast Received!");
break;
}
}
}
通过这种方式,每当我按下ACTION_MY_BRODACAST
为onClick
的按钮时,我都会收到sendBroadcast(View view)
广播。但是,当我插入或取消插入USB电缆时,什么都不会发生。然后我选择在AndroidManinfest.xml
注册广播接收器:
<receiver
android:name=".CustomBroadcastreceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
</intent-filter>
</receiver>
这次我不知道会发生什么:每次我插入充电线时,应用程序会立即崩溃并返回。我甚至无法在Android Studio中看到logcat。要知道到底发生了什么,我将Thread.sleep(5000)
添加到onReceive()
方法:
@Override
public void onReceive(Context context, Intent intent) {
// TODO: This method is called when the BroadcastReceiver is receiving
// an Intent broadcast.
String intentString = intent.getAction();
try {
Thread.sleep(5000);
}catch (InterruptedException e){
Log.e("Broadcastcounterback:",e.toString());
}
switch (intentString){
case Intent.ACTION_POWER_CONNECTED:
Log.d("BroadcastReceiver:",mTextView.toString());
mTextView.setText("power connected!");
// mTextView.setText(++count);
break;
case ACTION_MY_BRODACAST :
mTextView.setText("Custombroadcast Received!");
break;
}
}
这次当我点击发送自定义广播的按钮时,mTextView
会在休息5秒后显示Custombroadcast Received!
。当我插入充电线时,5秒后我收到错误:
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.view.View.toString()' on a null object reference
at com.example.bob.broadcastcounterback.CustomBroadcastreceiver.onReceive(CustomBroadcastreceiver.java:41)
这表明当我收到POWER_CONNECTED操作时mTextView
为空。为什么?我使用customReceiver = new CustomBroadcastreceiver(textView);
实例化了customReceiver,因此mTextView不应为null,实际上ACTION_MY_BRODACAST
操作将触发mTextView显示正确的文本而不会出现任何错误。
最后,我的两个问题:
1我们只能通过广播接收器静态注册接收POWER_CONNECTED动作吗?
2为什么会发生错误?
答案 0 :(得分:2)
ACTION_POWER_CONNECTED
广播是系统广播。 LocalBroadcastManager
仅处理与LocalBroadcastManager
一起发送的广播,因此您注册的Receiver实例将无法获得ACTION_POWER_CONNECTED
广播。您需要在Context
上注册Receiver实例,例如Activity
。
清单中的<receiver>
元素静态注册Receiver 类,而不是任何现有的实例。然后,系统会根据需要对该类进行实例化,并且这些实例都不会设置TextView
字段。如果要从静态注册的Receiver类更新Activity
,则需要使用其他一些机制;例如,Intent
s,LocalBroadcastManager
,其他一些事件总线等。
我还要提到ACTION_POWER_CONNECTED
广播不在the list of implicit broadcast exemptions for Android 8.0 and above上,所以如果您的targetSdkVersion
是26岁以上,则无法从Oreo开始使用静态注册的Receiver接收广播