如何将消息发送给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. photoshop几个基本技巧

    原文地址:http://blog.thmz.com/user1/936/archives/2008/20418.htm 去除文字的几种方法: 1.访印图章工具 2.修补工具 3.修复画笔工具 4.画笔 ...

  2. 连接oracle读取数据

    没怎么用过oracle,而且是在地税内网内部估计是防火墙的原因虚拟机里也连不上oracle,刚开始费了很多周折查找问题,现在又放弃使用直连数据库了,记下来以备后用吧 public class Load ...

  3. Nonove js timer 计时器

    <html> <head> <title> Nonove js timer 计时器 </title> </head> <body> ...

  4. 搭建SpringMVC+Mybatis框架并实现数据库的操作

    User类 public class User { private Integer id; private String userName; private String password; priv ...

  5. [转]uses-permission权限列表

    android.permission.ACCESS_CHECKIN_PROPERTIES允许读写访问”properties”表在checkin数据库中,改值可以修改上传 android.permiss ...

  6. Ubuntu nginx: [emerg] bind() to 0.0.0.0:80 failed (13: Permission denied)

    在Ubuntu 12中启动刚安装好的Nginx,报错: nginx: [emerg] bind() to 0.0.0.0:80 failed (13: Permission denied) 原因如下: ...

  7. Nginx反向代理 负载均衡

    nginx 这个轻量级.高性能的 web server 主要可以干两件事情: 〉直接作为http server(代替apache,对PHP需要FastCGI处理器支持): 〉另外一个功能就是作为反向代 ...

  8. 淘宝(阿里百川)手机客户端开发日记第四篇 自定义ListView详解

    我们知道,如果采用官方的ListView,实现的功能在很多时候,并不能满足自己的业务需求,比如在设计到复杂的列表的时候,这一节,我们就开始动手自己实现自定义的ListView. 在上一节中,我们采用了 ...

  9. NGUI 新版操作教程

    http://www.tasharen.com/forum/index.php?topic=6754

  10. [BZOJ1171][BZOJ2892]大sz的游戏

    [BZOJ1171][BZOJ2892]大sz的游戏 试题描述 大sz最近在玩一个由星球大战改编的游戏.话说绝地武士当前共控制了N个星球.但是,西斯正在暗处悄悄地准备他们的复仇计划.绝地评议会也感觉到 ...