问题描述
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:
- 如果您的应用没有
READ_CALL_LOG
权限(您已经说过您在应用中拥有该权限),但请注意,仅将其添加到清单中还不够,您需要实现 runtime permissions实际接收它。 - 如果当前状态更改不是
EXTRA_STATE_IDLE
=>EXTRA_STATE_RINGING
或EXTRA_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。