PhoneNumberUtils.formatNumber NullPointException

问题描述

package com.example.helloworld;
    
import android.content.broadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.Looper;
import android.telephony.PhoneNumberUtils;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.widget.Toast;

import java.util.Locale;

public class IncomingCallbroadcastReceiver extends broadcastReceiver {

    public static final String TAG = "PHONE STATE";
    private static String mLastState;
    private final Handler mHandler = new Handler(Looper.getMainLooper());

    @Override
    public void onReceive(final Context context,Intent intent) {
        Log.d(TAG,"onReceive()");

        String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);

        if (state.equals(mLastState)) {
            return;
        } else {
            mLastState = state;
        }

        if (TelephonyManager.EXTRA_STATE_RINGING.equals(state)) {
            String incomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);

if (incomingNumber == null ) {
                Log.i("call-state"," : NULL");
            } else {
                if (TelephonyManager.EXTRA_STATE_OFFHOOK.equals(state)) {
                    Toast.makeText(context,"call Active",Toast.LENGTH_SHORT).show();
                } else if (TelephonyManager.EXTRA_STATE_IDLE.equals(state)) {
                    Toast.makeText(context,"No call",Toast.LENGTH_SHORT).show();
                } else if (TelephonyManager.EXTRA_STATE_RINGING.equals(state)) {
                    Toast.makeText(context,"Ringing State",Toast.LENGTH_SHORT).show();
                    Toast.makeText(context,incomingNumber,Toast.LENGTH_SHORT).show();
                }
            }

            final String phone_number;
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
                phone_number = PhoneNumberUtils.formatNumber(incomingNumber,Locale.getDefault().getCountry());
            } else {
                phone_number = PhoneNumberUtils.formatNumber(incomingNumber);
            }
            Intent serviceIntent = new Intent(context,CallingService.class);
            serviceIntent.putExtra(CallingService.EXTRA_CALL_NUMBER,phone_number);
            context.startService(serviceIntent);
        }
    }
}

我检查并尝试了所有 stackoverflow 问题和答案。 但是,程序在以下位置抛出异常:

phone_number = PhoneNumberUtils.formatNumber(incomingNumber,Locale.getDefault().getCountry());

这是例外:

java.lang.RuntimeException:无法启动接收器 com.example.helloworld.IncomingCallbroadcastReceiver: java.lang.NullPointerException:尝试调用方法 'boolean java.lang.String.startsWith(java.lang.String)' 为空 对象引用

因此,我猜以下内容返回空值:

String incomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);

我尝试了许多其他方法,例如添加 READ_CALL_LOG。但它没有用。 甚至吐司消息也没有显示。 有什么办法可以解决吗?

解决方法

这是 API 的预期行为,according to the docs 在两种情况下您会为 EXTRA_INCOMING_NUMBER 获取 null:

  1. 如果您的应用没有 READ_CALL_LOG 权限(您已经说过您在应用中拥有该权限),但请注意,仅将其添加到清单中还不够,您需要实现 runtime permissions实际接收它。
  2. 如果当前状态更改不是 EXTRA_STATE_IDLE => EXTRA_STATE_RINGINGEXTRA_STATE_IDLE => EXTRA_STATE_OFFHOOK。我只看到您在获取额外状态并忽略之前的状态之前检查新状态的值。

我可以添加我所知道的另一件事,当您的应用具有 READ_CALL_LOG 权限时,您将为每个事件获得两次广播,其中 EXTRA_INCOMING_NUMBER 始终为空,另一个相同的状态-更改 EXTRA_INCOMING_NUMBER 可能有一个值的位置(根据上述情况),因此不要忽略重复的状态更改 (if (state.equals(mLastState)) return),仅当 EXTRA_INCOMING_NUMBER 的值是空。

以下是文档中的相关片段:

此额外内容仅适用于 ACTION_PHONE_STATE_CHANGED 广播已被授予 Manifest.permission.READ_CALL_LOG 和 Manifest.permission.READ_PHONE_STATE 权限。

对于来电,电话号码只保证是 当 EXTRA_STATE 从 EXTRA_STATE_IDLE 变为 EXTRA_STATE_RINGING。如果来电者来自未知号码, 额外的将填充一个空字符串。对于拨出电话, 电话号码只有在 EXTRA_STATE 从 EXTRA_STATE_IDLE 更改为 EXTRA_STATE_OFFHOOK。