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) 

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

  1. Preinstalado en una carpeta del sistema en la ROM
  2. 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í .

  • Soporte de difusión celular en Android?
  • La aplicación Messenger de Google no adjunta Imagen mientras envía MMS
  • ¿Es posible reenviar la llamada VoiP a GSM
  • Broadcastreceiver para obtener información de ServiceState
  • Volver automáticamente a la anterior aplicación de SMS predeterminada
  • ¿Cómo saber si estoy conectado correctamente a mi número de salida en Android?
  • Cómo recuperar llamadas perdidas en Android SDK 2.2
  • Métodos de reflexión no funcionan cuando se utiliza proguard para la aplicación de Android
  • Recibir SMS Intent: Obtener identificación de mensaje o de hilo
  • ¿Cómo comprobar el número de teléfono propio introducido por el usuario en EditText?
  • Android DDMS: envía llamadas al dispositivo actual
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.