我正在构建一个Android电子邮件客户端应用。我设法在RecylerView中显示电子邮件标题/发件人。接下来,我想开始一个新活动,当用户选择特定邮件时,该活动将显示电子邮件内容/附件。
我很难通过意图来做到这一点。我能够获取电子邮件的内容(文本,内嵌图像,附件),但我无法找到一种尽可能接近原始格式的方式。我想将文本放在StringBuilder中并通过意图发送它以显示文本,但这样我就无法在正确的位置显示内嵌图像,并且还存在格式问题。
对我应该采用的方式提出任何形式的指导都非常感激。
显示可用邮件列表并获取特定邮件内容的类,以便向其发送另一个用于显示邮件的活动。我知道代码有点危险,我尝试了很多方法,它远非最终形式。
public class CheckMail extends Activity {
static List<Message> messages = new ArrayList<>();
String[] sender;
String[] date;
String[] subject;
boolean[] seen;
Context context = null;
ListView listView;
Intent intent;
Store store;
StringBuilder content = new StringBuilder();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_check_mail);
if (android.os.Build.VERSION.SDK_INT > 9)
{
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}
context = this;
ReadEmails task = new ReadEmails();
task.execute();
}
public void writePart(Part p) throws Exception {
if (p instanceof Message)
this.writeEnvelope((Message) p);
//check if the content is plain text
if (p.isMimeType("text/plain")) {
content.append(p.getContent().toString());
}
//check if the content has attachment
else if (p.isMimeType("multipart/*")) {
System.out.println("This is a Multipart");
System.out.println("---------------------------");
Multipart mp = (Multipart) p.getContent();
int count = mp.getCount();
for (int i = 0; i < count; i++)
writePart(mp.getBodyPart(i));
}
//check if the content is a nested message
else if (p.isMimeType("message/rfc822")) {
System.out.println("This is a Nested Message");
System.out.println("---------------------------");
writePart((Part) p.getContent());
}
/*
//check if the content is an inline image
else if (p.isMimeType("image/jpeg")) {
System.out.println("--------> image/jpeg");
Object o = p.getContent();
InputStream x = (InputStream) o;
// Construct the required byte array
System.out.println("x.length = " + x.available());
while ((i = (int) ((InputStream) x).available()) > 0) {
int result = (int) (((InputStream) x).read(bArray));
if (result == -1)
int i = 0;
byte[] bArray = new byte[x.available()];
break;
}
FileOutputStream f2 = new FileOutputStream("/tmp/image.jpg");
f2.write(bArray);
}
else if (p.getContentType().contains("image/")) {
System.out.println("content type" + p.getContentType());
File f = new File("image" + new Date().getTime() + ".jpg");
DataOutputStream output = new DataOutputStream(
new BufferedOutputStream(new FileOutputStream(f)));
com.sun.mail.util.BASE64DecoderStream test =
(com.sun.mail.util.BASE64DecoderStream) p
.getContent();
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = test.read(buffer)) != -1) {
output.write(buffer, 0, bytesRead);
}
}
else {
Object o = p.getContent();
if (o instanceof String) {
System.out.println("This is a string");
System.out.println("---------------------------");
System.out.println((String) o);
}
else if (o instanceof InputStream) {
System.out.println("This is just an input stream");
System.out.println("---------------------------");
InputStream is = (InputStream) o;
is = (InputStream) o;
int c;
while ((c = is.read()) != -1)
System.out.write(c);
}
else {
System.out.println("This is an unknown type");
System.out.println("---------------------------");
System.out.println(o.toString());
}
}
*/
}
public void writeEnvelope(Message m) throws Exception {
System.out.println("This is the message envelope");
System.out.println("---------------------------");
Address[] a;
StringBuilder sender = new StringBuilder();
StringBuilder recipients = new StringBuilder();
String subject = "";
// FROM
if ((a = m.getFrom()) != null) {
for (int j = 0; j < a.length; j++)
sender.append(a[j].toString());
}
// TO
if ((a = m.getRecipients(Message.RecipientType.TO)) != null) {
for (int j = 0; j < a.length; j++)
recipients.append(a[j].toString());
}
// SUBJECT
if (m.getSubject() != null)
subject = m.getSubject();
intent.putExtra("Sender", sender.toString());
intent.putExtra("Recipients", recipients.toString());
intent.putExtra("Message", subject);
intent.putExtra("Date", m.getReceivedDate().toString());
}
class ReadEmails extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... params) {
// Create all the needed properties - empty!
Properties connectionProperties = new Properties();
// Create the session
Session session = Session.getDefaultInstance(connectionProperties, null);
try {
System.out.print("Connecting to the IMAP server...");
// Connecting to the server
// Set the store depending on the parameter flag value
store = session.getStore("imaps");
// Set the server depending on the parameter flag value
String server = "imap.gmail.com";
store.connect(server, "....@gmail.com", "password");
System.out.println("done!");
// Get the Inbox folder
Folder inbox = store.getFolder("Inbox");
// Set the mode to the read-only mode
inbox.open(Folder.READ_ONLY);
// Get messages
CheckMail.messages = Arrays.asList(inbox.getMessages());
System.out.println("Reading messages...");
sender = new String[messages.size()];
date = new String[messages.size()];
subject = new String[messages.size()];
seen = new boolean[messages.size()];
for (int i = 0; i < messages.size(); i++) {
try {
Address[] froms = messages.get(i).getFrom();
String email = froms == null ? null : ((InternetAddress) froms[0]).getAddress();
sender[i] = email;
date[i] = messages.get(i).getReceivedDate().toString();
subject[i] = messages.get(i).getSubject();
Flags flags = messages.get(i).getFlags();
Flags.Flag[] sf = flags.getSystemFlags();
for (int j = 0; j < sf.length; j++) {
if (sf[j] == Flags.Flag.SEEN)
seen[i] = true;
else
seen[i] = false;
}
} catch (MessagingException e) {
e.printStackTrace();
}
}
System.out.println("Done reading...");
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(String result) {
CustomListAdapter whatever = new CustomListAdapter((Activity) context, sender, date, subject, seen);
listView = (ListView) findViewById(R.id.listviewID);
listView.setAdapter(whatever);
listView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
try {
content.delete(0, content.length());
intent = new Intent(context, OpenMail.class);
writePart(messages.get(position));
intent.putExtra("Content", content.toString());
startActivity(intent);
}
catch (Exception e)
{e.printStackTrace();}
}
});
}
}
}
答案 0 :(得分:0)
由于没有人回答......我在某些应用中通过Javamail显示电子邮件。
我认为你已走上正轨,为列表和观众分别开展活动是一种很好的方法。 [或者单独的片段,因为在平板电脑上你可能想要在同一个屏幕上并排显示列表和正文]
可能出现的情侣问题:
我会谨慎地将电子邮件内容放在额外的内容中以启动活动和/或将其提交到查看器活动中保存的实例状态,因为存在大小限制[例如,1MB用于保存的实例状态Android 7 +]
在活动中的ASyncTask中下载电子邮件可能不是最好的方法。我不知道该应用程序的全部目的,但我认为无论用户是否等待,这都应该成功?如果他们的任务离开,ASyncTask将继续运行,但它将保持活动上下文,导致所谓的“临时内存泄漏”。最好将它放在一个服务中并在一个单独的线程中下载它。然而,在活动中将其作为概念证明是完全合理的......
我不认为在电子邮件列表活动中使用消息结构是最好的方法。在我的应用程序中,我在后台服务中下载电子邮件,并通过ContentProvider将数据提交到SQL-DB。在消息查看器屏幕上,使用名为CursorLoader的组件从ContentProvider / SQL-DB检索电子邮件正文。它处理后台中的所有加载,以便UI在加载大邮件时保持响应。但无论如何,我避免在活动之间传递消息体。
许多电子邮件都有HTML部分(multipart / alternative:text / plain&amp; text / html),因此查看器实现为WebView。 WebView以最小的努力制作了外观精美的电子邮件。
在检索邮件时偶然发现其他问题,请注意调用setPeek(true)。它将停止设置READ标志。对于GMail来说这不是问题,但是一些IMAP服务器会设置这个标志。如果除主电子邮件应用程序之外的任何应用程序更改READ标志,用户将会抱怨。也不要假设任何标题存在,垃圾邮件电子邮件因遗漏消息ID,主题和其他字段而臭名昭着。最后,可能值得考虑通过OAuth2实施身份验证,这将使您的应用程序能够通过Javamail连接到用户的GMail帐户,而无需他们的密码。
我不确定这些是否真的有帮助,因为它是一项相当大的工作,但一步一步......干杯!