通过whatsapp以编程方式发送消息
我正在尝试通过 Whatsapp 发送消息,该代码有效,但用户需要单击发送"按钮.我需要该应用程序执行所有操作(所有用户互动).做到这一点的一种方法如下.
I'm trying to send messages via Whatsapp programmatically, the code works except the user needs to click the send button. I need the app to do everything (all user interactions). One way to do to it as follows .
转到菜单按钮>设置>聊天.并选中输入即发送"选项
Go to Menu Button > Settings > Chats. and check the "Enter is send option"
这是我正在使用的代码:
Here's the code I'm using:
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);
}
谢谢
您可以使用这个想法很简单,您实际上将使Android执行Whatsapp的发送按钮的点击.
The idea is quite simple, you'll actually make Android perform the click on Whatsapp's send button.
因此流程将是:
- 发送常规消息(具有您当前正在使用的意图),并在消息内容的末尾添加后缀,例如"
Sent by MY_APP
". - 在此处输入文字后,将通知您的辅助功能服务whatsapp的
EditText
已填充. - 如果whatsapp的
EditText
上存在后缀,则您的可访问性服务将单击发送"按钮. (这是为了避免在用户自然键入常规消息时执行操作).
- 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
". - Once the text there, your accessibility service will be notified that the
EditText
of whatsapp is filled. - 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);
}
}
然后在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>
最后一件事是检查是否为您的应用程序启用了辅助功能,如果没有,则将用户重定向到设置:
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;
}
您将使用的呼叫方式:
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:
除非您以残疾人为对象(这是Accessibility API的目的),否则您应该不这样做.
Except if you are targeting people with disabilities (which is the very purpose of the Accessibility API), you should probably NOT do that.