(因爲本人喜歡word文檔編輯,不喜歡網絡編輯,因此仍然提供pdf版文檔,方便查閱http://files.cnblogs.com/franksunny/send_msg_to_Whatsapp.pdf)html
Whatsapp官網上沒有找到在Android上進行消息發送相關的信息,可是有一個iOS相關的帖子https://www.whatsapp.com/faq/iphone/23559013,原覺得用它的URL在Android上也是可使用的,結果試了下不行,看來錯誤地把URL看成URI了。android
後來根據Android Intent和Intent Filters的官方文檔說明(若是英文不太好,參考中文的翻譯文檔,連接爲下面的第二個地址):網絡
http://developer.android.com/guide/components/intents-filters.htmlapp
http://wiki.eoe.cn/page/Intents_and_Intent_Filters.html#commentiphone
就想着查看了下Whatsapp的Manifest配置文件,看看能不能找出點蛛絲馬跡,結果發現有以下的Activity信息ide
<activity測試
android:name=".ContactPicker"ui
android:configChanges="0x00000FB0"this
<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有了更進一步的認識了。