題前語
????Android系統(tǒng)的開源性使其在當前智能手機市場占據(jù)絕對優(yōu)勢,同時也產(chǎn)生了各種各樣的機型和系統(tǒng)。這使得我們Android開發(fā)人員需要根據(jù)不同的機型和系統(tǒng)去做對應的適配。
正文
????本篇所述需求為調(diào)用本地郵件客戶端發(fā)送帶有附件的郵件。
第一種常規(guī)調(diào)用郵件
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setData(Uri.parse("mailto:"));
intent.putExtra(Intent.EXTRA_EMAIL, "");
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file));
startActivity(Intent.createChooser(intent, "分享一下"));
????加載效果如下:

????我們看到第一種情況,我們標識的郵件(mailto),但是實際執(zhí)行卻成了分享文件,雖然其中也有郵件客戶端,但是卻增加了用戶的操作步驟,這樣的情況是產(chǎn)品經(jīng)理不可接受的,所以我們嘗試第二種方法。
第二種使用SENDTO來試試(網(wǎng)上多提倡此種方式)
Intent intent = new Intent(Intent.ACTION_SENDTO);
intent.setData(Uri.parse("mailto:"));
intent.putExtra(Intent.EXTRA_EMAIL, "");
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file));
startActivity(Intent.createChooser(intent, "分享一下"));
SENDTO代碼加載如下:

????SENDTO確實能調(diào)用郵箱客戶端,但是上面的截圖是“沒有應用可執(zhí)行此操作”。為什么說確實能調(diào)用呢,因為在有的機型上確實可以調(diào)用,但是華為平板卻沒有調(diào)起來。我們是不是就可以推測華為把Android系統(tǒng)郵箱相關(guān)標識改了呢?有興趣的同學可以去看看華為系統(tǒng)的源碼。既然這樣的方式不行,那么我們就繼續(xù)探索還有沒有其他的方法。
第三種方式SEND_MULTIPLE多附件發(fā)送
SENDTO是發(fā)送單個附件,而SEND_MULTIPLE卻是攜帶多個附件進行發(fā)送,下面我們來試試這一段代碼執(zhí)行的情況
Intent intent = new Intent(Intent.ACTION_SEND_MULTIPLE);
intent.setData(Uri.parse("mailto:"));
intent.putExtra(Intent.EXTRA_EMAIL, "");
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_STREAM, list);//Uri.fromFile(file)
startActivity(Intent.createChooser(intent, "分享一下"));
多附件執(zhí)行截圖如下:

????我們看到這個多附件的發(fā)送同第一種情況類似,調(diào)起了系統(tǒng)的所有郵件客戶端和藍牙,不過我們不需要調(diào)用這么多應用,那么我們就再試試其他的方式。
第四種直接調(diào)用應用
????相信肯定有直接能夠調(diào)用某個工具軟件的方式,我們直接用這種方式會不會能夠達到我們想要的效果呢?我們一起來試試
Intent intent = new Intent(android.content.Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_EMAIL, "");
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file));
intent.setClassName("com.android.email","com.android.email.activity.MessageCompose");
startActivity(Intent.createChooser(intent, "分享一下"));
????直接調(diào)用執(zhí)行效果截圖:

????這樣看我們是不是找?guī)讉€不同型號不同系統(tǒng)的手機,獲取對應的包名和Activity就可以達到我們想要的效果呢?答案是肯定的。并且經(jīng)過試用小米、紅米、三星、華為、榮耀、努比亞,發(fā)現(xiàn)可以實現(xiàn)需求。因為手上沒有魅族的機器所以還沒有在魅族的系統(tǒng)上嘗試過,有條件的同學可以試試,順便告知一下。我將萬分感謝。
最終代碼
????奉上最終代碼,因為一個類就可以解決了,就不在放Github了。
package com.hewc.sendmail;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.StrictMode;
import android.support.annotation.RequiresApi;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import java.io.File;
public class MainActivity extends AppCompatActivity {
private Context context;
private String filePath = "/storage/emulated/0/20.txt";
private static final String[] NARMAL_PHONE = {"com.android.email", "com.android.email.activity.MessageCompose"};
private static final String[] MIUI_PHONE = {"com.android.email", "com.kingsoft.mail.compose.ComposeActivity"};
private static final String[] SAMSUNG_PHONE = {"com.samsung.android.email.provider", "com.samsung.android.email.composer.activity.MessageCompose"};
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
context = this;
setContentView(R.layout.activity_main);
// android 7.0系統(tǒng)解決拍照的問題
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
builder.detectFileUriExposure();
TextView tv = findViewById(R.id.tv);
tv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
File file = new File(filePath);
try {
Intent intent = new Intent(android.content.Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_EMAIL, "");
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file));
if (getDeviceBrand().toUpperCase().contains("HONOR") || getDeviceBrand().toUpperCase().contains("HUAWEI") || getDeviceBrand().toUpperCase().contains("NUBIA")) {
intent.setClassName(NARMAL_PHONE[0], NARMAL_PHONE[1]);
} else if (getDeviceBrand().toUpperCase().contains("XIAOMI") || getDeviceBrand().toUpperCase().contains("XIAOMI")) {
intent.setClassName(MIUI_PHONE[0], MIUI_PHONE[1]);
} else if (getDeviceBrand().toUpperCase().contains("SAMSUNG")) {
intent.setClassName(SAMSUNG_PHONE[0], SAMSUNG_PHONE[1]);
}
startActivity(Intent.createChooser(intent, "分享一下"));
} catch (Exception e) {
e.printStackTrace();
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setData(Uri.parse("mailto:"));
intent.putExtra(Intent.EXTRA_EMAIL, "");
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file));
startActivity(Intent.createChooser(intent, "分享一下"));
}
}
});
}
/**
* 獲取手機廠商
*
* @return 手機廠商
*/
public static String getDeviceBrand() {
Log.e("--獲取手機廠商--:", android.os.Build.BRAND);
return android.os.Build.BRAND;
}
}
????關(guān)于獲取第三方應用Activity名稱的方法:
????adb shell dumpsys activity | findstr "mFocusedActivity"
題后語
????第一次嘗試寫技術(shù)文檔,難免會有瑕疵,希望同學們能夠積極指正。能幫到你是我的榮幸。