wake-up-neo.com

Anruf programmatisch in Nougat annehmen

Seit einem Jahr arbeite ich an IOT-Produkten und die beigefügte Anwendung funktionierte einwandfrei. Jetzt kann ich Anrufe in höheren Android-Versionen nicht programmgesteuert annehmen. Funktion ist sehr wichtig für das Produkt. Jede Hilfe wird sehr geschätzt.

Vor dem Update des Sicherheitspatches November 2016 funktionierte Runtime.getRunTime.exec("Command") gut, um Anrufe programmgesteuert anzunehmen. 

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

Wie mache ich das in der Nougat-Version von Android?.

Auf der Suche nach einem Hack. 

Ich habe einen Thread für die Erweiterungen geöffnet. 

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

Note * Wenn einer von Ihnen das gleiche Problem hat, fordern Sie bitte Android Dev Team an, um sich darauf einzulassen und die Bereitstellung der Berechtigung zur Laufzeit durch den Benutzer zu ermöglichen. Befolgen Sie die oben erwähnte URL zum Anfordern.

19
AndroidHacker

Da ich auch an IOT-Produkten arbeite, war dies eines der größten Probleme, mit denen ich konfrontiert war, aber nach einigem Nachdenken habe ich glaube, dass ich eine Lösung für dieses Problem gefunden habe, oder Sie können einen einfachen Hack sagen in mehreren Geräten mit mehreren Versionen und festgestellt, dass die meisten Geräte reagieren. Nur Samsung-Geräte reagieren nicht, einige Huawei-Geräte und einige Oppo-Geräte reagieren ebenfalls nicht. (Ich suche immer noch etwas nach diesen Geräten).

Mir ist aufgefallen, dass Android eine Funktion für den Zugriff auf Benachrichtigungen bietet. Sie können NotificationListenerService verwenden, um Benachrichtigungen zu lesen und einige Aktionen über sie auszuführen .. _ Sie bietet einige Überschreibungsmethoden:

 onNotificationPosted()
    onNotificationRemoved()
    getActiveNotifications()

... usw

Hier ist ein Code: Erstellen Sie einen Dienst, der NotificationListenerService erweitert

 class NLService extends NotificationListenerService {

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

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

Fügen Sie diesen Dienst in AndroidMenifest hinzu:

 <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>

Dadurch kann Ihre Anwendung jede empfangene Benachrichtigung lesen.

Jetzt ist hier der Hauptcode:

Fügen Sie in onNotificationPosted (StatusBarNotification sbn) diesen Code hinzu:

 @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();
          }
     }

Das ist es!

Alles ist eingestellt. Führen Sie die Anwendung und die Geräte mit Ausnahme von Samsung aus. Wenn Sie eine Benachrichtigung über einen eingehenden Anruf erhalten, können Sie mit den Aktionsschaltflächen Annehmen und Ablehnen/Ablehnen einen Anruf entgegennehmen.

Um die Benachrichtigungszugriffseinstellungen zu öffnen und Ihrer Anwendung zu erlauben, die Benachrichtigung zu lesen, verwenden Sie Folgendes:

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

Erstellen Sie einfach einen POC und lassen Sie mich wissen, wie es funktioniert.

Bitte kreuzen Sie meine Antwort an, wenn dies hilft.

Wenn Sie eine Lösung für Samsung-Geräte anbieten können, aktualisieren Sie diese bitte.

Vielen Dank

8
Vishal Sharma

Es ist eine Art Hack, Sie können accessibility service verwenden, um einen Anruf zu erhalten. Um den Eingabehilfedienst zu aktivieren, müssen Sie Ihren Dienst unter Einstellung - Eingabehilfen - Ihr Dienst aktivieren.

Fügen Sie zunächst typeWindowContentChanged zu accessibilityEventTypes hinzu.

<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"
/>

Und tun Sie etwas mit Ereignis oder "angezeigtem Text" oder "Inhaltsbeschreibung".

@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);
    }
}

Ja, ich weiß, dass dies kein anmutiger Weg ist, um Ihr Problem zu lösen. Es ist eine Art Hack.

0
Stanley Kou

Wenn Sie einen Anruf mit einer Taste annehmen möchten, setzen Sie ein Kennzeichen, wenn ein eingehender Anruf erkannt wird:

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

Erstellen Sie nun eine Liste in Ihrer NSLogService-Klasse.

static ArrayList<StatusBarNotification> statusBarNotifications;

und fügen Sie in Ihrem onNotificationPosted () StatusBarNotification einer Liste hinzu,

   @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>();
}

Rufen Sie in Ihrem Startbildschirm beim Klicken auf Button performNotificationOperation(NLService.getAllNotifications()); auf.

hier ist eine Definition für diese Methode:

 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

Entsprechend der Antwort " Vishal Sharma " können wir den Titel der Aktionsschaltfläche dynamisch erhalten, um andere Sprachen zu unterstützen:

  @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