我不能收到POWER_CONNECTED动作吗?

时间:2018-05-12 01:18:51

标签: android nullpointerexception broadcastreceiver

我正在学习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_BRODACASTonClick的按钮时,我都会收到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为什么会发生错误?

1 个答案:

答案 0 :(得分:2)

  1. ACTION_POWER_CONNECTED广播是系统广播。 LocalBroadcastManager仅处理与LocalBroadcastManager一起发送的广播,因此您注册的Receiver实例将无法获得ACTION_POWER_CONNECTED广播。您需要在Context上注册Receiver实例,例如Activity

  2. 清单中的<receiver>元素静态注册Receiver ,而不是任何现有的实例。然后,系统会根据需要对该类进行实例化,并且这些实例都不会设置TextView字段。如果要从静态注册的Receiver类更新Activity,则需要使用其他一些机制;例如,Intent s,LocalBroadcastManager,其他一些事件总线等。

  3. 我还要提到ACTION_POWER_CONNECTED广播不在the list of implicit broadcast exemptions for Android 8.0 and above上,所以如果您的targetSdkVersion是26岁以上,则无法从Oreo开始使用静态注册的Receiver接收广播