如何将消息发送给Whatsapp联系人
如何将消息发送给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联系人的更多相关文章
- RabbitMQ中,exchange1绑定exchange2,exchange1和exchange2都绑定queue1,此时消息发送给exchange1,queue1中有几条消息
如题: 存在两个交换器 exchange1,exchange2 存在一个队列 queue1 存在三个绑定关系:exchange1绑定exchange2 ,exchange1绑定queue1,excha ...
- C#实现发送给QQ邮件
最近在做一个通过点击忘记密码往用户邮箱中发邮件(邮件内容是一个超链接)点击进行修改的功能,发送原理,我们只是把邮件发送给smtp服务器,然后再由smtp服务器发送到邮箱,发送之前要校验一下. 1.微软 ...
- 小记---------maxwell 一个可以实时读取mysql二进制日志binlog,并生成JSON格式的消息,作为生产者发送给kafka,Redis,文件或其他平台的应用程序
maxwell主要提供了下列功能 支持 SELECT * FROM table 的方式进行全量数据初始化 支持在主库发生failover后,自动回复binlog位置(GTID) ...
- rabbitmq作为mqtt服务器实现websocket消息推送给浏览器
rabbitmq的RabbitMQ Web MQTT插件可以用来支持将rabbitmq作为MQTT协议的服务器,而websocket支持mqtt协议通信实现消息推送.因为我们目前使用rabbitmq, ...
- 9-51单片机ESP8266学习-AT指令(单片机采集温湿度数据通过8266发送给AndroidTCP客户端显示)
http://www.cnblogs.com/yangfengwu/p/8798512.html 补充:今天答应了一个朋友写一下如果单片机发过的是字符串应该怎么解析,答应了今天写,哦哦哦是明天了,闲话 ...
- 8-51单片机ESP8266学习-AT指令(单片机采集温湿度数据通过8266发送给C#TCP客户端显示)
http://www.cnblogs.com/yangfengwu/p/8785516.html 先写单片机端的程序 先把源码和资料链接放到这里 链接: https://pan.baidu.com/s ...
- 理解SetCapture、ReleaseCapture、GetCapture(控制了消息发往哪个窗口,是理解消息的关键)
理解SetCapture.ReleaseCapture.GetCapture 正常情况下,鼠标指针位于哪个窗口区域内,鼠标消息就自动发给哪个窗口.如果调用了SetCapture,之后无论鼠标的位置在哪 ...
- 理解SetCapture、ReleaseCapture、GetCapture(控制了消息发往哪个窗口,即消息窗口)
理解SetCapture.ReleaseCapture.GetCapture 正常情况下,鼠标指针位于哪个窗口区域内,鼠标消息就自动发给哪个窗口.如果调用了SetCapture,之后无论鼠标的位置在哪 ...
- 关于emoji表情,支持在app端发送web端显示,web端发送给app端显示,web与wap端互相显示。
要用到emoji.js和emoji.jquery.js两个插件配合实现三端互通. 1.app端发送的emoji表情----到服务器---服务器存储的是‘问号’,无法显示如图所示: 后台的同学也试验了网 ...
随机推荐
- 兼容amd,commonjs和browser的模块写法
从uuid.js中抽出来的写法. (function() { var _global = this; // Export public API var obj = {}; obj.attr = fun ...
- Java I/O操作
按字节读取读取文件,并且将文件里面的内容写到另外一个文件里面去 public class CopyBytes { public static void main(String[] args) thro ...
- C#设计模式-1、适配器模式(Adapter Pattern)(转载)
概述 在软件系统中,由于应用环境的变化,常常需要将“一些现存的对象”放在新的环境中应用,但是新环境要求的接口是这些现存对象所不满足的.那么如何应对这种“迁移的变化”?如何既能利用现有对象的良好实现,同 ...
- mybatis中的resultMap
resultMap <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBL ...
- Iterator<转>
Iterator就是迭代器的意思. Iterator是一个接口,利用迭代器主要是获取元素,很少删除元素.有三个方法: 1)hasNext():判断是否有更多的元素,如果有返回true. 2 ...
- Hibernate3的DetachedCriteria支持
Hibernate3支持DetachedCriteria,这是一个非常有意义的特性!我们知道,在常规的Web编程中,有大量的动态条件查询,即用户在网页上面自由选择某些条件,程序根据用户的选择条件,动态 ...
- whereis命令
whereis命令只能用于程序名的搜索,而且只搜索二进制文件(参数-b).man说明文件(参数-m)和源代码文件(参数-s).如果省略参数,则返回所有信息. 和find相比,whereis查找的速度非 ...
- HTTP 304 的理解
304 的标准解释是:Not Modified 客户端有缓冲的文档并发出了一个条件性的请求(一般是提供If-Modified-Since头表示客户只想比指定日期更新的文档).服务器告诉客户,原来缓冲的 ...
- JSON 与 String、Map、JavaBean互转
JSON 与 String.Map.JavaBean互转 //解析远程登录用户信息 AttributePrincipal principal = AssertionHolder.getAssertio ...
- jQuery1.11源码分析(9)-----初始化jQuery对象的函数和关联节点获取函数
这篇也没什么好说的,初始化jQuery对象的函数要处理多种情况,已经被寒冬吐槽烂了.关联节点获取函数主要基于两个工具函数dir和sibling,前者基于指定的方向遍历,后者则遍历兄弟节点(真的不能合并 ...