Android:IntentService 未正确排队
我正在尝试使用意图服务在后台运行来发送带有相当大(1-2mb)图像附件的电子邮件。我是一名初学者,到目前为止,我已经通过在网络上研究了解了所有内容(因此您可能会看到一些类似的代码)。
发生的情况是,当我发送第一封电子邮件时,一切正常。然而,当我尝试在第一个仍在处理时发送另一个时,第一个被丢弃,第二个则正常。它始终会发送最新的排队意图并跳过前面的意图。
根据我所做的研究,IntentService 应该对传递给它的意图进行排队,并按顺序执行它们。这个问题:IntentService:如何正确入队?类似,但我不知道认为这完全适用于我的情况。
我确信我错过了一些愚蠢的东西=(
这是我启动服务的onActivityResult:
public void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.i(TAG, "Entered onActivityResult");
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_CANCELED) {
Log.i(TAG, "onActivityResult Canceled");
Toast toast = Toast.makeText(this,"Camera Canceled", 10000);
toast.show();
return;
}
if ((requestCode == CAMERA_PIC_REQUEST) && (resultCode == Activity.RESULT_OK)) {
Log.i(TAG, "onActivityResult Result OK");
String filePath = getOutputPath();
String order = getOrder();
Log.i(TAG, "Sending From: " + filePath);
Intent sendIntent = new Intent(this, MailIntentService.class);
sendIntent.putExtra(MailIntentService.IN_SUBJECT, order);
sendIntent.putExtra(MailIntentService.IN_PATH, filePath);
startService(sendIntent);
Toast.makeText(this, "Image Upload Started. Check Notification Bar for Status.", Toast.LENGTH_LONG).show();
}
}
这是整个IntentService:
public class MailIntentService extends IntentService {
//These set the parameters for the Email
public static final String destEmail = "hidden";
public static final String sendEmail = "hidden";
public static final String sendPass = "hidden";
public static final String body = "GrowerLive image upload request.";
public static final String IN_SUBJECT = "insub";
public static final String IN_PATH = "inpath";
//This is the standard tag for class name
private static final String TAG = MailIntentService.class.getSimpleName();
//These set up the parameters for notifications
private NotificationManager mNotificationManager;
private Notification notifyDetails;
private int NOTIFICATION_ID;
private CharSequence contentTitle = "Bethel Upload";
private CharSequence contentText = "Image Uploading...";
private String contentTicker = "Upload Started...";
public void onCreate() {
super.onCreate();
Log.i(TAG, "MailIntentService Created");
mNotificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
notifyDetails = new Notification(R.drawable.ic_launcher, contentTicker, System.currentTimeMillis());
}
public void onDestroy() {
super.onDestroy();
File dir = new File(Environment.getExternalStorageDirectory() + "/BethelUpload");
if (dir.isDirectory()) {
String[] children = dir.list();
for (int i = 0; i < children.length; i++) {
new File(dir, children[i]).delete();
}
}
Log.i(TAG, "MailIntentService Destroyed");
}
public MailIntentService() {
super(TAG);
}
@Override
protected void onHandleIntent(Intent intent) {
Context context = getApplicationContext();
Intent notifyIntent = new Intent(BethelUploadActivity.class.getSimpleName());
PendingIntent intentP = PendingIntent.getActivity(MailIntentService.this, 0, notifyIntent, android.content.Intent.FLAG_ACTIVITY_NEW_TASK);
notifyDetails.setLatestEventInfo(context, contentTitle, contentText, intentP);
try {
String subject = intent.getStringExtra(IN_SUBJECT);
String path = intent.getStringExtra(IN_PATH);
Log.i(TAG, "Sending Mail...");
Log.i(TAG, "Subject: " + subject);
Log.i(TAG, "Attachment Path: " + path);
mNotificationManager.notify(NOTIFICATION_ID, notifyDetails);
GMailSender sender = new GMailSender(sendEmail, sendPass);
sender.sendMail(subject, body, sendEmail, destEmail, path);
Log.i(TAG, "Mail Sent!");
contentText = "Image Uploaded Successfully";
contentTicker = "Upload Successful";
notifyDetails.setLatestEventInfo(context, contentTitle, contentText, intentP);
mNotificationManager.notify(NOTIFICATION_ID, notifyDetails);
}
catch (Exception e) {
Log.e(TAG, e.getMessage(), e);
}
}
}
这是我在此处另一个示例中使用的GMailSender:在 Android 中使用 JavaMail API 发送电子邮件而不使用默认/内置 !
public class GMailSender extends javax.mail.Authenticator {
private String mailhost = "smtp.gmail.com";
private String user;
private String password;
private Session session;
static {
Security.addProvider(new com.provider.JSSEProvider());
}
public GMailSender(String user, String password) {
this.user = user;
this.password = password;
Properties props = new Properties();
props.setProperty("mail.transport.protocol", "smtp");
props.setProperty("mail.host", mailhost);
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.port", "465");
props.put("mail.smtp.socketFactory.port", "465");
props.put("mail.smtp.socketFactory.class",
"javax.net.ssl.SSLSocketFactory");
props.put("mail.smtp.socketFactory.fallback", "false");
props.setProperty("mail.smtp.quitwait", "false");
session = Session.getDefaultInstance(props, this);
}
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(user, password);
}
public synchronized void sendMail(String subject, String body, String sender, String recipients, String fileAttachment) throws Exception {
try{
MimeMessage message = new MimeMessage(session);
message.setSender(new InternetAddress(sender));
message.setSubject(subject);
MimeBodyPart messageBodyPart = new MimeBodyPart();
messageBodyPart.setText(body);
Multipart multipart = new MimeMultipart();
multipart.addBodyPart(messageBodyPart);
messageBodyPart = new MimeBodyPart();
DataSource source = new FileDataSource(fileAttachment);
messageBodyPart.setDataHandler(new DataHandler(source));
messageBodyPart.setFileName("SodPhoto.jpg");
multipart.addBodyPart(messageBodyPart);
message.setContent(multipart);
if (recipients.indexOf(',') > 0)
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(recipients));
else
message.setRecipient(Message.RecipientType.TO, new InternetAddress(recipients));
Transport.send(message);
}catch(Exception e){
}
}
public class ByteArrayDataSource implements DataSource {
private byte[] data;
private String type;
public ByteArrayDataSource(byte[] data, String type) {
super();
this.data = data;
this.type = type;
}
public ByteArrayDataSource(byte[] data) {
super();
this.data = data;
}
public void setType(String type) {
this.type = type;
}
public String getContentType() {
if (type == null)
return "application/octet-stream";
else
return type;
}
public InputStream getInputStream() throws IOException {
return new ByteArrayInputStream(data);
}
public String getName() {
return "ByteArrayDataSource";
}
public OutputStream getOutputStream() throws IOException {
throw new IOException("Not Supported");
}
}
}
我知道这是大量的代码/文字墙,但我想我宁愿给你太多的信息,也不愿给你太少的信息,我真的很感谢你的时间
I am attempting to use an Intent Service to run in the background to send email with fairly large (1-2mb) image attachments. I am a beginner, and have learned everything so far by researching on the web (so you may see some similar code).
What happens is that when I send the first email, everything works fine. However when I attempt to send another while the first is still processing, the first is dropped and the second goes through fine. It will always send the most recent of the queued intents and skip the ones before it.
From the research I have done, IntentService is supposed to queue the intents passed to it, and execute them sequentially in order. This question: IntentService : How to enqueue correctly? is similar, but I don't think it applies to my situation exactly.
I am sure I am missing something dumb =(
This is the onActivityResult where I start the service:
public void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.i(TAG, "Entered onActivityResult");
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_CANCELED) {
Log.i(TAG, "onActivityResult Canceled");
Toast toast = Toast.makeText(this,"Camera Canceled", 10000);
toast.show();
return;
}
if ((requestCode == CAMERA_PIC_REQUEST) && (resultCode == Activity.RESULT_OK)) {
Log.i(TAG, "onActivityResult Result OK");
String filePath = getOutputPath();
String order = getOrder();
Log.i(TAG, "Sending From: " + filePath);
Intent sendIntent = new Intent(this, MailIntentService.class);
sendIntent.putExtra(MailIntentService.IN_SUBJECT, order);
sendIntent.putExtra(MailIntentService.IN_PATH, filePath);
startService(sendIntent);
Toast.makeText(this, "Image Upload Started. Check Notification Bar for Status.", Toast.LENGTH_LONG).show();
}
}
This is the entire IntentService:
public class MailIntentService extends IntentService {
//These set the parameters for the Email
public static final String destEmail = "hidden";
public static final String sendEmail = "hidden";
public static final String sendPass = "hidden";
public static final String body = "GrowerLive image upload request.";
public static final String IN_SUBJECT = "insub";
public static final String IN_PATH = "inpath";
//This is the standard tag for class name
private static final String TAG = MailIntentService.class.getSimpleName();
//These set up the parameters for notifications
private NotificationManager mNotificationManager;
private Notification notifyDetails;
private int NOTIFICATION_ID;
private CharSequence contentTitle = "Bethel Upload";
private CharSequence contentText = "Image Uploading...";
private String contentTicker = "Upload Started...";
public void onCreate() {
super.onCreate();
Log.i(TAG, "MailIntentService Created");
mNotificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
notifyDetails = new Notification(R.drawable.ic_launcher, contentTicker, System.currentTimeMillis());
}
public void onDestroy() {
super.onDestroy();
File dir = new File(Environment.getExternalStorageDirectory() + "/BethelUpload");
if (dir.isDirectory()) {
String[] children = dir.list();
for (int i = 0; i < children.length; i++) {
new File(dir, children[i]).delete();
}
}
Log.i(TAG, "MailIntentService Destroyed");
}
public MailIntentService() {
super(TAG);
}
@Override
protected void onHandleIntent(Intent intent) {
Context context = getApplicationContext();
Intent notifyIntent = new Intent(BethelUploadActivity.class.getSimpleName());
PendingIntent intentP = PendingIntent.getActivity(MailIntentService.this, 0, notifyIntent, android.content.Intent.FLAG_ACTIVITY_NEW_TASK);
notifyDetails.setLatestEventInfo(context, contentTitle, contentText, intentP);
try {
String subject = intent.getStringExtra(IN_SUBJECT);
String path = intent.getStringExtra(IN_PATH);
Log.i(TAG, "Sending Mail...");
Log.i(TAG, "Subject: " + subject);
Log.i(TAG, "Attachment Path: " + path);
mNotificationManager.notify(NOTIFICATION_ID, notifyDetails);
GMailSender sender = new GMailSender(sendEmail, sendPass);
sender.sendMail(subject, body, sendEmail, destEmail, path);
Log.i(TAG, "Mail Sent!");
contentText = "Image Uploaded Successfully";
contentTicker = "Upload Successful";
notifyDetails.setLatestEventInfo(context, contentTitle, contentText, intentP);
mNotificationManager.notify(NOTIFICATION_ID, notifyDetails);
}
catch (Exception e) {
Log.e(TAG, e.getMessage(), e);
}
}
}
This is the GMailSender I use from another example here: Sending Email in Android using JavaMail API without using the default/built-in app
public class GMailSender extends javax.mail.Authenticator {
private String mailhost = "smtp.gmail.com";
private String user;
private String password;
private Session session;
static {
Security.addProvider(new com.provider.JSSEProvider());
}
public GMailSender(String user, String password) {
this.user = user;
this.password = password;
Properties props = new Properties();
props.setProperty("mail.transport.protocol", "smtp");
props.setProperty("mail.host", mailhost);
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.port", "465");
props.put("mail.smtp.socketFactory.port", "465");
props.put("mail.smtp.socketFactory.class",
"javax.net.ssl.SSLSocketFactory");
props.put("mail.smtp.socketFactory.fallback", "false");
props.setProperty("mail.smtp.quitwait", "false");
session = Session.getDefaultInstance(props, this);
}
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(user, password);
}
public synchronized void sendMail(String subject, String body, String sender, String recipients, String fileAttachment) throws Exception {
try{
MimeMessage message = new MimeMessage(session);
message.setSender(new InternetAddress(sender));
message.setSubject(subject);
MimeBodyPart messageBodyPart = new MimeBodyPart();
messageBodyPart.setText(body);
Multipart multipart = new MimeMultipart();
multipart.addBodyPart(messageBodyPart);
messageBodyPart = new MimeBodyPart();
DataSource source = new FileDataSource(fileAttachment);
messageBodyPart.setDataHandler(new DataHandler(source));
messageBodyPart.setFileName("SodPhoto.jpg");
multipart.addBodyPart(messageBodyPart);
message.setContent(multipart);
if (recipients.indexOf(',') > 0)
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(recipients));
else
message.setRecipient(Message.RecipientType.TO, new InternetAddress(recipients));
Transport.send(message);
}catch(Exception e){
}
}
public class ByteArrayDataSource implements DataSource {
private byte[] data;
private String type;
public ByteArrayDataSource(byte[] data, String type) {
super();
this.data = data;
this.type = type;
}
public ByteArrayDataSource(byte[] data) {
super();
this.data = data;
}
public void setType(String type) {
this.type = type;
}
public String getContentType() {
if (type == null)
return "application/octet-stream";
else
return type;
}
public InputStream getInputStream() throws IOException {
return new ByteArrayInputStream(data);
}
public String getName() {
return "ByteArrayDataSource";
}
public OutputStream getOutputStream() throws IOException {
throw new IOException("Not Supported");
}
}
}
I know this is a huge amount of code / wall of text, but I figured I would rather give you too much information than too little. I really appreciate your time!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我认为这将是解决方案...
这使得您的第一封邮件在当前系统时间延迟 30 秒发送,第二封邮件也以这种方式发送...
I think this will be solution...
This makes your first mail sends at 30seconds delayed from current System time and second one also sends like this manner...
在发现使用 SystemClock.sleep(30000)(感谢下面的 DineshKumar)可以解决我的问题后,我做了一些研究,发现网络调用并不总是阻止 IntentService >。
SystemClock.sleep(30000)
确实会阻止IntentService
,但它会使其等待 30 秒,即使不需要(不是最佳)。然后我想出了一种方法来检查我的 GMailSender 类是否正在处理:
然后我在我的
IntentService
中放置了一个while
循环,该循环会阻止代码,直到它看到 GMailSender处理完毕:After figuring out that using
SystemClock.sleep(30000)
(thanks to DineshKumar below) will fix my problem, I did some research and found that network calls do not always block anIntentService
.SystemClock.sleep(30000)
does block theIntentService
, but it makes it wait 30 seconds even if it doesn't need to (not optimal).I then figured out a way to check to see if my GMailSender class was processing:
And then I placed a
while
loop in myIntentService
that blocks the code until it sees that GMailSender is finished processing:在pendingIntent中使用请求代码..这是你的代码,
看看为什么你的第一封邮件没有发送,但最后一封发送了问题是在待处理意图中使用请求代码,即为每个待处理意图创建一个单独的id..我将显示aome simple例如..
请参阅而不是使用 startService() 直接尝试使用 AlarmManager 来挂起Intent,以便您在指定时间发送邮件
我希望这会帮助你..
use the requestcode in pendingIntent..it's your code
see why your first mail is not sended but the last one sends the problem is use request code in pending intent i.e to create a separate a id for each pending intent..i will show aome simple example..
see instead of using startService() directly try pendingIntent with AlarmManager so you send mail at specified time
i hope this will helps you..