Android郵件傳送詳解

weixin_33831673發表於2015-06-16

轉載:http://flysnow.iteye.com/blog/1128354

Android中我為什麼發不了郵件???我手機裡明明有郵件客戶端的,可我為什麼不能呼叫它傳送郵件???相信這是很多人會問的問題,手機裡有Email客戶端,可是偏偏在自己的應用裡呼叫不了,抑或是不知道怎麼呼叫,還有的是一直認為自己寫對了,可是偏偏不能呼叫,無奈之下只能卻網上找段程式碼貼上上,ok,可以了。。可是你知道別人的程式碼為什麼可以?你知道呼叫Email是怎麼工作的嗎?如果你又像給多人發郵件,還想傳送附件,怎麼做?又迷糊了吧?所以需要搞懂原理才能一通百通,舉一反三,而這就是這篇博文要寫的,也是你可以在這篇博文中學到的。

我們新建一個工程SendEmail,基於Android1.6實現。然後定義佈局檔案和程式碼如下:

Xml程式碼:

[html] view plaincopy
 
 
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="fill_parent"  
  6.     >  
  7. <Button  
  8.     android:id="@+id/send_btn"    
  9.     android:layout_width="fill_parent"   
  10.     android:layout_height="wrap_content"   
  11.     android:text="Send Action"  
  12.     />  
  13. </LinearLayout>  


Java程式碼:

[java] view plaincopy
 
 
  1.  /** 傳送郵件測試介面 
  2.  * */  
  3. public class SendEmailActivity extends Activity implements View.OnClickListener{  
  4.     private Button mSendBtn;  
  5.     /** Called when the activity is first created. */  
  6.     @Override  
  7.     public void onCreate(Bundle savedInstanceState) {  
  8.         super.onCreate(savedInstanceState);  
  9.         setContentView(R.layout.main);  
  10.         mSendBtn=(Button)findViewById(R.id.send_btn);  
  11.         mSendBtn.setOnClickListener(this);  
  12.     }  
  13.     @Override  
  14.     public void onClick(View v) {  
  15.         switch(v.getId()){  
  16.         case R.id.send_btn:  
  17.             startSendEmailIntent();  
  18.             break;  
  19.         }  
  20.     }  
  21.     private void startSendEmailIntent(){  
  22.         Intent data=new Intent(Intent.ACTION_SENDTO);  
  23.         data.setData(Uri.parse("mailto:qq10000@qq.com"));  
  24.         data.putExtra(Intent.EXTRA_SUBJECT, "這是標題");  
  25.         data.putExtra(Intent.EXTRA_TEXT, "這是內容");  
  26.         startActivity(data);  
  27.     }  
  28. }  


這是我們執行應用,點選按鈕就會看到如下效果:



 

 

分析傳送程式碼 

 

主要的傳送程式碼如下:

[java] view plaincopy
 
 
  1. Intent data=new Intent(Intent.ACTION_SENDTO);  
  2. data.setData(Uri.parse("mailto:qq10000@qq.com"));  
  3. data.putExtra(Intent.EXTRA_SUBJECT, "這是標題");  
  4. data.putExtra(Intent.EXTRA_TEXT, "這是內容");  
  5. startActivity(data);  


 

  1.  首先構造一個Action為SENDTO的Action
  2. 其次建立一個Uri,他是一個mailto的郵件連結,也就是接收地址.
  3. 再通過Intent.EXTRA_SUBJECT和Intent.EXTRA_TEXT傳遞標題和文字的資料,記住,一定要使用這些常量,這是標準,否則Email客戶端不認識,那樣你傳遞的標題和文字就不起作用了。
  4. 然後就是startActivity進行開啟,系統會根據Intent自動匹配找到能處理這個intent的應用,如圖列表,有很多個,我們這裡選擇網易掌上郵,就開啟了一個郵件傳送介面,如我們所願,郵件地址、標題和內容都在了,很成功.
  5. intent中的資料傳遞是以Extra的方式進行put後傳遞的,然後在使用的時候getter取出使用。

傳送給多人以及抄送和密送

傳送給多人以及抄送和密送都很簡單,查詢Intent類中的Extra常量,傳送有這麼三個常量:Intent.EXTRA_EMAIL,Intent.EXTRA_CC,Intent.EXTRA_BCC。這三個分別用於傳遞“接受人地址列表”、“抄送人地址列表”和“密送人地址列表”,傳遞的都是String[]型別的Email地址,如果陣列中有多個地址,就可以傳送給多人。傳送的函式修改如下,我們看下效果:

[java] view plaincopy
 
 
  1. private void startSendEmailIntent(){  
  2.         Intent data=new Intent(Intent.ACTION_SENDTO);  
  3.         data.setData(Uri.parse("mailto:qq10000@qq.com"));  
  4.         data.putExtra(Intent.EXTRA_EMAIL, new String[]{"ls8707@163.com","ls8708@163.com"});  
  5.         data.putExtra(Intent.EXTRA_CC, new String[]{"ls8709@163.com"});  
  6.         data.putExtra(Intent.EXTRA_BCC, new String[]{"ls810@163.com"});  
  7.         data.putExtra(Intent.EXTRA_SUBJECT, "這是標題");  
  8.         data.putExtra(Intent.EXTRA_TEXT, "這是內容");  
  9.         startActivity(data);  
  10.     }  


 


傳送附件

Email'客戶端的傳送Activity提供了兩個Intent Filter,一個用於傳送普通郵件,一個使用者傳送帶有附件的郵件。區分很很容易的,傳送普通郵件的那個Intent Filter配置的Action SENDTO,而帶有附件的郵件則是SEND,所以是2個不一樣,但是哪些比如附加“標題”,“內容”,“抄送”,“傳送多人”等等還是通用的。佈局檔案新增一個按鈕,用於傳送帶有附件的郵件,Activity程式碼也做修改。

 

[html] view plaincopy
 
 
  1. <Button  
  2.     android:id="@+id/send_to_btn"    
  3.     android:layout_width="fill_parent"   
  4.     android:layout_height="wrap_content"   
  5.     android:text="SendTo Action"/>  


 

[java] view plaincopy
 
 
  1.  /* * 傳送郵件測試介面 
  2.  * @author 飛雪無情 個人部落格:http://flysnow.iteye.com/ 
  3.  * @since 2011-7-19 
  4.  */  
  5. public class SendEmailActivity extends Activity implements View.OnClickListener{  
  6.     private Button mSendBtn;  
  7.     private Button mSendToBtn;  
  8.     /** Called when the activity is first created. */  
  9.     @Override  
  10.     public void onCreate(Bundle savedInstanceState) {  
  11.         super.onCreate(savedInstanceState);  
  12.         setContentView(R.layout.main);  
  13.         mSendBtn=(Button)findViewById(R.id.send_btn);  
  14.         mSendToBtn=(Button)findViewById(R.id.send_to_btn);  
  15.         mSendBtn.setOnClickListener(this);  
  16.         mSendToBtn.setOnClickListener(this);  
  17.     }  
  18.     @Override  
  19.     public void onClick(View v) {  
  20.         switch(v.getId()){  
  21.         case R.id.send_btn:  
  22.             startSendEmailIntent();  
  23.             break;  
  24.         case R.id.send_to_btn:  
  25.             startSendToEmailIntent();  
  26.             break;  
  27.         }  
  28.     }  
  29.     private void startSendEmailIntent(){  
  30.         Intent data=new Intent(Intent.ACTION_SENDTO);  
  31.         data.setData(Uri.parse("mailto:qq10000@qq.com"));  
  32.         data.putExtra(Intent.EXTRA_EMAIL, new String[]{"ls8707@163.com","ls8708@163.com"});  
  33.         data.putExtra(Intent.EXTRA_CC, new String[]{"ls8709@163.com"});  
  34.         data.putExtra(Intent.EXTRA_BCC, new String[]{"ls810@163.com"});  
  35.         data.putExtra(Intent.EXTRA_SUBJECT, "這是標題");  
  36.         data.putExtra(Intent.EXTRA_TEXT, "這是內容");  
  37.         startActivity(data);  
  38.     }  
  39.     private void startSendToEmailIntent(){  
  40.         Intent data=new Intent(Intent.ACTION_SEND);  
  41.         data.putExtra(Intent.EXTRA_EMAIL, new String[]{"ls8707@163.com"});  
  42.         data.putExtra(Intent.EXTRA_SUBJECT, "這是標題");  
  43.         data.putExtra(Intent.EXTRA_TEXT, "這是內容");  
  44.         data.putExtra(Intent.EXTRA_STREAM, Uri.parse(""));  
  45.         data.setType("text/plain");  
  46.         startActivity(data);  
  47.     }  
  48. }  


執行應用,我們看到效果圖裡最小面的附件標識,說明已經可以傳送附件了.


 

傳送附件最重要的就是Action必須為SEND,type一定要設定setType(""),還要為Intent.EXTRA_STREAM賦值,型別為Uri,一個附件的Uri。這樣才能傳送附件。

客戶端Email應用的傳送Activity配置

           這是Android1.6自帶Email客戶端的配置,如下:

 

[html] view plaincopy
 
 
  1. <activity  
  2.             android:name=".activity.MessageCompose"  
  3.             android:label="@string/app_name"  
  4.             android:enabled="false"  
  5.             >  
  6.             <intent-filter>  
  7.                 <action android:name="android.intent.action.VIEW" />  
  8.                 <action android:name="android.intent.action.SENDTO" />  
  9.                 <data android:scheme="mailto" />  
  10.                 <category android:name="android.intent.category.DEFAULT" />  
  11.                 <category android:name="android.intent.category.BROWSABLE" />  
  12.             </intent-filter>  
  13.             <intent-filter android:label="@string/app_name">  
  14.                 <action android:name="android.intent.action.SEND" />  
  15.                 <data android:mimeType="text/plain" />  
  16.                 <data android:mimeType="image/*" />  
  17.                 <data android:mimeType="video/*" />  
  18.                 <category android:name="android.intent.category.DEFAULT" />  
  19.             </intent-filter>  
  20.         </activity>  

從以上程式碼總結:

 

  1. 一個Activity定義了2個Intent Filter用於傳送不同型別郵件。
  2. SENDTO傳送普通郵件,SEND可以傳送普通和帶有附件的,不過最好主要用於傳送附件。
  3. 使用SENDTO時,必須為Intent設定Data,也就是Uri,內容為"mailto:emailaddr",否則不能匹配,因為有schema必須為mailto的限制
  4. 使用SEND時必須要設定type,也就是使用setType()方法,type只能為以前xml定義的4個。不過我測試了text/*也可以,其他的沒測試.
  5. 傳送附件只能使用SEND這個Action.
 
 
 
附加Email客戶端中提取Email地址,抄送,標題,附件等資訊的原始碼分析.
[java] view plaincopy
 
 
  1. void initFromIntent(Intent intent) {  
  2.           
  3.         //提取接受人地址列表  
  4.         String[] extraStrings = intent.getStringArrayExtra(Intent.EXTRA_EMAIL);  
  5.         if (extraStrings != null) {  
  6.             addAddresses(mToView, extraStrings);  
  7.         }  
  8. //提取抄送人地址列表  
  9.         extraStrings = intent.getStringArrayExtra(Intent.EXTRA_CC);  
  10.         if (extraStrings != null) {  
  11.             addAddresses(mCcView, extraStrings);  
  12.         }  
  13. //提取密送人地址列表  
  14.         extraStrings = intent.getStringArrayExtra(Intent.EXTRA_BCC);  
  15.         if (extraStrings != null) {  
  16.             addAddresses(mBccView, extraStrings);  
  17.         }  
  18. //提取標題  
  19.         String extraString = intent.getStringExtra(Intent.EXTRA_SUBJECT);  
  20.         if (extraString != null) {  
  21.             mSubjectView.setText(extraString);  
  22.         }  
  23.   
  24.         //提取Uri中的接受人地址  
  25.         final Uri dataUri = intent.getData();  
  26.         if (dataUri != null) {  
  27.             if ("mailto".equals(dataUri.getScheme())) {  
  28.                 initializeFromMailTo(dataUri.toString());  
  29.             } else {  
  30.                 String toText = dataUri.getSchemeSpecificPart();  
  31.                 if (toText != null) {  
  32.                     addAddresses(mToView, toText.split(","));  
  33.                 }  
  34.             }  
  35.         }  
  36.   
  37.        //提取郵件內容  
  38.           
  39.         CharSequence text = intent.getCharSequenceExtra(Intent.EXTRA_TEXT);  
  40.         if (text != null) {  
  41.             mMessageContentView.setText(text);  
  42.         }  
  43.           
  44.       //提取附件,可以看出Action必須是SEND.EXTRA_STREAM中有資料  
  45.      //type不能為null,這樣才能提取倒附件.  
  46.           
  47.         if (Intent.ACTION_SEND.equals(intent.getAction()) && intent.hasExtra(Intent.EXTRA_STREAM)) {  
  48.             String type = intent.getType();  
  49.             Uri stream = (Uri) intent.getParcelableExtra(Intent.EXTRA_STREAM);  
  50.             if (stream != null && type != null) {  
  51.                 if (MimeUtility.mimeTypeMatches(type, Email.ACCEPTABLE_ATTACHMENT_SEND_TYPES)) {  
  52.                     addAttachment(stream);  
  53.                 }  
  54.             }  
  55.         }  
  56.           
  57.         // Finally - expose fields that were filled in but are normally hidden, and set focus  
  58.           
  59.         if (mCcView.length() > 0) {  
  60.             mCcView.setVisibility(View.VISIBLE);  
  61.         }  
  62.         if (mBccView.length() > 0) {  
  63.             mBccView.setVisibility(View.VISIBLE);  
  64.         }  
  65.         setNewMessageFocus();  
  66.         mDraftNeedsSaving = false;  
  67.     }  

相關文章