如何将消息发送给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. web漏洞总结

    目录: 1.sql注入获取数据库信息2.sql注入绕过管理后台登录3.反射型xss4.存储型xss5.csrf6.文件上传7.暴力破解8.目录遍历9.权限跨越10.文件包含11.未知漏洞 web漏洞演 ...

  2. JavaScript由单价、数量计算总价

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  3. TFS2008解除独占式锁定文件命令(转载)

    使用场景:如果项目团队成员A对项目某个文件以独占式方式签出,恰好那天该成员A没有来上班而成员需要对此文件进入修改并check in,这时需要先把A对该文件的锁定解除.没有IDE可以使用,只能使用下面的 ...

  4. html5摇一摇[转]

    写在前面 年底了,有些公司会出一个摇奖的活动,今天在家没事就搜了一下这方面的资料. 原文地址:http://www.cnblogs.com/waitingbar/p/4682215.html 测试 效 ...

  5. 不起眼却有大作用的 .NET功能集(转发)

    http://www.cnblogs.com/powertoolsteam/p/top15features.html 目录 1. ObsoleteAttribute2. 设置默认值属性: Defaul ...

  6. 调用gluNurbsCurve绘制圆弧

    <OpenGL编程指南>第12章第3小结专门介绍调用GLU绘制NURBS曲线或曲面,很可惜的是并未给出绘制圆弧的例子.网上可以找到很多绘制整个园的例子,却没圆弧例子,自己瞎折腾了2个礼拜, ...

  7. Dual Palindromes

    Dual PalindromesMario Cruz (Colombia) & Hugo Rickeboer (Argentina) A number that reads the same ...

  8. java工具类包

    Hutool 提供丰富的java方法,其maven引用 <dependency> <groupId>com.xiaoleilu</groupId> <arti ...

  9. (7)UI(基础对象)

    1.地图控件:   地图控件可支持导入Tiled地图编辑器导出的tmx格式文件,地图是制作游戏关卡地形图的控件,对于即时战略类型游戏的制作,为了使玩家流畅的切换游戏画面,经常会使用超过屏幕尺寸的地图. ...

  10. [Effective JavaScript 笔记]第51条:在类数组对象上复用通用的数组方法

    前面有几条都讲过关于Array.prototype的标准方法.这些标准方法被设计成其他对象可复用的方法,即使这些对象并没有继承Array. arguments对象 在22条中提到的函数argument ...