くらげになりたい。

くらげのようにふわふわ生きたい日曜プログラマなブログ。趣味の備忘録です。

Androidで電話の発信・切断・状態の確認

Androidで電話を操作するアプリを作る機会があったので、その時の備忘録。

発信する

  • 発信する場合は簡単。Intentを発行するだけでOK。
Context context = ...;
String phoneNumber = "090-0000-9999"
Uri uri = Uri.parse("tel:" + phoneNumber);
Intent intent = new Intent(Intent.ACTION_CALL, uri);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // Activity以外から呼ぶ場合に必要
context.startActivity(intent);

切断する

  • 切断する場合は、APIが公開されていないため、複雑
  • 非公開APIなので、今後使えなくなる可能性もある
  • また、電話を扱う場合は、パーミッションも必要
<uses-permission android:name="android.permission.CALL_PHONE"/>

1. 非公開インターフェースITelephonyを自前で用意する

package com.android.internal.telephony;

public interface ITelephony {
    boolean endCall(); // 切断
    void answerRingingCall(); // 応答
    void silenceRinger(); // 着信音を消す
}

2. リフレクションを使って、ITelephonyのインスタンスを取得

// TelephonyManagerを取得
TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);

// protectedなTelephonyManager.getITelephony()のアクセス修飾子を変更して、呼び出す
Class<?> c = Class.forName(telephonyManager.getClass().getName());
Method m = c.getDeclaredMethod("getITelephony");
m.setAccessible(true);
ITelephony telephony = (ITelephony) m.invoke(telephonyManager);

3. 取得したITelephonyのインスタンスで切断

telephony.endCall(); // 切断

TelephonyManagerまではソースが見れるので、そこからいろいろ見てみると良いかも。

電話の状態を確認する

  • PhoneStateListenerが用意されているので、extendする
  • 電話番号も取得したい場合には、パーミッションが必要
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
  • 電話の状態を確認するには、PhoneStateListenerのonCallStateChangedをOverrideする
// TelephonyManagerを取得
TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);

// listenerを登録
telephonyManager.listen(new PhoneStateListener(){
    // PhoneStateListenerの`onCallStateChanged`をOverride
    @Override
    public void onCallStateChanged(int state, String incomingNumber) {
        // パーミッションがない場合、incomingNumberは常に空
        switch (state) {
          case TelephonyManager.CALL_STATE_RINGING:
            /* 着信 */
            Log.i(TAG, "Call State Changed: CALL_STATE_RINGING");
            break;
        case TelephonyManager.CALL_STATE_OFFHOOK:
            /* 通話 */
            Log.i(TAG, "Call State Changed: CALL_STATE_OFFHOOK");
            break;
        case TelephonyManager.CALL_STATE_IDLE:
            /* 待受 */
            Log.i(TAG, "Call State Changed: CALL_STATE_IDLE");
            break;
        }
    }
}, PhoneStateListener.LISTEN_CALL_STATE);

以上!!

参考にしたサイト様