Cómo conceder el permiso de MODIFY_PHONE_STATE para las aplicaciones que se ejecutan en Gingerbread
Escribo una aplicación que intenta modificar el estado de la llamada telefónica. Funciona bien en Android 2.2 o menos, pero lanzar una excepción en Android 2.3 debido a la falta de permiso en android.permission.MODIFY_PHONE_STATE permiso (declaré este permiso en AndroidManifest.xml). ¿Alguna idea? A continuación se muestra el registro de excepciones:
01-15 09:14:23.210: ERROR/AndroidRuntime(404): FATAL EXCEPTION: main 01-15 09:14:23.210: ERROR/AndroidRuntime(404): java.lang.RuntimeException: Unable to start receiver test.PhoneReceiver: java.lang.SecurityException: Neither user 10031 nor current process has android.permission.MODIFY_PHONE_STATE. 01-15 09:14:23.210: ERROR/AndroidRuntime(404): at android.app.ActivityThread.handleReceiver(ActivityThread.java:1780) 01-15 09:14:23.210: ERROR/AndroidRuntime(404): at android.app.ActivityThread.access$2400(ActivityThread.java:117) 01-15 09:14:23.210: ERROR/AndroidRuntime(404): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:978) 01-15 09:14:23.210: ERROR/AndroidRuntime(404): at android.os.Handler.dispatchMessage(Handler.java:99) 01-15 09:14:23.210: ERROR/AndroidRuntime(404): at android.os.Looper.loop(Looper.java:123) 01-15 09:14:23.210: ERROR/AndroidRuntime(404): at android.app.ActivityThread.main(ActivityThread.java:3647) 01-15 09:14:23.210: ERROR/AndroidRuntime(404): at java.lang.reflect.Method.invokeNative(Native Method) 01-15 09:14:23.210: ERROR/AndroidRuntime(404): at java.lang.reflect.Method.invoke(Method.java:507) 01-15 09:14:23.210: ERROR/AndroidRuntime(404): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839) 01-15 09:14:23.210: ERROR/AndroidRuntime(404): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597) 01-15 09:14:23.210: ERROR/AndroidRuntime(404): at dalvik.system.NativeStart.main(Native Method)
- Envío de tonos DTMF sobre el enlace ascendente en llamada
- ¿Cómo puedo agregar una opción al realizar una llamada saliente?
- ¿Cómo saber si se ha establecido una llamada?
- Llamada entrante falsa en un dispositivo Android
- Cómo detectar cuándo se responde o se rechaza el teléfono
- Detectar si se ha contestado una llamada saliente
- Detectar si se ha contestado una llamada saliente
- ¿Cómo puedo detectar en Android que el número que estoy llamando (desde el código) está ocupado
- Estado de la llamada telefónica
- ¿Cómo obtengo el estado de una llamada saliente en un teléfono Android?
- ¿Detectar el número de teléfono de destino en la llamada entrante es para SIM 1 o para SIM 2?
- No hay función de telefonía en AVD con soporte GSM
- ¿Hay alguna forma de terminar una llamada en Android 2.3?
MODIFY_PHONE_STATE es un permiso sólo de sistema, por lo que las aplicaciones no están permitidas para obtenerlo.
Esto puede haber cambiado de las versiones anteriores de la plataforma, pero eso está bien porque sólo protege las API privadas, por lo que si está haciendo algo que lo requiere, está utilizando APIs privadas que no son compatibles y resultarán en cosas como su aplicación. Rompiendo en diferentes construcciones de la plataforma.
El rastreo de la pila que incluye no está completo, por lo que no hay manera de saber lo que está haciendo realmente.
El problema que está teniendo se introdujo en Android 2.3 (Gingerbread). Cualquier código que tengas que requiera MODIFY_PHONE_STATE funcionará hasta el Android 2.2 (y incluido), pero se romperá para Android 2.3 o superior.
Un cambio fue comprobado por David Brown que limita el uso del permiso de MODIFY_PHONE_STATE a las aplicaciones del sistema. Las aplicaciones del sistema son
- Preinstalado en una carpeta del sistema en la ROM
- Compilado por un fabricante utilizando su certificado de seguridad
Sospecho que estás intentando usar una API oculta como ITelephony. Yo estaba … y me quemé por este cambio. La justificación del equipo de Android es que era una API oculta que no deberías haber estado utilizando en primer lugar.
Dicho esto, hubo una solicitud de mejora abierta para crear una API de telefonía pública adecuada, pero Google mató el boleto. Parece que su postura es que no tienen la intención de invertir la dirección y estas API no son para consumo público.
Prueba esto.
public static void answerPhoneHeadsethook(Context context) { // Simulate a press of the headset button to pick up the call // SettingsClass.logMe(tag, "Simulating headset button"); Intent buttonDown = new Intent(Intent.ACTION_MEDIA_BUTTON); buttonDown.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_HEADSETHOOK)); context.sendOrderedBroadcast(buttonDown, "android.permission.CALL_PRIVILEGED"); // froyo and beyond trigger on buttonUp instead of buttonDown Intent buttonUp = new Intent(Intent.ACTION_MEDIA_BUTTON); buttonUp.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_HEADSETHOOK)); context.sendOrderedBroadcast(buttonUp, "android.permission.CALL_PRIVILEGED"); }
Tengo la solución.
Más bien para reemplazar la pantalla de llamadas entrantes, haga por debajo de dos cosas. Que le permitirá acceder al botón de aceptar y rechazar y también le permitirá mostrar la pantalla por encima de su pantalla de llamadas entrantes.
(1) Hacer una clase de receptor:
public class MyPhoneReceiver extends BroadcastReceiver { @Override public void onReceive(final Context context, final Intent intent) { Bundle extras = intent.getExtras(); if (extras != null) { String state = extras.getString(TelephonyManager.EXTRA_STATE); if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) String phoneNumber = extras.getString(TelephonyManager.EXTRA_INCOMING_NUMBER); Intent i = new Intent(context, IncomingCallActivity.class); i.putExtras(intent); i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(i); } } }
(2) su actividad xml se parece a:
RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_gravity="top" android:gravity="top" android:orientation="vertical" android:windowAnimationStyle="@android:style/Animation.Translucent" android:windowBackground="@android:color/transparent" android:windowIsTranslucent="true"
(3) Haga que el diseño de su actividad sea transparente (lo que vendrá por encima de la pantalla de llamadas), escriba el código abajo en menifest
<activity android:name=".IncomingCallActivity" android:theme="@android:style/Theme.Translucent"> </activity>
(4) En menifest agregue su receptor ancho del molde
<receiver android:name="MyPhoneReceiver" > <intent-filter> <action android:name="android.intent.action.PHONE_STATE" > </action> </intent-filter> </receiver>
(5) añada el siguiente código en oncreate () de IncomingCallActivity
getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE); getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL); this.requestWindowFeature(Window.FEATURE_NO_TITLE);
¡Aclamaciones!
¡Déjeme saber si usted hace frente a cualquier problema!
Si su aplicación para Gingerbread se está ejecutando en una tableta y no hay teléfono, entonces este es el comportamiento esperado. Tendrá que hacer que los permisos relacionados con la telefonía en su manifiesto no sean obligatorios para ejecutarse en tablets.
Intente esto en su manifiesto:
<uses-feature android:name="android.hardware.telephony" android:required="false" />
Por supuesto, estoy haciendo un gran supuesto sobre la tableta. También puedes ver la referencia de Android aquí .
- Cómo hacer el código QR para AMBOS Android Market y App Store
- Admob obtener una respuesta de anuncio. ErrorCode: 0 Error al cargar anuncio: 0