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
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:
Sent by MY_APP
".EditText
de WhatsApp est rempli.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.