Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

startActivity within a subclass of Application

I have a little Android application in which I specify my application directly and do some application-wide setup in the ApplicationSubclass' onCreate, but I am getting the following error (Note, I know about FLAG_ACTIVITY_NEW_TASK):

Caused by: android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity  context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
    at android.app.ContextImpl.startActivity(ContextImpl.java:644)
    at android.content.ContextWrapper.startActivity(ContextWrapper.java:258)
    at somePart.ofA.nameSpace.ApplicationSubclass.sendNotificationEmail(ApplicationSubclass.java:186)

I am calling this sendNotificationEmail when some exceptions are thrown and I catch them, so that the user of the app can send in a little e-mail with information on the exception so that I can more easily fix anything that might arise or guide them on fixing their issue.

Here is some of the relevant code:

manifest.xml:

<application android:label="@string/app_name" android:icon="@drawable/icon" android:name=".ApplicationSubclass">
// ... some stuff, including all of my app's activities
</application>

the ApplicationSubclass is defined as:

public class ApplicationSubclass extends Application {
   // Multiple methods, including an override of onCreate

  public void sendNotificationEmail(String emailBody) {
      Intent emailIntent = new Intent(Intent.ACTION_SEND);
      emailIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
      emailIntent.setType("text/html");
      emailIntent.putExtra(Intent.EXTRA_EMAIL, notificationRecipients);
      emailIntent.putExtra(Intent.EXTRA_SUBJECT, "MyAppName Error");
      emailIntent.putExtra(Intent.EXTRA_TEXT, emailBody);
      try {
          startActivity(Intent.createChooser(emailIntent, "An error has occurred! Send an error report?"));
      } catch (ActivityNotFoundException e) {
          // If there is nothing that can send a text/html MIME type
          e.printStackTrace();
      }
   }
}

I'd like to know why this is happening. I read some documentation, I looked for some answers on StackOverflow and the Internet at large. It seems to me that I should be fine since I am setting FLAG_ACTIVITY_NEW_TASK, however that's clearly not the case!

Is it simply that I may not even attempt to do this from the Application's context? Must I be within a Activity in my application when I attempt this? It would be sort of annoying to need to re-engineer around this, and being able to send exception e-mails would be quite useful!

EDIT: Rich asked a good question, and that's why the heck would I want to be doing this in the first place? The answer is simply that there is data being loaded in the Application that could fail, and I'd like the user to be able to send some of that failure data when this occurs.

The reason this is in the Application and not the activity is that there are application state variables I don't want to lose every time someone rotates the device. When I found out about the fact that onPause and onCreate are called when you rotate (for Activies) I refactored this code out into the Application (which works great!). I had actually tried the solution to send these to onConfigurationChanged and Override that method in my activity, but that's messy and for whatever reason despite putting android:configChanges="keyboardHidden|orientation" in my manifest it wasn't correctly working for me. I'm sure I could pursue this option, but I'd rather leave things as they are (it's cleaner) and get the ability for someone to e-mail!

like image 367
Kevek Avatar asked Oct 12 '11 20:10

Kevek


2 Answers

Ah! I figured out what I did, it's quite simple! I was setting the FLAG_ACTIVITY_NEW_TASK on the wrong intent! Silly me, I missed that Intent.createChooser(...,...) will return a new Intent, so you must set the flag on the chooser Intent rather than on the ACTION_SEND Intent.

Not all that confusing when you think about it, and I can't believe I overlooked that!

So if anyone ever does what I did, here you go:

public void sendNotificationEmail(String emailBody) {
        Intent emailIntent = new Intent(Intent.ACTION_SEND);
        emailIntent.setType("text/html");
        emailIntent.putExtra(Intent.EXTRA_EMAIL, notificationRecipients);
        emailIntent.putExtra(Intent.EXTRA_SUBJECT, "MyAppName Error");
        emailIntent.putExtra(Intent.EXTRA_TEXT, emailBody);
        Intent emailChooser = Intent.createChooser(emailIntent, "An error has occurred! Send an error report?");
        emailChooser.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        try {
            startActivity(emailChooser);
        } catch (ActivityNotFoundException e) {
            // If there is nothing that can send a text/html MIME type
            e.printStackTrace();
        }
    }
like image 78
Kevek Avatar answered Oct 26 '22 15:10

Kevek


I have launch an activity(to relogin the user when loss the session) from my class which subclass from Application as follow:

public boolean relogin(Activity act) {      
    Intent intent = new Intent(act,ActivityLogin.class);    
    intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);     
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
    startActivity(intent);              
    act.finish();// here i finish my current activity
}
like image 39
Dayerman Avatar answered Oct 26 '22 14:10

Dayerman