web-dev-qa-db-ja.com

Gingerbreadで実行されたアプリにMODIFY_PHONE_STATE権限を付与する方法

電話の状態を変更しようとするアプリケーションを作成します。 Android 2.2以下で動作しますが、Android.permission.MODIFY_PHONE_STATE権限の許可がないため、Android 2.3で例外をスローします(私は宣言しましたAndroidManifest.xmlでのこのアクセス許可)何か考えがありますか?以下は例外ログです:

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)
37
Bao Le

MODIFY_PHONE_STATEはシステムのみの権限であるため、アプリは取得できません。

これはプラットフォームの以前のバージョンから変更された可能性がありますが、プライベートAPIのみを保護しているため、問題ありませんプラットフォームのさまざまなビルドを壊します。

含めたスタッククロールは完全ではないため、実際に何をしているかを知る方法はありません。

21
hackbod

あなたが抱えている問題はAndroid 2.3(Gingerbread)で導入されました。 MODIFY_PHONE_STATEを必要とするコードは、Android 2.2までは動作しますが、Android 2.3+では機能しなくなります。

変更がチェックインされました David Brownにより、MODIFY_PHONE_STATE権限の使用をシステムアプリに制限します。システムアプリは

  1. ROMのシステムフォルダーにプリインストールされています
  2. メーカーがセキュリティ証明書を使用してコンパイル

ITelephonyのような隠されたAPIを使用しようとしているのではないでしょうか。私はそうでした-そして、私はこの変化によって燃えました。 Androidチームの正当性は、そもそもそれを使用してはいけない隠されたAPIだったということです。

とは言っても、適切なパブリックテレフォニーAPIを作成するために 拡張要求 が開かれましたが、Googleはチケットを殺しました。彼らのスタンスは、彼らが方向を逆にするつもりはないということであり、これらのAPIは一般消費向けではないようです。

55
Skylar Sutton

これを試して。

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
user1163234

私は解決策を得た。

着信画面をオーバーライドするには、次の2つのことを行います。これにより、承諾ボタンと拒否ボタンにアクセスしたり、着信画面の上に画面を表示したりできます。

(1)1つのレシーバークラスを作成します。

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)アクティビティxmlは次のようになります。

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)アクティビティのレイアウトを透明にする(これは呼び出し画面の上に来る)、メニフェストのコードの下に書く

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

(4)メニフェストで、ブロードキャストレシーバーを追加します

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

(5)IncomingCallActivityのoncreate()に以下のコードを追加します

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

乾杯!

問題が発生した場合はお知らせください!

5
Dhrupal