web-dev-qa-db-ja.com

whatsappを介してプログラムでメッセージを送信する

Whatsapp経由でメッセージを送信しようとしていますが、ユーザーが送信ボタンをクリックする必要がある場合を除き、コードは機能します。すべて(すべてのユーザーインタラクション)を実行するアプリが必要です。次のようにそれを行う1つの方法。

メニューボタン> [設定]> [チャット]に移動します。 「Enter is sendオプション」をチェックします

私が使用しているコードは次のとおりです。

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

ありがとうございました

7
Nizar

Androidの Accessibility API を使用して、それを行うことができますonly.

アイデアは非常にシンプルで、実際にAndroid Whatsappの送信ボタンをクリックして実行します。

したがって、フローは次のようになります。

  1. Sent by MY_APP」などのメッセージコンテンツの末尾にサフィックスを付けて、通常のメッセージを(現在使用している意図で)送信します。
  2. テキストが表示されると、whatsappのEditTextがいっぱいになったことがアクセシビリティサービスに通知されます。
  3. WhatsappのEditTextに接尾辞が存在する場合、アクセシビリティサービスは[送信]ボタンをクリックします。 (これは、ユーザーが自然に通常のメッセージを入力するときにアクションを実行するのを避けるためです)。

以下に例を示します(より制限的にしたい場合はTweakを使用します)。

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

これは純粋にソリューションの技術的な側面にあります。

さて、の倫理的問題「それをするべきですか?」、答えは非常に明確だと思います:

障害を持つ人々(Accessibility APIのまさに目的)をターゲットにしている場合を除き、おそらく[〜#〜] not [〜#〜] それを行う。

19
user1079425