Send message via whatsapp programmatically Send message via whatsapp programmatically android android

Send message via whatsapp programmatically


You can do that only using the Accessibility API of Android.

The idea is quite simple, you'll actually make Android perform the click on Whatsapp's send button.

So the flow will be:

  1. Send a regular message (with the intent you're currently using) with a suffix at the end of your message content such as "Sent by MY_APP".
  2. Once the text there, your accessibility service will be notified that the EditText of whatsapp is filled.
  3. If the suffix is present on the EditText of whatsapp, Your accessibility service will click on the send button. (this is to avoid performing actions as the user types in naturally a regular message).

Here's an example (which you'll have tweak if you wanna make it more restrictive):

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

Then create its definition in 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"/>

Then declare it in your manifest:

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

And last thing, is to check if the accessibility services are enabled for your app or not, and redirect the user to the settings if not:

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

which you'll call with:

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

This is purely on the technical aspect of the solution.

Now, the ethical question of "should you do that?", I believe the answer is quite clear:

Except if you are targeting people with disabilities (which is the very purpose of the Accessibility API), you should probably NOT do that.