如何将消息发送给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. android源代码提示文本框还能输入多少个字符

    public class TestAndroidActivity extends Activity { /** Called when the activity is first created. * ...

  2. 对称加密和分组加密中的四种模式(ECB、CBC、CFB、OFB)

    一. AES对称加密: AES加密 分组 二. 分组密码的填充 分组密码的填充 e.g.: PKCS#5填充方式 三. 流密码:   四. 分组密码加密中的四种模式: 3.1 ECB模式 优点: 1. ...

  3. UrlConnection连接和Socket连接的区别

    关于UrlConnection连接和Socket连接的区别,只知道其中的原理如下: 抽象一点的说,Socket只是一个供上层调用的抽象接口,隐躲了传输层协议的细节. urlconnection 基于H ...

  4. .net环境下从PDF文档中抽取Text文本的一些方法汇总

    1.PDFBox的IKVM版本:据我所知,目前只有PDFBox的IKVM版本能比较好地从PDF中提取文本,PDFBOX更多信息请访问http://www.pdbox.org,关于其应用实例,可以参考C ...

  5. 修改织梦默认提示"dedecms提示信息!"

    在使用dedecms搜索的时候如果搜索频率过快,经常会跳出一个提示窗口提示"管理员设定搜索时间间隔为*秒,请稍后再试!".怎么自定义Dedecms提示信息呢?让心存不轨的家伙少一个 ...

  6. 一次手工注入waf [转载]

    转载自sss安全论坛 目标站点:http://www.xxx.cn:88注入点:http://www.xxx.cn:88/new/details1.asp?n_id=49909对其进行检测:http: ...

  7. The Perfect Stall (incomplete)

    恩,一看就知道是一道二分图最大匹配的题. 感动得发现自己不会做..果然我是太弱了.学校里真是麻烦死,根本没有时间好吗. (NOIP)会不会感动地滚粗啊? 然后稍微看看,恩,匈牙利算法. 真是感动得落泪 ...

  8. Heap(堆)和stack(栈)有的区别是什么。

    java的内存分为两类,一类是栈内存,一类是堆内存.栈内存是指程序进入一个方法时,会为这个方法单独分配一块私属存储空间,用于存储这个方法内部的局部变量,当这个方法结束时,分配给这个方法的栈会释放,这个 ...

  9. 【云计算】Docker云平台—Docker进阶

    Docker云平台系列共三讲,此为第二讲:Docker进阶 参考资料: 五个Docker监控工具的对比:http://www.open-open.com/lib/view/open1433897177 ...

  10. Maven发布web项目到tomcat

    在java开发中经常要引入很多第三方jar包:然而无论是java web开发还是其他java项目的开发经常会由于缺少依赖包引来一些不必要的异常.常常也是因为这样的原因导致许多简单的缺包和版本问题耗费大 ...