web-dev-qa-db-fra.com

Envoyer un message via WhatsApp par programme

J'essaie d'envoyer des messages via Whatsapp par programme, le code fonctionne sauf que l'utilisateur doit cliquer sur le bouton envoyer. J'ai besoin de l'application pour tout faire (toutes les interactions avec les utilisateurs). Une façon de le faire comme suit.

Allez dans le bouton Menu> Paramètres> Chats. et cochez l'option "Enter is send"

Voici le code que j'utilise:

protected void sendwts(){
    String smsNumber = "2126123456789"; // E164 format without '+' sign
    Intent sendIntent = new Intent(Intent.ACTION_SEND);
    //  Intent sendIntent = new Intent(Intent.ACTION_SENDTO);
    sendIntent.setType("text/plain");
    sendIntent.putExtra(Intent.EXTRA_TEXT, "test \n");
    sendIntent.putExtra("jid", smsNumber + "@s.whatsapp.net"); //phone number without "+" prefix
    sendIntent.setPackage("com.whatsapp");

    startActivity(sendIntent);
}

Je vous remercie

7
Nizar

Vous pouvez le faire seulement en utilisant API d'accessibilité d'Android.

L'idée est assez simple, vous ferez en fait Android effectuer le clic sur le bouton d'envoi de Whatsapp.

Le flux sera donc:

  1. Envoyez un message régulier (avec l'intention que vous utilisez actuellement) avec un suffixe à la fin du contenu de votre message, tel que "Sent by MY_APP ".
  2. Une fois le texte là, votre service d'accessibilité sera informé que le EditText de WhatsApp est rempli.
  3. Si le suffixe est présent sur le EditText de WhatsApp, votre service d'accessibilité cliquera sur le bouton d'envoi. (ceci pour éviter d'effectuer des actions pendant que l'utilisateur tape naturellement un message normal).

Voici un exemple (que vous aurez Tweak si vous voulez le rendre plus restrictif):

public class WhatsappAccessibilityService extends AccessibilityService {

    @Override
    public void onAccessibilityEvent (AccessibilityEvent event) {
        if (getRootInActiveWindow () == null) {
            return;
        }

        AccessibilityNodeInfoCompat rootInActiveWindow = AccessibilityNodeInfoCompat.wrap (getRootInActiveWindow ());

        // Whatsapp Message EditText id
        List<AccessibilityNodeInfoCompat> messageNodeList = rootInActiveWindow.findAccessibilityNodeInfosByViewId ("com.whatsapp:id/entry");
        if (messageNodeList == null || messageNodeList.isEmpty ()) {
            return;
        }

        // check if the whatsapp message EditText field is filled with text and ending with your suffix (explanation above)
        AccessibilityNodeInfoCompat messageField = messageNodeList.get (0);
        if (messageField.getText () == null || messageField.getText ().length () == 0 
            || !messageField.getText ().toString ().endsWith (getApplicationContext ().getString (R.string.whatsapp_suffix))) { // So your service doesn't process any message, but the ones ending your apps suffix
            return;
        }

        // Whatsapp send button id
        List<AccessibilityNodeInfoCompat> sendMessageNodeInfoList = rootInActiveWindow.findAccessibilityNodeInfosByViewId ("com.whatsapp:id/send");
        if (sendMessageNodeInfoList == null || sendMessageNodeInfoList.isEmpty ()) {
            return;
        }

        AccessibilityNodeInfoCompat sendMessageButton = sendMessageNodeInfoList.get (0);
        if (!sendMessageButton.isVisibleToUser ()) {
            return;
        }

        // Now fire a click on the send button
        sendMessageButton.performAction (AccessibilityNodeInfo.ACTION_CLICK);

        // Now go back to your app by clicking on the Android back button twice: 
        // First one to leave the conversation screen 
        // Second one to leave whatsapp
        try {
            Thread.sleep (500); // hack for certain devices in which the immediate back click is too fast to handle
            performGlobalAction (GLOBAL_ACTION_BACK);
            Thread.sleep (500);  // same hack as above
        } catch (InterruptedException ignored) {}
        performGlobalAction (GLOBAL_ACTION_BACK);
    }
}

Créez ensuite sa définition dans res -> xml -> whatsapp_service.xml:

<?xml version="1.0" encoding="utf-8"?>
<accessibility-service
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:accessibilityEventTypes="typeWindowContentChanged"
    Android:packageNames="com.whatsapp"
    Android:accessibilityFeedbackType="feedbackSpoken"
    Android:notificationTimeout="100"
    Android:canRetrieveWindowContent="true"/>

Déclarez-le ensuite dans votre manifeste:

<service
    Android:name=".services.WhatsappAccessibilityService"
    Android:label="Accessibility Service"
   Android:permission="Android.permission.BIND_ACCESSIBILITY_SERVICE">
    <meta-data
        Android:name="Android.accessibilityservice"
        Android:resource="@xml/whatsapp_service"/>

    <intent-filter>
        <action Android:name="Android.accessibilityservice.AccessibilityService"/>
    </intent-filter>
</service>

Et la dernière chose, c'est de vérifier si les services d'accessibilité sont activés pour votre application ou non, et de rediriger l'utilisateur vers les paramètres sinon:

private boolean isAccessibilityOn (Context context, Class<? extends AccessibilityService> clazz) {
    int accessibilityEnabled = 0;
    final String service = context.getPackageName () + "/" + clazz.getCanonicalName ();
    try {
        accessibilityEnabled = Settings.Secure.getInt (context.getApplicationContext ().getContentResolver (), Settings.Secure.ACCESSIBILITY_ENABLED);
    } catch (Settings.SettingNotFoundException ignored) {  }

    TextUtils.SimpleStringSplitter colonSplitter = new TextUtils.SimpleStringSplitter (":");

    if (accessibilityEnabled == 1) {
        String settingValue = Settings.Secure.getString (context.getApplicationContext ().getContentResolver (), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
        if (settingValue != null) {
            colonSplitter.setString (settingValue);
            while (colonSplitter.hasNext ()) {
                String accessibilityService = colonSplitter.next ();

                if (accessibilityService.equalsIgnoreCase (service)) {
                    return true;
                }
            }
        }
    }

    return false;
}

que vous appellerez avec:

if (!isAccessibilityOn (context, WhatsappAccessibilityService.class)) {
    Intent intent = new Intent (Settings.ACTION_ACCESSIBILITY_SETTINGS);
    context.startActivity (intent);
}

Il s'agit uniquement de l'aspect technique de la solution.

Maintenant, la question éthique de "devriez-vous faire cela?" , je pense que la réponse est assez claire:

Sauf si vous ciblez des personnes handicapées (ce qui est le but même de l'API d'accessibilité), vous devriez probablement [~ # ~] pas [~ # ~] fais ça.

19
user1079425