[英]Android, TelephonyManager, the joys of PhoneStateListener and incoming numbers
I've very newly gotten into Android
development, and decided that my first conquest on this fresh field would be to grasp how the phone reacted to incoming calls. 我刚刚进入
Android
开发阶段,并决定我对这个新领域的首次征服将是掌握手机对来电的反应。
A little googling later led me to http://www.compiletimeerror.com/2013/08/android-call-state-listener-example.html#.Vi3Ren4vfwM (so my code shares a striking resemblance to his/hers). 稍微用谷歌搜索引导我到http://www.compiletimeerror.com/2013/08/android-call-state-listener-example.html#.Vi3Ren4vfwM (所以我的代码与他/她的代码有着惊人的相似之处)。
My main (and only) activity looks like this: 我的主要(也是唯一)活动如下所示:
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.view.Menu;
import android.widget.Toast;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TelephonyManager TelephonyMgr = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
TelephonyMgr.listen(new TeleListener(),
PhoneStateListener.LISTEN_CALL_STATE);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
class TeleListener extends PhoneStateListener {
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:
// CALL_STATE_IDLE;
Log.d("MyLittleDebugger", "I'm in " + state + " and the number is " + incomingNumber);
Toast.makeText(getApplicationContext(), "CALL_STATE_IDLE",
Toast.LENGTH_LONG).show();
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
// CALL_STATE_OFFHOOK;
Log.d("MyLittleDebugger", "I'm in " + state + " and the number is " + incomingNumber);
Toast.makeText(getApplicationContext(), "CALL_STATE_OFFHOOK",
Toast.LENGTH_LONG).show();
break;
case TelephonyManager.CALL_STATE_RINGING:
// CALL_STATE_RINGING
Log.d("MyLittleDebugger", "I'm in " + state + " and the number is " + incomingNumber);
Toast.makeText(getApplicationContext(), incomingNumber,
Toast.LENGTH_LONG).show();
Toast.makeText(getApplicationContext(), "CALL_STATE_RINGING",
Toast.LENGTH_LONG).show();
break;
default:
break;
}
}
}
}
Now, here's where the fun stops. 现在,这里的乐趣停止了。 I got the app running on emulator, and used
DDMS
to spoof a few phone calls to my emulated device to see where the pieces landed. 我让应用程序在模拟器上运行,并使用
DDMS
欺骗我的模拟设备的几个电话,以查看碎片落在哪里。
And surely enough toast popped up and MyLittleDebugger
flared up upon state swaps. 肯定有足够的吐司出现,
MyLittleDebugger
在州交换中爆发。 The listener was working, however no number was ever being shown in my log or my toast. 听众正在工作,但我的日志或吐司中没有显示任何数字。
It was just blank where the number should have been! 这个数字应该是空白的! Not null or anything, no, but blank!
不是空或任何东西,不,但空白!
After a little more googling, I realized that my AndroidManifest.xml
might be the problem. 经过一番谷歌搜索,我意识到我的
AndroidManifest.xml
可能是问题所在。 It is as follows: 它如下:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.x.xy" >
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme" >
<activity android:name=".MainActivity" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
Now, here's the question: what am I missing? 现在,问题是:我错过了什么?
Clearly, a little fraction of a something has gone wrong somewhere, because I am able to have my TelephonyMgr
object .listen()
to call states, but I can't get the number to show. 很明显,某个地方的一小部分在某个地方出了问题,因为我可以让我的
TelephonyMgr
对象.listen()
来调用状态,但我无法得到要显示的数字。
New information: 新的信息:
I've also tried this on my phone, without emulating to the exact same result. 我也在手机上试过这个,但没有仿真到完全相同的结果。
You probably need to make use of broadcast receiver which may help you what you trying to achieve. 您可能需要使用广播接收器,它可以帮助您实现您想要实现的目标。 create class extending broadcast receiver and in that try to catch the incoming number.
创建类扩展广播接收器,并尝试捕获传入的数字。
public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(final Context context, Intent intent) {
TelephonyManager mtelephony = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
mtelephony.listen(new PhoneStateListener(){
@Override
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
// CALL_STATE_RINGING
Log.d("MyLittleDebugger", "I'm in " + state + " and the number is " + incomingNumber);
Toast.makeText(getApplicationContext(), incomingNumber,
Toast.LENGTH_LONG).show();
Toast.makeText(getApplicationContext(), "CALL_STATE_RINGING",
Toast.LENGTH_LONG).show();
break;
default:
break;
}
}
},PhoneStateListener.LISTEN_CALL_STATE);
}
and in your manifest this line as well. 在你的清单中也是这一行。
<receiver android:name=".MyReceiver" >
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
I haven't used the listen
function of TelephonyManager
, but I did successfully use a BroadcastReceiver for getting the phone state changes and the phone number. 我没有使用
TelephonyManager
的listen
功能,但我成功使用BroadcastReceiver来获取手机状态更改和电话号码。
Register your receiver in the Activity or in the Manifest (if you want to receive updates when the app is in background): 在活动或清单中注册您的接收者(如果您希望在应用程序处于后台时接收更新):
Activity: 活动:
@Override
protected void onResume() {
super.onResume();
BroadcastReceiver receiver = new PhoneStateBroadcastReceiver();
IntentFilter filter= new IntentFilter();
filter.addAction("android.intent.action.PHONE_STATE");
filter.addAction("android.intent.action.NEW_OUTGOING_CALL");
registerReceiver(reciever, filter);
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(reciever);
}
Manifest: 表现:
<receiver
android:name=".PhoneStateBroadcastReceiver"
android:permission="android.permission.READ_PHONE_STATE" >
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
</intent-filter>
</receiver>
and a basic receiver: 和一个基本的接收者:
public class PhoneStateBroadcastReceiver extends BroadcastReceiver {
private final String TAG = getClass().getName();
private static String number = null;
@Override
public void onReceive(final Context context, final Intent intent) {
if (intent.getAction().equals(TelephonyManager.ACTION_PHONE_STATE_CHANGED)) {
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
Log.d(TAG, intent.getAction() + ", EXTRA_STATE: " + state);
// on ringing get incoming number
if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
number = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
Log.d(TAG, "EXTRA_INCOMING_NUMBER: " + number);
}
}
if (intent.getAction().equals(Intent.ACTION_NEW_OUTGOING_CALL)) {
number = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
Log.d(TAG, intent.getAction() + ", EXTRA_PHONE_NUMBER: " + number);
}
}
}
and in this SO answer you can find a nice implementation that also handles multiple calls: https://stackoverflow.com/a/15564021/348378 在这个SO答案中你可以找到一个很好的实现,也可以处理多个调用: https : //stackoverflow.com/a/15564021/348378
I would advise you to run your app on a real working phone! 我会建议你在真正的工作电话上运行你的应用程序!
There are multiple reasons why a phone number is not available on all notifications, but you stand a much better chance of there being one if the call is from a real phone network that can provide the number. 所有通知都没有电话号码的原因有很多,但如果电话号码来自可以提供号码的真实电话网络,那么您有更好的机会。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.