web-dev-qa-db-ja.com

電話が応答または拒否されたことを検出する方法

電話が鳴っているときにアクティビティを準備することができました。電話に出るか、電話を拒否したときに、このアクティビティをキャンセルする方法を知る必要があります。EXTRA_STATE_IDLEまたはEXTRA_STATE_OFFHOOKに電話しますか?

何か案は?

マニフェスト

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

IncomingBroadcastReceiver Java Class

public class IncomingBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
        // If an incoming call arrives
        if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) { //Did my work }
24
user1163234

あなたのonReceiveで:

PhoneStateChangeListener pscl = new PhoneStateChangeListener();
TelephonyManager tm = (TelephonyManager)this.getSystemService(Context.TELEPHONY_SERVICE);
tm.listen(pscl, PhoneStateListener.LISTEN_CALL_STATE);

別のクラス:

private class PhoneStateChangeListener extends PhoneStateListener {
    public static boolean wasRinging;
    String LOG_TAG = "PhoneListener";
    @Override
    public void onCallStateChanged(int state, String incomingNumber) {
        switch(state){
            case TelephonyManager.CALL_STATE_RINGING:
                 Log.i(LOG_TAG, "RINGING");
                 wasRinging = true;
                 break;
            case TelephonyManager.CALL_STATE_OFFHOOK:
                 Log.i(LOG_TAG, "OFFHOOK");

                 if (!wasRinging) {
                     // Start your new activity
                 } else {
                     // Cancel your old activity
                 }

                 // this should be the last piece of code before the break
                 wasRinging = true;
                 break;
            case TelephonyManager.CALL_STATE_IDLE:
                 Log.i(LOG_TAG, "IDLE");
                 // this should be the last piece of code before the break
                 wasRinging = false;
                 break;
        }
    }
}

あなたがする必要があるのは、以前の状態が「鳴っている」かどうかを確認するためのコードを書くことだけです。現在の状態がアイドルで、前の状態が鳴っていた場合、それらは通話をキャンセルしました。現在の状態がオフフックで、前の状態が鳴っていた場合は、通話に応答しました。

21
Andreas

上記の答えは、発信コールの場合は完全に間違っています。 Android=では、(発信コールの場合)コールが実際に応答されたかどうかを検出する方法はありません。番号をダイヤルした瞬間、off_hook状態が発生しました。これはAndroidプログラミングの欠点の1つです。

25
kkreddy

以下は、さまざまなシナリオで発生する状態です。

1)着信に応答する

CALL_STATE_RINGING => CALL_STATE_OFFHOOK (After Answering call) => CALL_STATE_IDLE (After End call) 

2)着信の拒否/応答なし(不在)

CALL_STATE_RINGING => CALL_STATE_IDLE (After End call)  

3)電話をかける

CALL_STATE_OFFHOOK (After dialing) => CALL_STATE_IDLE (After End call) 

コード

  int prev_state=0;


  public class CustomPhoneStateListener extends PhoneStateListener {  

        private static final String TAG = "CustomPhoneStateListener";  

        @Override  
        public void onCallStateChanged(int state, String incomingNumber){  

            if(incomingNumber!=null&&incomingNumber.length()>0) incoming_nr=incomingNumber;   

            switch(state){  
                case TelephonyManager.CALL_STATE_RINGING:  
                        Log.d(TAG, "CALL_STATE_RINGING");  
                        prev_state=state;  
                        break;  
                case TelephonyManager.CALL_STATE_OFFHOOK:  
                Log.d(TAG, "CALL_STATE_OFFHOOK");  
                prev_state=state;  
                break;  
                case TelephonyManager.CALL_STATE_IDLE:  
                    Log.d(TAG, "CALL_STATE_IDLE==>"+incoming_nr);  
                    NumberDatabase database=new NumberDatabase(mContext);  
                    if((prev_state==TelephonyManager.CALL_STATE_OFFHOOK)){  
                        prev_state=state;  
                        //Answered Call which is ended  
                    }  
                    if((prev_state==TelephonyManager.CALL_STATE_RINGING)){  
                        prev_state=state;  
                        //Rejected or Missed call  
                    }  
                    break;  

            }  
        }  
    }  

あなたの受信機で

onReceive(Context context, Intent intent) {  
        TelephonyManager telephony = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE); //TelephonyManager object  
        CustomPhoneStateListener customPhoneListener = new CustomPhoneStateListener();  
        telephony.listen(customPhoneListener, PhoneStateListener.LISTEN_CALL_STATE);          //Register our listener with TelephonyManager  

        Bundle bundle = intent.getExtras();  
        String phoneNr= bundle.getString("incoming_number");  

        mContext=context;  
 }  
7
Karthi

以下は、アクセシビリティイベントによって発信を検出するコードです-

プロジェクトにAccessibilityServiceを拡張するクラスを追加します-

_public class CallDetection extends AccessibilityService {
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
     acquireLock(this);
    Log.d("myaccess","after lock");
    if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED) {
        Log.d("myaccess","in window changed");
        AccessibilityNodeInfo info = event.getSource();
        if (info != null && info.getText() != null) {
            String duration = info.getText().toString();
            String zeroSeconds = String.format("%02d:%02d", new Object[]{Integer.valueOf(0), Integer.valueOf(0)});
            String firstSecond = String.format("%02d:%02d", new Object[]{Integer.valueOf(0), Integer.valueOf(1)});
            Log.d("myaccess","after calculation - "+ zeroSeconds + " --- "+ firstSecond + " --- " + duration);
            if (zeroSeconds.equals(duration) || firstSecond.equals(duration)) {
                Toast.makeText(getApplicationContext(),"Call answered",Toast.LENGTH_SHORT).show();
               // Your Code goes here
            }
            info.recycle();
        }
    }
}


@Override
protected void onServiceConnected() {
    super.onServiceConnected();
    Toast.makeText(this,"Service connected",Toast.LENGTH_SHORT).show();
    AccessibilityServiceInfo info = new AccessibilityServiceInfo();
    info.eventTypes = AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED;
    info.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;
    info.notificationTimeout = 0;
    info.packageNames = null;
    setServiceInfo(info);
}

@Override
public void onInterrupt() {

}
}
_

ただし、関数event.getSource()を機能させるには、xmlを使用してサービス構成の一部を指定する必要があるため、プロジェクトにxmlフォルダーを作成し、-と呼ばれるxmlファイルを追加します。 serviceconfig.xml(任意の名前を付けることができます。

Serviceconfigの内容は次のとおりです-

_<accessibility-service xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:description="@string/callDetection"
Android:accessibilityEventTypes="typeWindowContentChanged"
Android:notificationTimeout="100"
Android:canRetrieveWindowContent="true"
/>
_

serviceconfigの詳細については ここ を参照してください

今あなたのサービスをあなたに追加してくださいManifestこのようなファイル-

_<service Android:name=".CallDetection"
        Android:permission="Android.permission.BIND_ACCESSIBILITY_SERVICE"
        Android:label="@string/callDetection">
        <intent-filter>
            <action Android:name="Android.accessibilityservice.AccessibilityService" />
        </intent-filter>
        <meta-data
            Android:name="Android.accessibilityservice"
            Android:resource="@xml/serviceconfig" />
</service>
_

完了したら、アプリを実行して携帯電話のAccessibility settingsに移動すると、detectionまたは任意の名前のオプションが見つかりますサービスの説明として指定した場合)、スイッチをオンにして、アプリにアクセス許可を付与します。

これで、通話に応答するとトーストが表示されます。

そこに必要なコードをコーディングできます。また、アクティビティでコールバック関数を呼び出すこともできます

最も重要-通話に応答するまで、通話ウィンドウ(Androidダイヤラウィンドウ)を呼び出さないでください。そうしないと、機能しません。

-Androidは、通話が応答されたかどうかを検出するためのソリューションを提供していません。これは私が行った最良の代替手段です。それがあなたのために機能することを願っています。

1
kaustav07