Android设备通话功能

时间:2011-03-04 16:59:23

标签: android android-intent

如何判断某台设备是否有能力拨打电话?

例如,我的Galaxy Tablet无法发起通话,它不是手机。我想在调用isIntentAvailable(context, Intent.ACTION_DIAL)之前检测到它。我已经尝试检查isIntentAvailable了,但这似乎不是可行的方法。

7 个答案:

答案 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会发生什么:

  • 在原生Dialer / Phone应用程序中输入电话号码,然后按“呼叫”。
  • 弹出窗口标题为“使用完整操作”并提供“拨号器”或“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_TELEPHONYgetPhoneType时遇到了问题,因为两者似乎都在检查设备是否具有理论上的能力,并假设它可以在这种情况下进行调用。如果您的手机没有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;
}