Comment accorder la permission de modifier L'état du téléphone pour les applications lancées sur Gingerbread

j'écris une application qui tente de modifier l'état de l'appel téléphonique. Il fonctionne bien sur Android 2.2 ou moins, mais jeter une exception sur Android 2.3 en raison du manque de permission sur android.autorisation.MODIFY_PHONE_STATE permission (j'ai déclaré Cette permission sur AndroidManifest.XML.) Une idée? Ci-dessous est l'exception log:

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.access00(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)
37
demandé sur Bao Le 2011-01-17 19:10:10

5 réponses

MODIFY_PHONE_STATE est une permission système seulement, donc les applications ne sont pas autorisées à l'obtenir.

cela peut avoir changé par rapport aux versions précédentes de la plate-forme, mais c'est correct car cela ne protège que les API privées, donc si vous faites quelque chose qui l'exige, vous utilisez des API privées qui ne sont pas supportées et qui entraîneront des choses comme le bris de votre application sur différentes versions de la plate-forme.

le rampement de la pile que vous incluez n'est pas complet, donc il n'y a aucun moyen pour dire ce que vous êtes en train de faire.

21
répondu hackbod 2012-03-06 22:45:13

le problème que vous avez a été introduit dans Android 2.3 (Gingerbread). Tout code que vous avez qui nécessite MODIFY_PHONE_STATE fonctionnera jusqu'à (et incluant) Android 2.2, mais se brisera pour Android 2.3+.

le changement a été enregistré dans par David Brown, qui limite l'utilisation de la MODIFY_PHONE_STATE la permission de système d'applications. Les applications système sont soit

  1. préinstallé dans un dossier système sur la ROM
  2. Compilé par un fabricant utilisant leur certificat de sécurité

je soupçonne que vous essayez d'utiliser une API cachée comme ITelephony. J'étais-et j'ai été grillé par ce changement. La justification de L'équipe Android est que c'était une API cachée que vous n'auriez pas dû utiliser en premier lieu.

cela dit, il y a une demande d'amélioration ouvert pour créer une API de téléphonie publique correcte, mais Google a tué le ticket. Il semble que leur position est qu' ils n'ont pas l'intention d'inverser la direction et ces IPA ne sont pas destinés à la consommation publique.

55
répondu Skylar Sutton 2017-01-20 14:17:09

Essayez ceci.

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");
}
6
répondu user1163234 2012-03-14 12:03:29

j'ai la solution.

plutôt que d'outrepasser l'écran d'appel entrant, faites deux choses ci-dessous. qui vous permettra d'accéder à accepter et refuser des bouton et vous permettent également d'afficher l'écran au-dessus de votre écran d'appel entrant.

(1) Faire une classe de récepteur:

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) votre activité xml ressembler à ç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) rendre la mise en page transparente de votre activité(qui sera placée au-dessus de l'écran appelant), écrire le code ci-dessous menifest

<activity android:name=".IncomingCallActivity" 
         android:theme="@android:style/Theme.Translucent">
</activity>

(4)Dans menifest ajouter votre exprimés large récepteur

<receiver android:name="MyPhoneReceiver" >
        <intent-filter>
            <action android:name="android.intent.action.PHONE_STATE" >
            </action>
        </intent-filter>
</receiver>

(5) Ajouter ci-dessous le code dans oncreate() de L'activité de revenu

getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);

Cheers!

faites - moi savoir si vous avez un problème!

5
répondu Dhrupal 2013-07-19 08:52:52

si votre application pour Gingerbread est en cours d'exécution sur une tablette et il n'y a pas de téléphone, alors c'est Comportement attendu. Vous aurez besoin de rendre les permissions liées à la téléphonie dans votre manifeste non-obligatoire pour fonctionner sur des tablettes.

essayez ceci dans votre manifeste:

<uses-feature android:name="android.hardware.telephony" 
    android:required="false" />

bien sûr, je fais une grande supposition à propos de la tablette. Vous pouvez également voir la référence Android ici.

-3
répondu Jerry Brady 2011-08-04 15:04:36