如何判断某台设备是否有能力拨打电话?
例如,我的Galaxy Tablet无法发起通话,它不是手机。我想在调用isIntentAvailable(context, Intent.ACTION_DIAL)
之前检测到它。我已经尝试检查isIntentAvailable
了,但这似乎不是可行的方法。
答案 0 :(得分:49)
if (((TelephonyManager)getContext().getSystemService(Context.TELEPHONY_SERVICE)).getPhoneType()
== TelephonyManager.PHONE_TYPE_NONE)
{
// no phone
}
编辑我很惊讶它回来PHONE_TYPE_CDMA
。这是另一种可能性:
if (((TelephonyManager)getContext().getSystemService(Context.TELEPHONY_SERVICE)).getLine1Number()
== null)
{
// no phone
}
这需要READ_PHONE_STATE
权限。
答案 1 :(得分:30)
设备不一定需要Context.TELEPHONY_SERVICE
才能拨打电话。考虑一下如果安装Skype会发生什么:
所以,我相信Skype可以在没有手机功能的无线设备上工作(根据Context.TELEPHONY_SERVICE
)。
我认为您的原始想法是正确的,但您需要检查注册哪些应用程序来处理Intent.ACTION_CALL
而不是Intent.ACTION_DIAL
,例如。
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setData(Uri.parse("tel:5551231234"));
List<ResolveInfo> callAppsList =
context.getPackageManager().queryIntentActivities(callIntent, 0);
但是,我不知道有任何可靠的,前瞻性的方法来确定这些应用程序是否能够处理电话呼叫。考虑以下情况:
1)安装了Skype的仅限wifi的Xoom。它需要有效的WiFi连接,并且用户必须已配置Skype才能使用其帐户,否则呼叫将无法成功。
2)未启用SIM卡的电话启用设备,或已锁定或已用完的SIM卡。设备认为它可以处理电话,但是呼叫导致“未在网络上注册”错误。
3)启用电话的设备没有wifi或移动连接(或者因为它处于飞机/飞行模式)。设备认为它可以处理电话,但呼叫将失败。
有一些方法可以检测到其中一些情况(例如检查getSystemService(Context.TELEPHONY_SERVICE).getSimState()
),但我认为这可能会导致脆弱的代码在未来发生变化时可能会中断。例如,您是否可以始终可靠地检测列表中的哪个应用程序是默认的拨号器/电话应用程序?如果Android在后续版本中更改了其名称,该怎么办?
希望这能为您提供一些有用的信息 - 我想表明,乍看起来可能更为棘手!
答案 2 :(得分:23)
我认为更好的方法是查询PackageManager以检测设备上是否还有Telephony功能。如果设备有电话,则设备应该只具有电话功能。我在没有手机的Nexus 7上进行了测试,但它确实有效。我没有配备手机的设备来测试相反的情况。
PackageManager pm = getPackageManager();
if (pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)){
//has Telephony features.
}
答案 3 :(得分:4)
史蒂夫,
结帐TelephonyManager
。它具有getPhoneType()
函数,在您的情况下将返回PHONE_TYPE_NONE
。
答案 4 :(得分:2)
这些解决方案中的大多数/所有解决方案都适用于某些情况,但不是全部。
正如@DanJ所说。没有简单的方法来实现这一目标。
我在检查PackageManager.FEATURE_TELEPHONY
和getPhoneType
时遇到了问题,因为两者似乎都在检查设备是否具有理论上的能力,并假设它可以在这种情况下进行调用。如果您的手机没有SIM卡,可能会中断,如果您没有覆盖/超出范围,则可能会中断。检查哪些应用程序可以处理呼叫的方法也是如此,因为手机应用程序仍然安装,但是当没有SIM卡时,它会中断(至少在我的galaxy s3上)。
但是,在大多数情况下,有一次检查可以让我在我看来工作,那就是检查你的电话subscriberId
,基本上是&#34;名称/ ID是什么您的网络提供商&#34;。
你可以这样做:
if(((TelephonyManager)getContext()
.getSystemService(Context.TELEPHONY_SERVICE))
.getSubscriberId() == null) {
//No network id ~= can't make calls
}
我们在这里检查我们是否没有网络,因此可以安全地#34;假设设备无法拨打电话。在您拥有VoIP电话或安装了类似Skype的情况下,这种方法会产生误报。
此方法要求您添加权限:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
@ TedHopp的解决方案需要READ_SMS
权限,这对我来说似乎更具侵入性。
哦,我希望phone.canMakeCallsWithoutCrashing()
是android api中的一个东西。
答案 5 :(得分:2)
您只能分别检查 TELEPHONY 功能或 GSM 和 CDMA :
private boolean hasTelephony() {
return getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
}
或
private boolean hasGsmOrCdma() {
PackageManager pm = getPackageManager();
boolean gsmSupported = pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_GSM);
boolean cdmaSupported = pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_CDMA);
//if necessary write somehow what exactly the devise supports
return gsmSupported || cdmaSupported;
}
运作良好!
答案 6 :(得分:0)
我还没有检查过这个,但这是我提出的解决方案,似乎应该可以正常工作。我认为这不需要任何特殊许可,因为它只是寻找制造商设定的bool。
static boolean isRunningOnPhone(Context context){
UiModeManager uiModeManager = (UiModeManager) context.getSystemService(UI_MODE_SERVICE);
PackageManager packageManager = context.getPackageManager();
boolean a = packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
boolean b = packageManager.hasSystemFeature(PackageManager.FEATURE_SIP_VOIP) || context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY_CDMA) || context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY_CDMA);
boolean c = packageManager.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN);
boolean d;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
d = packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
}else {
d = !(uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_CAR);
}
boolean e = !(uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION);
boolean f = uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_APPLIANCE;
boolean g = true;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
g = !(uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_WATCH);
}
return a && b && c && d && e && f && g;
}