以编程方式通过whatsapp发送消息

时间:2018-04-04 15:16:22

标签: android whatsapp

我尝试通过 Whatsapp 以编程方式发送消息,代码可以正常工作,但用户需要点击发送按钮。我需要应用程序来完成所有事情(所有用户交互)。一种方法如下。

  

转到菜单按钮>设置>聊天。并选中"输入发送选项"

以下是我使用的代码:

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

谢谢

1 个答案:

答案 0 :(得分:16)

您可以使用Android的Accessibility API执行

这个想法很简单,你实际上会让Android执行点击Whatsapp的发送按钮。

所以流程将是:

  1. 发送常规消息(具有您当前使用的意图),并在消息内容末尾添加后缀,例如“Sent by MY_APP”。
  2. 在那里发送文字后,您的辅助功能服务将被通知Whatsapp的EditText已填写。
  3. 如果whatsapp的EditText上有后缀,您的辅助功能服务将点击发送按钮。 (这是为了避免在用户自然输入常规消息时执行操作。)
  4. 这是一个例子(如果你想让它更具限制性,你可以调整一下):

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

    然后在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"/>
    

    然后在你的清单中声明它:

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

    最后一点是检查是否为您的应用启用了辅助功能服务,如果没有,则将用户重定向到设置:

    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;
    }
    
    你打电话给

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

    这完全取决于解决方案的技术方面。

    现在,的道德问题“你应该这样做吗?”,我相信答案很清楚:

    除非您针对残疾人(这是辅助功能API的目的),否则您应该这样做。