Capacidad de llamadas telefónicas del dispositivo Android

¿Cómo puedo saber si un dispositivo determinado tiene la capacidad de hacer llamadas telefónicas?

Por ejemplo, mi Galaxy Tablet no puede, no es un teléfono. Quiero detectar eso antes de hacer una llamada a isIntentAvailable(context, Intent.ACTION_DIAL) . He intentado comprobar el isIntentAvailable para esto, pero eso no parece ser la manera de ir.

 if (((TelephonyManager)getContext().getSystemService(Context.TELEPHONY_SERVICE)).getPhoneType() == TelephonyManager.PHONE_TYPE_NONE) { // no phone } 

EDIT Me sorprende que vuelva PHONE_TYPE_CDMA . He aquí otra posibilidad:

 if (((TelephonyManager)getContext().getSystemService(Context.TELEPHONY_SERVICE)).getLine1Number() == null) { // no phone } 

Esto requerirá el permiso READ_PHONE_STATE .

Los dispositivos no necesariamente necesitan Context.TELEPHONY_SERVICE para realizar llamadas telefónicas. Considere lo que sucede si instala Skype:

  • Ingrese un número de teléfono en la aplicación Dialer / Phone nativa y presione "Call".
  • Aparecerá una ventana emergente titulada "Acción completa utilizando" y que ofrece aplicaciones "Marcador" o "Skype" (podría incluir otras aplicaciones también).

Por lo tanto, creo que Skype funcionaría en un dispositivo wifi-only sin capacidades de teléfono (de acuerdo con Context.TELEPHONY_SERVICE ).

Creo que estaba correcto con su idea original, pero debe comprobar qué aplicaciones están registradas para manejar Intent.ACTION_CALL lugar de Intent.ACTION_DIAL , por ejemplo

 Intent callIntent = new Intent(Intent.ACTION_CALL); callIntent.setData(Uri.parse("tel:5551231234")); List<ResolveInfo> callAppsList = context.getPackageManager().queryIntentActivities(callIntent, 0); 

Sin embargo, no soy consciente de ninguna manera fiable, a prueba de futuro para averiguar si esas aplicaciones serán capaces de manejar la llamada telefónica. Considere estos casos:

1) Un Xoom wifi-only con Skype instalado. Necesita una conexión wifi válida, y el usuario debe haber configurado Skype para usar su cuenta, de lo contrario la llamada no tendrá éxito.

2) Un dispositivo habilitado para telefonía sin tarjeta SIM o una tarjeta SIM bloqueada o agotada. El dispositivo piensa que puede manejar la telefonía, pero la llamada da como resultado un error "No registrado en la red".

3) Un dispositivo habilitado para telefonía sin conexión wifi o móvil (o porque está en modo Avión / Vuelo). El dispositivo piensa que puede manejar la telefonía, pero la llamada fallará.

Hay formas de detectar algunos de estos escenarios (por ejemplo, inspeccionar getSystemService(Context.TELEPHONY_SERVICE).getSimState() ), pero creo que esto probablemente conduciría a código frágil que podría romperse cuando las cosas cambien en el futuro. Por ejemplo, ¿podría detectar siempre de forma fiable qué aplicación de la lista es la aplicación de marcación / teléfono predeterminada? ¿Qué pasa si Android cambió el nombre del paquete para ello en una versión posterior.

Esperemos que le dio alguna información útil – quería mostrar esto es más complicado que podría aparecer a primera vista!

Creo que un mejor enfoque sería consultar el PackageManager para detectar si las funciones de telefonía están incluso disponibles en el dispositivo. Un dispositivo sólo debe tener funciones de telefonía si tiene un teléfono. He probado esto en un Nexus 7, que no tiene un teléfono, y funciona. No tengo un dispositivo con un teléfono para probar el caso opuesto.

 PackageManager pm = getPackageManager(); if (pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)){ //has Telephony features. } 

Steve,

Echa un vistazo a TelephonyManager . Tiene la función getPhoneType() que devolverá PHONE_TYPE_NONE en su caso.

La mayoría de estas soluciones funcionan en algunos casos, pero no en todas.

Como indica @DanJ. No hay manera fácil de lograr esto.

Tuve problemas comprobando el PackageManager.FEATURE_TELEPHONY y el getPhoneType , porque ambos parecen comprobar si el dispositivo es capaz en teoría, y asumir que puede hacer llamadas si este es el caso. Esto se rompe si usted tiene un teléfono sin tarjeta SIM, y posiblemente si no tiene cobertura / fuera de rango. Lo mismo ocurre con el enfoque de comprobar qué aplicaciones pueden manejar una llamada, porque la aplicación de teléfono todavía está instalada, pero se romperá (al menos en mi galaxia s3) cuando no haya SIM.

Sin embargo, hay una vez verificación que puede hacer que me parece trabajar en la mayoría de los casos, y que es para comprobar subscriberId de teléfono, básicamente, "cuál es el nombre / id de su proveedor de red".

Puedes hacerlo:

 if(((TelephonyManager)getContext() .getSystemService(Context.TELEPHONY_SERVICE)) .getSubscriberId() == null) { //No network id ~= can't make calls } 

Aquí verificamos si no tenemos red, por lo tanto podemos "con seguridad" suponer que el dispositivo no puede hacer una llamada. Este enfoque da un falso negativo en el caso en que usted tiene un teléfono VoIP, o tiene algo como Skype instalado.

Este enfoque requiere que añada un permiso:

 <uses-permission android:name="android.permission.READ_PHONE_STATE" /> 

@La solución de TedHopp requiere el permiso READ_SMS que me parece más intrusivo.


Ohh cómo deseo phone.canMakeCallsWithoutCrashing() era una cosa en el api de Android.

No he comprobado esto todavía, pero aquí es una solución que surgió con que parece que debería funcionar bien. No creo que esto requiere ningún permiso especial, ya que es sólo buscando bools establecido por la fabricación.

 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; } 

Puede comprobar solo la función TELEFONÍA o GSM y CDMA por separado:

 private boolean hasTelephony() { return getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY); } 

o

 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; } 

¡funciona bien!

FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.