如何将消息发送给Whatsapp联系人

(由于本人喜欢word文档编辑,不喜欢网络编辑,所以仍然提供pdf版文档,方便查阅http://files.cnblogs.com/franksunny/send_msg_to_Whatsapp.pdf

Whatsapp官网上没有找到在Android上进行消息发送相关的信息,但是有一个iOS相关的帖子https://www.whatsapp.com/faq/iphone/23559013,原以为用它的URL在Android上也是可以使用的,结果试了下不行,看来错误地把URL当作URI了。

基础功能实现

后来根据Android Intent和Intent Filters的官方文档说明(如果英文不太好,参考中文的翻译文档,链接为下面的第二个地址):

http://developer.android.com/guide/components/intents-filters.html

http://wiki.eoe.cn/page/Intents_and_Intent_Filters.html#comment

就想着查看了下Whatsapp的Manifest配置文件,看看能不能找出点蛛丝马迹,结果发现有如下的Activity信息

<activity

android:name=".ContactPicker"

android:configChanges="0x00000FB0"

>

<intent-filter

>

<action

android:name="android.intent.action.PICK"

>

</action>

<category

android:name="android.intent.category.DEFAULT"

>

</category>

<category

android:name="com.whatsapp"

>

</category>

</intent-filter>

<intent-filter

>

<action

android:name="android.intent.action.CREATE_SHORTCUT"

>

</action>

</intent-filter>

<intent-filter

>

<action

android:name="android.intent.action.SEND"

>

</action>

<category

android:name="android.intent.category.DEFAULT"

>

</category>

<data

android:mimeType="audio/*"

>

</data>

<data

android:mimeType="video/*"

>

</data>

<data

android:mimeType="image/*"

>

</data>

<data

android:mimeType="text/plain"

>

</data>

<data

android:mimeType="text/x-vcard"

>

</data>

</intent-filter>

<intent-filter

>

<action

android:name="android.intent.action.SEND_MULTIPLE"

>

</action>

<category

android:name="android.intent.category.DEFAULT"

>

</category>

<data

android:mimeType="audio/*"

>

</data>

<data

android:mimeType="video/*"

>

</data>

<data

android:mimeType="image/*"

>

</data>

</intent-filter>

</activity>

至于是不是这个Activity,简单写个测试就验证了,既然找到了这个对象,怎么将信息发送进去,继续google下“com.whatsapp”和“com.whatsapp.ContactPicker”字符串,结果就发现如下一些热帖:

http://stackoverflow.com/questions/6394173/androidpick-action-in-intent

http://stackoverflow.com/questions/19081654/send-to-specific-contact-whatsapp

http://stackoverflow.com/questions/15462874/sending-message-through-whatsapp

从中发现如果想要发送文字信息给Whatsapp进行Whatsapp内消息的发送,可以利用的intent中两个缺省的字段Intent.EXTRA_TEXT和Intent.EXTRA_SUBJECT,于是就按照“android.intent.action.SEND”这个Intent Filter做下如下的代码尝试。

public static boolean sendWhatsApp(Context ctx, String text){

boolean sendOk = false;

if(checkApkExist(ctx, "com.whatsapp")){

Intent vIt = new Intent("android.intent.action.SEND");

vIt.setPackage("com.whatsapp");

vIt.setType("text/plain");

if(!Util.IsNullOrEmpty(text)){

vIt.putExtra(Intent.EXTRA_TEXT, "This is a simple test");

vIt.putExtra(Intent.EXTRA_SUBJECT, "Subject");

}

ctx.startActivity(vIt);

sendOk = true;

}

return sendOk;

}

private static boolean checkApkExist(Context ctx, String packageName) {

if (packageName == null || "".equals(packageName))

return false;

try {

ApplicationInfo info = ctx.getPackageManager().getApplicationInfo(packageName, PackageManager.GET_UNINSTALLED_PACKAGES);

if(info != null){

return true;

}else{

return false;

}

}catch (NameNotFoundException e){

return false;

}

}

上述的checkApkExist方法是用于判断当前是否有安装相应包程序的,发送效果如下:

假如上述代码中,去除vIt.setPackage("com.whatsapp");这段代码之后,就会出现一个选择框的效果,这个就和很多程序中做分享的效果一致了,下面选择环聊做了简单测试。

假如要发图片的话也可以通过分享Deja头像的方式,来实现,下面将代码简单整理了下,就先省略了具体的判断代码:

public static void shareImageToWhatsapp(Activity ctx, Bitmap shareBitmap, String subject, String text) {

Intent intent = new Intent(Intent.ACTION_SEND);

intent.setPackage("com.whatsapp");

intent.setType("image/*");

Uri imageUri = Uri.parse(MediaStore.Images.Media.insertImage(ctx.getContentResolver(), shareBitmap, null, null));

intent.putExtra(Intent.EXTRA_SUBJECT, subject);

intent.putExtra(Intent.EXTRA_TEXT, text);

intent.putExtra(Intent.EXTRA_STREAM, imageUri);

ctx.startActivity(Intent.createChooser(intent, ctx.getTitle()));

}

扩展深入

以前对Intent和Intent Filters可以说是一知半解的,对于官方的提供的上面的那个API文档,也没有吃透,不过经过这次的机会,对于Intent和Intent Filter可以说有了一个比较进一步的认识。

Intent分为显式和隐式两种,简而言之,显式就是已经明显告知了所要调用的组件名称,而隐式是没有明确告知组件名称的调用方式,所以说显式调用时虽然也是通过Intent,但是显式调用不进行Intent Filter条件过滤;隐式调用组件时,就要通过组建在Manifest中设置的Intent Filter来进行匹配了。

显式调用有两种,一种是程序内部明确知道是具体的Activity,然后类似下述的直接调用:

startActivity(new Intent(this, ShareTargetActivity.class));

这种调用显然是能够通过lib或源码import到现有文件的方式。另外一种显式调用就是通过Intent的setComponent方法来显示调用,比如我们已经知道Whatsapp的组件名了,我们就可以通过以下方式调用:

public static boolean sendWhatsApp(Context ctx, String text){

boolean sendOk = false;

if(checkApkExist(ctx, "com.whatsapp")){

Intent vIt = new Intent();

ComponentName comp = new ComponentName( "com.whatsapp", "com.whatsapp.ContactPicker");

vIt.setComponent(comp);

if(!Util.IsNullOrEmpty(text)){

vIt.putExtra(Intent.EXTRA_TEXT, text);

vIt.putExtra(Intent.EXTRA_SUBJECT, "Subject\n");

}

ctx.startActivity(vIt);

sendOk = true;

}

return sendOk;

}

显式Intent时,压根就不用设置任何跟Intent Filter相关的参数,如果写了反而证明是不明真相的画蛇添足。

隐式Intent的调用就必须查看Manifest里面的配置了,而且根据API文档的说明,隐式Intent在进行过滤时,action、category和、data是必须进行匹配的,至于extra和flag选项只是负责传参数,不作为过滤条件。而一个Intent Filter只有一个action,category则是可以叠加的,至于data还是看API文档吧,不做过多展看了,通常我们都是忽略掉category,在这里正好给我们提供了一个category的例子,因为Whatsapp里面的第一个Intent Filter,即如下内容

<intent-filter

>

<action

android:name="android.intent.action.PICK"

>

</action>

<category

android:name="android.intent.category.DEFAULT"

>

</category>

<category

android:name="com.whatsapp"

>

</category>

</intent-filter>

我们可以通过下述方法进行隐式调用,就可以通过这个Filter的过滤,将参数正确传给ContactPicker这个Activity,以下给出简单代码:

public static boolean sendWhatsApp(Context ctx, String text) {

boolean sendOk = false;

if (checkApkExist(ctx, "com.whatsapp")) {

Intent vIt = new Intent("android.intent.action.PICK");

vIt.addCategory("com.whatsapp");

// vIt.setType("text/plain");

if (!Util.IsNullOrEmpty(text)) {

vIt.putExtra(Intent.EXTRA_TEXT, text);

vIt.putExtra(Intent.EXTRA_SUBJECT, "Subject\n");

}

ctx.startActivity(vIt);

sendOk = true;

}

return sendOk;

}

注意在上述这个例子中,注释掉的setType代码是必须注释的,否则程序将因为找不到Activity组件而报android.content.ActivityNotFoundException的异常错误。

同样我们也不能通过以下方式进行调用

public static boolean sendWhatsApp(Context ctx, String text){

boolean sendOk = false;

if(checkApkExist(ctx, "com.whatsapp")){

Intent vIt = new Intent("android.intent.action.SEND_MULTIPLE");

vIt.setPackage("com.whatsapp");

vIt.setType("text/plain");

if(!Util.IsNullOrEmpty(text)){

vIt.putExtra(Intent.EXTRA_TEXT, text);

vIt.putExtra(Intent.EXTRA_SUBJECT, "Subject");

}

ctx.startActivity(vIt);

sendOk = true;

}

return sendOk;

}

对照下Manifest,应该就一目了然了,总体上,通过这个例子,应该能对Intent和Intent Filter有了更进一步的认识了。

如何将消息发送给Whatsapp联系人的更多相关文章

  1. RabbitMQ中,exchange1绑定exchange2,exchange1和exchange2都绑定queue1,此时消息发送给exchange1,queue1中有几条消息

    如题: 存在两个交换器 exchange1,exchange2 存在一个队列 queue1 存在三个绑定关系:exchange1绑定exchange2 ,exchange1绑定queue1,excha ...

  2. C#实现发送给QQ邮件

    最近在做一个通过点击忘记密码往用户邮箱中发邮件(邮件内容是一个超链接)点击进行修改的功能,发送原理,我们只是把邮件发送给smtp服务器,然后再由smtp服务器发送到邮箱,发送之前要校验一下. 1.微软 ...

  3. 小记---------maxwell 一个可以实时读取mysql二进制日志binlog,并生成JSON格式的消息,作为生产者发送给kafka,Redis,文件或其他平台的应用程序

    maxwell主要提供了下列功能     支持 SELECT * FROM table 的方式进行全量数据初始化     支持在主库发生failover后,自动回复binlog位置(GTID)     ...

  4. rabbitmq作为mqtt服务器实现websocket消息推送给浏览器

    rabbitmq的RabbitMQ Web MQTT插件可以用来支持将rabbitmq作为MQTT协议的服务器,而websocket支持mqtt协议通信实现消息推送.因为我们目前使用rabbitmq, ...

  5. 9-51单片机ESP8266学习-AT指令(单片机采集温湿度数据通过8266发送给AndroidTCP客户端显示)

    http://www.cnblogs.com/yangfengwu/p/8798512.html 补充:今天答应了一个朋友写一下如果单片机发过的是字符串应该怎么解析,答应了今天写,哦哦哦是明天了,闲话 ...

  6. 8-51单片机ESP8266学习-AT指令(单片机采集温湿度数据通过8266发送给C#TCP客户端显示)

    http://www.cnblogs.com/yangfengwu/p/8785516.html 先写单片机端的程序 先把源码和资料链接放到这里 链接: https://pan.baidu.com/s ...

  7. 理解SetCapture、ReleaseCapture、GetCapture(控制了消息发往哪个窗口,是理解消息的关键)

    理解SetCapture.ReleaseCapture.GetCapture 正常情况下,鼠标指针位于哪个窗口区域内,鼠标消息就自动发给哪个窗口.如果调用了SetCapture,之后无论鼠标的位置在哪 ...

  8. 理解SetCapture、ReleaseCapture、GetCapture(控制了消息发往哪个窗口,即消息窗口)

    理解SetCapture.ReleaseCapture.GetCapture 正常情况下,鼠标指针位于哪个窗口区域内,鼠标消息就自动发给哪个窗口.如果调用了SetCapture,之后无论鼠标的位置在哪 ...

  9. 关于emoji表情,支持在app端发送web端显示,web端发送给app端显示,web与wap端互相显示。

    要用到emoji.js和emoji.jquery.js两个插件配合实现三端互通. 1.app端发送的emoji表情----到服务器---服务器存储的是‘问号’,无法显示如图所示: 后台的同学也试验了网 ...

随机推荐

  1. NoClassDefFoundError: org/apache/commons/pool/impl/GenericObjectPool

    错误:Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/pool/impl ...

  2. 使用qsort对结构体的数据排序

    1007 DNA 排序 题目大意: 序列“未排序程度”的一个计算方式是元素乱序的元素对个数.例如:在单词序列“DAABEC'”中,因为D大于右边四个单词,E大于C,所以计算结果为5.这种计算方法称为序 ...

  3. kindle paperwhite折腾记

    在亚马逊官网上买了一个kindle paperwhite 一代(849元) , 打算再买个皮套, 淘宝店  http://detail.tmall.com/item.htm?spm=a230r.1.1 ...

  4. css实现固定高度及未知高度文字垂直居中的完美解决方案

    在工作当中我们经常碰到类似于"固定高度文字垂直居中及未知高度垂直居中问题",或者 "图片垂直居中问题",而我们最容易会想到使用表格来垂直居中,或者如果是单行文字 ...

  5. SQL Server2008ldf文件太大

    --适用于SQL Server 2008的方法 USE [master] GO ALTER DATABASE RmyyHisDW SET RECOVERY SIMPLE WITH NO_WAIT GO ...

  6. cocos基础教程(5)数据结构介绍之cocos2d::Value

    1.概述 cocos2d::Valie 是一个包含了很多原生类型(int,float,double,bool,unsigned char,char* 和 std::string)外加 std::vec ...

  7. 使用python在SAE上搭建一个微信应用,使用有道翻译的api进行在线翻译

    1. 准备,先在使用python一步一步搭建微信公众平台(一)中基本实现自动回复的功能后,接着在有道词典上申请一个key,http://fanyi.youdao.com/openapi?path=da ...

  8. Python ===if while for语句 以及一个小小网络爬虫实例

    if分支语句 >>> count=89 >>> if count==89: print count 89                          #单分支 ...

  9. Ninth scrum meeting - 2015/11/3

    今天课上老师询问了每个团队的进度,我们发现有好多团队都已经基本完成了, 距离预定的alpha版本开发完成时间也越来越近了,我们的工作也都在有条不紊的进行着.今天又出现了git pull时有冲突的情况, ...

  10. 第17章 使用iSCSI服务部署网络存储

    章节概述: 本章节将分析SCSI与iSCSI技术结构的不同,了解iSCSI技术的优势.SAN存储网络技术结构以及iSCSI HBA卡的作用. 完整演示部署iSCSI target服务程序的方法流程:创 ...