web-dev-qa-db-ja.com

Nougatでプログラム的に通話を受け入れる

1年目からIOT製品に取り組んでおり、付属のアプリケーションは問題なく動作していました。現在、Androidの上位バージョンでプログラム的に呼び出しを受け入れることができません。製品にとって機能は非常に重要です。どんな助けでも大歓迎です。

セキュリティパッチを更新する前2016年11月Runtime.getRunTime.exec("Command")はプログラムで呼び出しを受け入れるために正常に機能していました。

Runtime.getRuntime().exec("input keyevent " +Integer.toString(KeyEvent.KEYCODE_HEADSETHOOK));

AndroidのNougatバージョンでそれを可能にする方法。

あらゆる種類のハックを探しています。

拡張機能のスレッドを開きました。

https://code.google.com/p/Android/issues/detail?can=2&start=0&num=100&q=&colspec=ID%20Status%20Priority%20Owner%20Summary%20Stars%20Reporter%20Opened&groupby=&sort= &id = 231938

注*誰かが同じ問題に直面している場合は、Android Dev Teamにリクエストして、問題に参加し、実行するためのプロビジョニングを提供してください-ユーザーによる時間の許可。上記のURLに従ってリクエストしてください。

20
AndroidHacker

私もIOT製品に取り組んでいるため、これは私が直面した最大の問題の1つでしたが、いくつかの調査の後、この問題の解決策を見つけたと思います。または、簡単なハックと言えます。私はいくつかのバージョンのいくつかのデバイスでこのハックをテストしましたが、ほとんどのデバイスが応答しています。 Samsungデバイスのみが応答せず、一部のHuaweiデバイスと一部のOppoデバイスも応答しません(これらのデバイスについてもまだ探しています)。

Androidは通知へのアクセスの1つの機能を提供します。NotificationListenerServiceを使用して通知を読み取り、それらに対していくつかのアクションを実行できます。それはいくつかのオーバーライドメソッドを提供します:

 onNotificationPosted()
    onNotificationRemoved()
    getActiveNotifications()

...など

次にコードを示します。NotificationListenerServiceを拡張するサービスを作成します。

 class NLService extends NotificationListenerService {

     @Override
     public void onNotificationPosted(StatusBarNotification sbn) {
       ....
     }

     @Override
     public void onNotificationRemoved(StatusBarNotification sbn) {
       ....
     }

AndroidMenifestで、このサービスを次のように追加します。

 <service
        Android:name=".NLService"
        Android:label="@string/app_name"
Android:permission="Android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
        <intent-filter>
            <action 
Android:name="Android.service.notification.NotificationListenerService" />
        </intent-filter>
    </service>

これにより、アプリケーションは受信した通知を読み取ることができます。

今、ここにメインコードがあります:

OnNotificationPosted(StatusBarNotification sbn)に次のコードを追加します。

 @Override
    public void onNotificationPosted(StatusBarNotification sbn) {
        try {
            if (sbn.getNotification().actions != null) {
                for (Notification.Action action : sbn.getNotification().actions) 
                  {
                    Log.e(TAG, "" + action.title);
                    if (action.title.toString().equalsIgnoreCase("Answer")) {
                        Log.e(TAG, "" + true);
                        PendingIntent intent = action.actionIntent;

                        try {
                            intent.send();
                        } catch (PendingIntent.CanceledException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
          } catch (Exception e) {
              e.printStackTrace();
          }
     }

それでおしまい!

すべてが設定されています。アプリケーションを実行し、Samsungを除くデバイスのいずれかで、[応答]ボタンと[拒否/拒否アクション]ボタンを使用して着信の通知を表示すると、通話に応答できます。

通知アクセス設定を開き、アプリケーションが通知を読み取れるようにするには、以下を使用します。

 Intent intent = new 
    Intent("Android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");
        startActivity(intent); 

このためのPOCを作成し、それがどのように機能するかを知らせてください。

これが役立つ場合は、私の答えにマークを付けてください。

また、Samsungデバイスに関して同じ解決策を提供できる場合は、更新してください。

ありがとう

9
Vishal Sharma

それは一種のハックです、あなたは電話を受けるために アクセシビリティサービス を使うことができます。アクセシビリティサービスを有効にするには、設定-アクセシビリティ-サービスでサービスを有効にする必要があります。

まず、typeWindowContentChangedをaccessibilityEventTypesに追加します。

<accessibility-service
     Android:accessibilityEventTypes="typeViewClicked|typeViewFocused|typeViewScrolled|typeWindowContentChanged|typeWindowStateChanged"
     Android:packageNames="com.example.Android.myFirstApp, com.example.Android.mySecondApp"
     Android:accessibilityFeedbackType="feedbackSpoken"
     Android:notificationTimeout="100"
     Android:settingsActivity="com.example.Android.apis.accessibility.TestBackActivity"
     Android:canRetrieveWindowContent="true"
/>

そして、イベントまたは「表示されたテキスト」または「コンテンツの説明」で何かを行います。

@Override
public void onAccessibilityEvent(AccessibilityEvent event) {

    // Do something with Click or Focused event
    final int eventType = event.getEventType();
    String eventText = null;
    switch(eventType) {
        case AccessibilityEvent.TYPE_VIEW_CLICKED:
            eventText = "Focused: ";
            break;
        case AccessibilityEvent.TYPE_VIEW_FOCUSED:
            eventText = "Focused: ";
            break;
    }
    eventText = eventText + event.getContentDescription();


    // Traverse all items in screen. 
    // Do something with text.

    AccessibilityNodeInfo info = getRootInActiveWindow();

    int index;
    int count = info.getChildCount();
    AccessibilityNodeInfo child;

    for (index = 0; index < count; index++) {
        child = info.getChild(index);
        if (child.getText() != null)
            Log.d(TAG, "text: " + child.getText().toString() + " " + child.getContentDescription());

        // perform Click
        //if (child.isClickable());
            //child.performAction(AccessibilityNodeInfo.ACTION_CLICK);
    }
}

はい、これは問題を解決するための適切な方法ではないことを知っています。一種のハックです。

0
Stanley Kou

ボタンを使用して通話に応答するには、着信を検出したときにフラグを設定します。

_ if(state==TelephonyManager.CALL_STATE_RINGING){
           shouldAnswerCallViaNotification = true;
        } else {
            shouldAnswerCallViaNotification = false;
        }
_

次に、NSLogServiceクラスにリストを作成します。

_static ArrayList<StatusBarNotification> statusBarNotifications;
_

そして、あなたのonNotificationPosted()でStatusBarNotificationをリストに追加し、

_   @Override
public void onNotificationPosted(StatusBarNotification sbn) {

    if (HomeScreen.shouldAnswerCallViaNotification) {
        if (statusBarNotifications == null) {
            updateNotificationList();
        }
       statusBarNotifications.add(sbn);

    } else {
        updateNotificationList();
    }

}
 public static ArrayList<StatusBarNotification> getAllNotifications() {
    return statusBarNotifications;
}

public static void updateNotificationList() {

    if (statusBarNotifications != null)
        statusBarNotifications = null;
    statusBarNotifications = new ArrayList<StatusBarNotification>();
}
_

ホームスクリーンで、ボタンをクリックしてperformNotificationOperation(NLService.getAllNotifications());を呼び出します

このメソッドの定義は次のとおりです。

_ private void performNotificationOperation(ArrayList<StatusBarNotification> activeNotifications) {

    if (activeNotifications.size()> 0) {
        main_Loop:
        for (StatusBarNotification notification : activeNotifications) {
            try {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KitKat) {
                    if (notification.getNotification().actions != null) {
                        for (Notification.Action action : notification.getNotification().actions) {
                            //            Log.e(TAG, "" + action);

                            Log.e(TAG, "" + action.title);
                            if (action.title.toString().equalsIgnoreCase("Answer")) {
                                Log.e(TAG, "" + true);
                                PendingIntent intent = action.actionIntent;

                                try {
                                    intent.send();
                                } catch (PendingIntent.CanceledException e) {
                                    e.printStackTrace();
                                }
                                break main_Loop;
                            }


                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
    }
    try {
        NLService.updateNotificationList();
    } catch (Exception e) {
        e.printStackTrace();
    }

}
_
0
Vishal Sharma

"Vishal Sharma"の回答によると、他の言語をサポートするために、アクションボタンのタイトルを動的に取得できます。

  @Override
  public void onNotificationPosted(StatusBarNotification sbn) {
    try {
      if (sbn.getNotification().actions != null) {
        Notification.Action[] notificationAction=sbn.getNotification().actions;
        //Log.e(G.TAG, "" +notificationAction  + " =>"+notificationAction.length);
           String rejectTitle=""+notificationAction[0].title;
           String acceptTitle=""+notificationAction[1].title;

        for (Notification.Action action : notificationAction){
          if (action.title.toString().equalsIgnoreCase(acceptTitle)) {
            PendingIntent intent = action.actionIntent;
            try {
              intent.send();
            } catch (PendingIntent.CanceledException e) {
              e.printStackTrace();
            }
          }
        }


      }
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
0
Mikael