【问题标题】:Android: IntentService not queuing properlyAndroid:IntentService 未正确排队
【发布时间】:2012-01-04 21:39:14
【问题描述】:

我正在尝试使用 Intent 服务在后台运行以发送带有相当大 (1-2mb) 图像附件的电子邮件。我是一个初学者,到目前为止,通过在网络上研究已经学到了所有东西(所以你可能会看到一些类似的代码)。

发生的情况是,当我发送第一封电子邮件时,一切正常。但是,当我尝试在第一个仍在处理时发送另一个时,第一个被丢弃,第二个通过正常。它将始终发送最新的排队意图并跳过之前的意图。

根据我所做的研究,IntentService 应该将传递给它的意图排队,并按顺序依次执行它们。这个问题:IntentService : How to enqueue correctly? 类似,但我认为它并不完全适用于我的情况。

我确定我错过了一些愚蠢的东西 =(

这是我启动服务的 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: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");
    }
}
}

我知道这是大量的代码/文字墙,但我想我宁愿给你太多信息也不愿太少。非常感谢您的宝贵时间!

【问题讨论】:

  • 您的 GMailSender#sendMail 方法正在捕获所有异常并且不打印任何内容...您可以删除 try/catch 块并查看是否发生任何异常吗?
  • 你有什么异常吗?
  • @EricKraft:删除 GmailSender sendMail 方法中的 try/catch 块后,如果我没有数据信号,则会出现异常。否则(假设我确实有数据信号)我没有得到任何信号。

标签: android queue android-intent android-service intentservice


【解决方案1】:

我认为这将是解决方案...

     GMailSender sender = new GMailSender(sendEmail, sendPass); 
         SystemClock.sleep(30000);
    sender.sendMail(subject, body, sendEmail, destEmail, path);

这使您的第一封邮件在当前系统时间延迟 30 秒后发送,第二封邮件也以这种方式发送...

【讨论】:

  • 感谢您的意见 Dinesh!这似乎有效,但我不确定为什么。我将对其进行更多测试以确保,但我更喜欢不需要等待发送邮件的解决方案。
【解决方案2】:

在确定使用 SystemClock.sleep(30000)(感谢下面的 DineshKumar)可以解决我的问题后,我做了一些研究,发现网络调用并不总是阻止 IntentServiceSystemClock.sleep(30000) 确实阻止了 IntentService,但即使它不需要它也会等待 30 秒(不是最佳的)。

然后我想出了一种方法来检查我的 GMailSender 类是否正在处理:

private boolean isSending() {
        ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
        List<RunningAppProcessInfo> runningProcInfo = manager.getRunningAppProcesses();
        for(int i = 0; i < runningProcInfo.size(); i++) {
        if(runningProcInfo.get(i).processName.equals("com.bethelfarms.bethelupload.GMailSender")) {
            Log.i(TAG, "isSending is true");
            return true;
        }
    }
    Log.i(TAG,"isSending is false");
    return false;
}

然后我在我的IntentService 中放置了一个while 循环,该循环会阻止代码,直到它看到 GMailSender 已完成处理:

        GMailSender sender = new GMailSender(sendEmail, sendPass);  
        //Blocking action to wait for previous message to send
        sent = isSending();
        while(sent==true) {
            SystemClock.sleep(1000);
            sent = isSending();
        }
        sender.sendMail(subject, body, sendEmail, destEmail, path); 

【讨论】:

    【解决方案3】:

    在pendingIntent中使用requestcode..这是你的代码

       PendingIntent intentP = PendingIntent.getActivity(MailIntentService.this, 0,     notifyIntent, android.content.Intent.FLAG_ACTIVITY_NEW_TASK);
    

    看看为什么你的第一封邮件没有发送,但最后一封邮件发送的问题是在待处理的意图中使用请求代码,即为每个待处理的意图创建一个单独的 id..我将展示一个简单的示例..

        int COUNT=Integer.parseInt(some_txt.getText().toString());
    
        if(COUNT==1)  
         { 
            PendingIntent intentP = PendingIntent.getService(MailIntentService.this, COUNT,     notifyIntent, android.content.Intent.FLAG_ACTIVITY_NEW_TASK);
         }
       else if(COUNT==2)
       {
           PendingIntent intentP = PendingIntent.getActivity(MailIntentService.this, COUNT,     notifyIntent, android.content.Intent.FLAG_ACTIVITY_NEW_TASK);
        }
      else if(COUNT==3)
      {
         PendingIntent intentP = PendingIntent.getActivity(MailIntentService.this, COUNT,     notifyIntent, android.content.Intent.FLAG_ACTIVITY_NEW_TASK);
       }
    

    查看而不是直接使用 startService() 尝试使用 AlarmManager 的 pendingIntent 以便您在指定时间发送邮件 我希望这会对你有所帮助..

    【讨论】:

    • 您是说我的 IntentService 中的通知导致了问题,还是说每当我在主要活动中启动服务时都会导致问题?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-20
    • 2016-04-26
    • 2018-09-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多