我正在尝试开发一款应用程序,该应用程序从不是Google的POP3服务器获取电子邮件,而且我遇到了很多问题。
我正在使用JavaMail库并遵循TutorialsPoint教程。他们的pop3示例在Eclipse /桌面上工作正常,但是当我在Android上移动代码时,它永远无法工作,我很沮丧。
在logcat中,我得到了所有大量的错误,其中首先说明了
W / System.err:android.os.NetworkOnMainThreadException即使我正在使用AsyncTask(可能不正确)。
有没有办法可以修复AsyncTask才能正常工作?
另外,有没有办法让我可以做这样的事情而不使用像K-9 Mail这样的专业应用程序?
有人感兴趣的代码:
public class FetchPop extends AsyncTask{
public static void fetch(String pop3Host, String storeType, String user,
String password) {
try {
// create properties field
Properties properties = new Properties();
properties.put("mail.store.protocol", "pop3");
properties.put("mail.pop3.host", pop3Host);
properties.put("mail.pop3.port", "995");
properties.put("mail.pop3.starttls.enable", "true");
Session emailSession = Session.getDefaultInstance(properties);
// emailSession.setDebug(true);
// create the POP3 store object and connect with the pop server
Store store = emailSession.getStore("pop3s");
store.connect(pop3Host, user, password);
// create the folder object and open it
Folder emailFolder = store.getFolder("INBOX");
emailFolder.open(Folder.READ_ONLY);
BufferedReader reader = new BufferedReader(new InputStreamReader(
System.in));
// retrieve the messages from the folder in an array and print it
Message[] messages = emailFolder.getMessages();
Log.d("No. messages:", messages.length + ""); //just the number at first
/*for (int i = 0; i < messages.length; i++) {
Message message = messages[i];
writePart(message);
String line = reader.readLine();
if ("YES".equals(line)) {
message.writeTo(System.out);
} else if ("QUIT".equals(line)) {
break;
}
}*/
// close the store and folder objects
emailFolder.close(false);
store.close();
} catch (NoSuchProviderException e) {
e.printStackTrace();
} catch (MessagingException e) {
e.printStackTrace();
} /*catch (IOException e) {
e.printStackTrace();
}*/ catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected Object doInBackground(Object[] params) {
String host = "pop.gmail.com";// I tried google's pop
String mailStoreType = "pop3";
String username =
"myusername";// change accordingly
String password = "notmyrealpass";// change accordingly
//Call method fetch
fetch(host, mailStoreType, username, password);
Log.d("mytag","done!");
return null;
}
public void GO() {
doInBackground(null);
}
/*
* This method checks for content-type
* based on which, it processes and
* fetches the content of the message
*/
public static void writePart(Part p) throws Exception {
if (p instanceof Message)
//Call methos writeEnvelope
writeEnvelope((Message) p);
/* System.out.println("----------------------------");
System.out.println("CONTENT-TYPE: " + p.getContentType());*/
//check if the content is plain text
if (p.isMimeType("text/plain")) {
System.out.println("This is plain text");
System.out.println("---------------------------");
System.out.println((String) p.getContent());
}
//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
int i;
byte[] bArray = new byte[0];
System.out.println("x.length = " + x.available());
while ((i = (int) ((InputStream) x).available()) > 0) {
int result = (int) (((InputStream) x).read(bArray));
if (result == -1)
i=0;
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());
}
}
}
/*
* This method would print FROM,TO and SUBJECT of the message
*/
public static void writeEnvelope(Message m) throws Exception {
System.out.println("This is the message envelope");
System.out.println("---------------------------");
Address[] a;
// FROM
if ((a = m.getFrom()) != null) {
for (int j = 0; j < a.length; j++)
System.out.println("FROM: " + a[j].toString());
}
// TO
if ((a = m.getRecipients(Message.RecipientType.TO)) != null) {
for (int j = 0; j < a.length; j++)
System.out.println("TO: " + a[j].toString());
}
// SUBJECT
if (m.getSubject() != null)
System.out.println("SUBJECT: " + m.getSubject());
}
}
答案 0 :(得分:0)
尝试使用此库https://code.google.com/p/javamail-android/。
不知道lib的确切状态,但是他们在这个博客(http://www.jondev.net/articles/Sending_Emails_without_User_Intervention_%28no_Intents%29_in_Android)中有一个很好的例子,他们说
“这是JavaMail API的特殊版本,专门为Android编写。”
答案 1 :(得分:0)
看起来你没有正确使用AsyncTask,特别是看到你有一个直接调用GO()
的{{1}}方法。删除doInBackground()
方法,不需要它。
执行AsyncTask的正确方法是使用GO()
方法,该方法调用execute()
并在工作线程上运行它,这将消除您doInBackground()
运行时错误到目前为止。
因此,除了使用特定于Android的库之外,还要修复AsyncTask,以便它实际在工作线程而不是主UI线程中运行NetworkOnMainThreadException
方法。
一般来说,最好使用泛型和变量而不是让doInBackground()
将doInBackground()
作为参数。
每次执行AsyncTask时都能传递用户名和密码也很有用,所以请使用String varargs参数。
Object[]
然后,要正确执行AsyncTask,请使用public class FetchPop extends AsyncTask<String, Void, Void> {
@Override
protected Void doInBackground(String... params) {
String host = "pop.gmail.com";// I tried google's pop
String mailStoreType = "pop3";
String username = params[0]; //passed in through the execute() method
String password = params[1]; //passed in through the execute() method
//Call method fetch
fetch(host, mailStoreType, username, password);
Log.d("mytag", "done!");
return null;
}
}
方法,并传入用户名和密码:
execute()
另请注意,任何与UI相关的代码都需要放在 //First get the username and password from the user through the UI
String user = "myusername"; // change accordingly
String pass = "notmyrealpass"; // change accordingly
new FetchPop().execute(user, pass);
中,因为所有UI任务都需要在Android的主UI线程上执行。
有关AsyncTasks的更多常规信息,this question and the answers posted
中有很多有用的信息