通过编程向特定联系人发送文本消息(WhatsApp)

80

我想知道如何向特定的WhatsApp联系人发送文本。我找到了一些代码来查看特定的联系人,但没有发送数据的代码。

Cursor c = getContentResolver().query(ContactsContract.Data.CONTENT_URI,
    new String[] { ContactsContract.Contacts.Data._ID }, ContactsContract.Data.DATA1 + "=?",
    new String[] { id }, null);
c.moveToFirst();
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse("content://com.android.contacts/data/" + c.getString(0)));

startActivity(i);
c.close();

这对于查看WhatsApp联系人很好用,但现在我如何添加一些文本呢?或者Whatsapp开发人员没有实现这种API吗?


重复的问题,参考链接:https://dev59.com/6WUp5IYBdhLWcg3wLVKn - rds
5
不,你提供的链接使用了一个选择器,而我不想用它。我想直接将文本发送给一个联系人。 - Manuel Allenspach
他想要打开聊天记录,而我想要发送文本。这是非常不同的。 - Manuel Allenspach
1
@manu 你好,我在我的应用程序中使用了你的代码来向Whatsapp发送消息,而不必打开Whatsapp,但是我遇到了getSherlockActivity()的错误。由于我是Android新手,所以我不理解getSherlockActivity()是什么意思。 - Mahi
似乎无法通过WhatsApp程序化地发送消息,所以我放弃了... - Manuel Allenspach
显示剩余2条评论
29个回答

96

我已经找到了正确的方法:

源代码:phonemessage都是String类型。

    PackageManager packageManager = context.getPackageManager();
    Intent i = new Intent(Intent.ACTION_VIEW);

    try {
        String url = "https://api.whatsapp.com/send?phone="+ phone +"&text=" + URLEncoder.encode(message, "UTF-8");
        i.setPackage("com.whatsapp");
        i.setData(Uri.parse(url));
        if (i.resolveActivity(packageManager) != null) {
            context.startActivity(i);
        }
    } catch (Exception e){
        e.printStackTrace();
    }

尽情享受!


6
这个是正确的,而得到最多赞的那个方法只有当联系人已经被添加到手机中才能起作用。 - Pablo Quemé
2
不发送文本,只是打开聊天窗口但不发送文本。 - suv
3
正如@PabloQuemé所说,如果您之前没有添加过联系人,则会出现一个提示,指出您没有此联系人。因此,我只发送了电话号码,但是一旦我添加了带有国家/地区代码的完整号码,这就起作用了! - MontDeska
1
完美答案。 - Amin Pinjari
4
在号码前加上国家代码,例如+91、+1、+44等,将会打开该联系人的聊天界面。 - Pratik Tank
显示剩余12条评论

75

我认为答案是你的问题和这个答案的结合: https://dev59.com/6WUp5IYBdhLWcg3wLVKn#15931345 因此,我建议尝试以下代码:

  1. 将ACTION_VIEW更改为ACTION_SENDTO
  2. 像您所做的那样设置Uri
  3. 将应用程序包设置为 whatsapp
Intent i = new Intent(Intent.ACTION_SENDTO, Uri.parse("content://com.android.contacts/data/" + c.getString(0)));
i.setType("text/plain");
i.setPackage("com.whatsapp");           // so that only Whatsapp reacts and not the chooser
i.putExtra(Intent.EXTRA_SUBJECT, "Subject");
i.putExtra(Intent.EXTRA_TEXT, "I'm the body.");
startActivity(i);

我查看了Whatsapp清单并发现ACTION_SEND已经注册到活动,所以那不会对你有帮助。然而,ACTION_SENDTO已经注册到活动,似乎更适合你的问题。

Whatsapp可以作为发送短信的替代品,因此它应该像短信一样工作。当你没有指定期望的应用程序(通过)时,Android将显示应用程序选择器。因此,你只需要查看通过意图发送短信的代码,然后提供额外的包信息即可。

Uri uri = Uri.parse("smsto:" + smsNumber);
Intent i = new Intent(Intent.ACTION_SENDTO, uri);
i.putExtra("sms_body", smsText);  
i.setPackage("com.whatsapp");  
startActivity(i);

首先尝试将意图 ACTION_SEND 替换为 ACTION_SENDTO。如果这不起作用,则提供额外的 sms_body。如果这还是不起作用,请尝试更改 URI。

更新 我尝试自己解决这个问题,但无法找到解决方案。WhatsApp 打开了聊天记录,但没有将文本发送出去。似乎这个功能还没有实现。


8
只是打开了联系人,但没有将文本传递给WhatsApp...似乎WhatsApp无法识别这些额外信息(或不想识别)。 - Manuel Allenspach
1
似乎 WhatsApp 封锁了这种方式... 谢谢您的帮助。 - Manuel Allenspach
1
如果你想要一个选择器怎么办?如果我添加i.setPackage("com.whatsapp"),它会启动Whatsapp,但是当我不添加时,它会启动短信应用程序(在我的情况下是Hangouts)。 - Roel
2
它告诉我这个电话号码没有WhatsApp,即使它有。我应该先以某种方式格式化它吗? - android developer
2
请阅读我的回答,它可以在不将其添加到您的联系人列表中的情况下正常工作。完美运行。 - Crono
显示剩余14条评论

69

我做到了!

private void openWhatsApp() {
    String smsNumber = "7****"; // E164 format without '+' sign
    Intent sendIntent = new Intent(Intent.ACTION_SEND);
    sendIntent.setType("text/plain");
    sendIntent.putExtra(Intent.EXTRA_TEXT, "This is my text to send.");
    sendIntent.putExtra("jid", smsNumber + "@s.whatsapp.net"); //phone number without "+" prefix
    sendIntent.setPackage("com.whatsapp");
    if (intent.resolveActivity(getActivity().getPackageManager()) == null) {
        Toast.makeText(this, "Error/n" + e.toString(), Toast.LENGTH_SHORT).show();
        return;    
    }
    startActivity(sendIntent);
}

2
我对你的解决方案持怀疑态度,因为它没有得到很多赞同。但是它确实有效! - Sarthak Majithia
2
它可以打开特定的联系人号码和特定的聊天文本,但不会发送它,用户必须按发送按钮才能发送消息。+1 赞成票以打开特定活动。 - Amandeep Rohila
6
可以翻译为:“功能正常,但应将电话号码添加到设备联系人列表中。” - Agustin Scalisi
2
这个确实有效!如果能找到一种方法来使用应用选择器并仍然包括消息文本和电话号码,以便用户可以选择短信和Whatsapp选项,那就更好了...有人知道吗? - Vova
这个可以工作。太好了,谢谢你的回答。问题是,如果联系人没有保存,它就无法工作。你能对此做些什么吗? - Reddy Raaz
显示剩余2条评论

23

这种方法同样适用于 WhatsApp Business 应用程序!

更改包名称为 sendIntent.setPackage("com.whatsapp.w4b"); 以适用于 WhatsApp Business。

伟大的技巧,Rishabh,非常感谢,我一直在寻找这个解决方案已经三年了。

根据上面 Rishabh Maurya 的答案,我已经实现了这段代码,它可以很好地用于在 WhatsApp 上分享文本和图片。

请注意,在这两种情况下它都会打开一个 WhatsApp 对话(如果 toNumber 存在于用户的 WhatsApp 联系人列表中),但是用户必须点击发送按钮才能完成操作。也就是说,它有助于跳过联系人选择步骤。

对于文本消息

String toNumber = "+91 98765 43210"; // contains spaces.
toNumber = toNumber.replace("+", "").replace(" ", "");

Intent sendIntent = new Intent("android.intent.action.MAIN");
sendIntent.putExtra("jid", toNumber + "@s.whatsapp.net");
sendIntent.putExtra(Intent.EXTRA_TEXT, message);
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.setPackage("com.whatsapp");
sendIntent.setType("text/plain");
startActivity(sendIntent);

分享图片

String toNumber = "+91 98765 43210"; // contains spaces.
toNumber = toNumber.replace("+", "").replace(" ", "");

Intent sendIntent = new Intent("android.intent.action.MAIN");
sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(imageFile));
sendIntent.putExtra("jid", toNumber + "@s.whatsapp.net");
sendIntent.putExtra(Intent.EXTRA_TEXT, message);
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.setPackage("com.whatsapp");
sendIntent.setType("image/png");
context.startActivity(sendIntent);

享受使用WhatsApp!


2
对我没用。它只打开了联系人选择界面。 - Mayank Pandya
@DeepakPandit 请查看我们的应用程序 https://play.google.com/store/apps/details?id=com.wiwonders.billbook,其中包含共享图像功能。 - Pioneer
1
打开带有空白消息的特定联系人。 - Abhi
对于多个数字,我应该怎么办? - Attaullah
有什么方法可以过滤消息吗? - Manjunath Gk
显示剩余2条评论

19

它可以让您打开WhatsApp与特定用户的对话屏幕:

private void openWhatsApp() {
    String smsNumber = "91XXXXXXXX20";
    boolean isWhatsappInstalled = whatsappInstalledOrNot("com.whatsapp");
    if (isWhatsappInstalled) {

        Intent sendIntent = new Intent("android.intent.action.MAIN");
        sendIntent.setComponent(new ComponentName("com.whatsapp", "com.whatsapp.Conversation"));
        sendIntent.putExtra("jid", PhoneNumberUtils.stripSeparators(smsNumber) + "@s.whatsapp.net");//phone number without "+" prefix

        startActivity(sendIntent);
    } else {
        Uri uri = Uri.parse("market://details?id=com.whatsapp");
        Intent goToMarket = new Intent(Intent.ACTION_VIEW, uri);
        Toast.makeText(this, "WhatsApp not Installed",
                Toast.LENGTH_SHORT).show();
        startActivity(goToMarket);
    }
}

private boolean whatsappInstalledOrNot(String uri) {
    PackageManager pm = getPackageManager();
    boolean app_installed = false;
    try {
        pm.getPackageInfo(uri, PackageManager.GET_ACTIVITIES);
        app_installed = true;
    } catch (PackageManager.NameNotFoundException e) {
        app_installed = false;
    }
    return app_installed;
}

你在哪里提到要发送“WhatsApp消息”? - Suryaprakash Pisay
1
它将打开一个窗口,您可以在其中输入消息,然后明确地发送它。试一次。 - Prakhar Kulshreshtha
1
打开特定联系人并附带空白消息。 - Abhi
你可能还想在调用“startActivity(goToMarket)”时加上try / catch子句,因为某些手机可能没有Google Play或任何其他活动来响应试图查找“market://”URI的Intent。 - HendrikFrans
它说:“异常android.content.ActivityNotFoundException:无法找到显式活动类{com.whatsapp / com.whatsapp.Conversation};您是否在AndroidManifest.xml中声明了此活动,或者您的意图与其声明的<intent-filter>不匹配?” - Ready Android
显示剩余5条评论

15

看看我的回答:https://dev59.com/xpXfa4cB1Zd3GeqPhqCk#40285262

 Intent sendIntent = new Intent("android.intent.action.MAIN");
 sendIntent.setComponent(new  ComponentName("com.whatsapp","com.whatsapp.Conversation"));
 sendIntent.putExtra("jid", PhoneNumberUtils.stripSeparators("YOUR_PHONE_NUMBER")+"@s.whatsapp.net");//phone number without "+" prefix

 startActivity(sendIntent);

更新:

之前提到的黑客攻击不能用于添加任何特定的信息,因此这里有一种新的方法。将用户的手机号码以国际格式传递到此处,不要包含任何括号、破折号或加号。例如:如果用户来自印度,他的手机号码是94xxxxxxxx,那么国际格式将为9194xxxxxxxx。不要忘记在手机号码前面作为前缀添加国家代码。

  private fun sendMsg(mobile: String, msg: String){
    try {
        val packageManager = requireContext().packageManager
        val i = Intent(Intent.ACTION_VIEW)
        val url =
            "https://wa.me/$mobile" + "?text=" + URLEncoder.encode(msg, "utf-8")
        i.setPackage("com.whatsapp")
        i.data = Uri.parse(url)
        if (i.resolveActivity(packageManager) != null) {
            requireContext().startActivity(i)
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

注意:此方法仅适用于用户在其Whatsapp帐户中添加的联系人。


@Manu 你需要重新考虑对这个问题的回答! - Rishabh Maurya
你应该使用"com.whatsapp.ContactPicker"代替"com.whatsapp.Conversation"。 - AMI CHARADAVA
1
@RishabhMaurya 如何同时包含一个位图? - Darshan Miskin

12

Whatsapp 有自己的 API

    Intent sendIntent = new Intent("android.intent.action.MAIN");
                        sendIntent.setAction(Intent.ACTION_VIEW);
                        sendIntent.setPackage("com.whatsapp");
                        String url = "https://api.whatsapp.com/send?phone=" + "Phone with international format" + "&text=" + "your message";
                        sendIntent.setData(Uri.parse(url));
                        if(sendIntent.resolveActivity(context.getPackageManager()) != null){
                             startActivity(sendIntent);
                        }

为了检查该活动是否可用,已添加更新代码检查。

请参见此文档


2
在 WhatsApp 版本 2.18.380 上对我有效。 - Codelicious
对我来说运行良好。 - kiumars gilanizadeh

6

这将首先搜索指定的联系人,然后打开一个聊天窗口。如果未安装WhatsApp,则使用try-catch块处理此问题。

    String digits = "\\d+";
    String mob_num = "987654321";     
    if (mob_num.matches(digits)) 
            {
        try {
              //linking for whatsapp
              Uri uri = Uri.parse("whatsapp://send?phone=+91" + mob_num);
              Intent i = new Intent(Intent.ACTION_VIEW, uri);
              startActivity(i);
            }
            catch (ActivityNotFoundException e){
                    e.printStackTrace();
                    //if you're in anonymous class pass context like "YourActivity.this"
                    Toast.makeText(this, "WhatsApp not installed.", Toast.LENGTH_SHORT).show();
            }
        }

6

我正在尝试使用另一个应用程序在WhatsApp中发送文本消息。

假设我们有一个按钮,当点击该按钮时,会调用以下方法:

sendTextMsgOnWhatsApp("+91 9876543210", "你好,这是我的测试消息");

public void sendTextMsgOnWhatsApp(String sContactNo, String sMessage) {
        String toNumber = sContactNo; // contains spaces, i.e., example +91 98765 43210
        toNumber = toNumber.replace("+", "").replace(" ", "");

        /*this method contactIdByPhoneNumber() will get unique id for given contact,
        if this return's null then it means that you don't have any contact save with this mobile no.*/
        String sContactId = contactIdByPhoneNumber(toNumber);

        if (sContactId != null && sContactId.length() > 0) {

            /*
             * Once We get the contact id, we check whether contact has a registered with WhatsApp or not.
             * this hasWhatsApp(hasWhatsApp) method will return null,
             * if contact doesn't associate with whatsApp services.
             * */
            String sWhatsAppNo = hasWhatsApp(sContactId);

            if (sWhatsAppNo != null && sWhatsAppNo.length() > 0) {
                Intent sendIntent = new Intent("android.intent.action.MAIN");
                sendIntent.putExtra("jid", toNumber + "@s.whatsapp.net");
                sendIntent.putExtra(Intent.EXTRA_TEXT, sMessage);
                sendIntent.setAction(Intent.ACTION_SEND);
                sendIntent.setPackage("com.whatsapp");
                sendIntent.setType("text/plain");
                startActivity(sendIntent);
            } else {
                // this contact does not exist in any WhatsApp application
                Toast.makeText(this, "Contact not found in WhatsApp !!", Toast.LENGTH_SHORT).show();
            }
        } else {
            // this contact does not exist in your contact
            Toast.makeText(this, "create contact for " + toNumber, Toast.LENGTH_SHORT).show();
        }
    }

    private String contactIdByPhoneNumber(String phoneNumber) {
        String contactId = null;
        if (phoneNumber != null && phoneNumber.length() > 0) {
            ContentResolver contentResolver = getContentResolver();
            Uri uri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber));
            String[] projection = new String[]{ContactsContract.PhoneLookup._ID};

            Cursor cursor = contentResolver.query(uri, projection, null, null, null);

            if (cursor != null) {
                while (cursor.moveToNext()) {
                    contactId = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.PhoneLookup._ID));
                }
                cursor.close();
            }
        }
        return contactId;
    }

    public String hasWhatsApp(String contactID) {
        String rowContactId = null;
        boolean hasWhatsApp;

        String[] projection = new String[]{ContactsContract.RawContacts._ID};
        String selection = ContactsContract.RawContacts.CONTACT_ID + " = ? AND " + ContactsContract.RawContacts.ACCOUNT_TYPE + " = ?";
        String[] selectionArgs = new String[]{contactID, "com.whatsapp"};
        Cursor cursor = getContentResolver().query(ContactsContract.RawContacts.CONTENT_URI, projection, selection, selectionArgs, null);
        if (cursor != null) {
            hasWhatsApp = cursor.moveToNext();
            if (hasWhatsApp) {
                rowContactId = cursor.getString(0);
            }
            cursor.close();
        }
        return rowContactId;
    }

请将以下权限添加到 AndroidManifest.xml 文件中

<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.INTERNET" />

1
这项工作不需要联系人ID,也不需要检查WhatsApp,我可以直接发送到号码。 - mDonmez
很棒,这对你有所帮助。实际上,这是最好的处理方式,你可以忽略在你的情况下不需要的逻辑部分。 - Ramesh kumar

4

这是最短的方式。

    String mPhoneNumber = "+972505555555";
    mPhoneNumber = mPhoneNumber.replaceAll("+", "").replaceAll(" ", "").replaceAll("-","");
    String mMessage = "Hello world";
    String mSendToWhatsApp = "https://wa.me/" + mPhoneNumber + "?text="+mMessage;
    startActivity(new Intent(Intent.ACTION_VIEW,
            Uri.parse(
                    mSendToWhatsApp
            )));

另请参阅 WhatsApp 的文档

(注:此链接为中文版)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接