I am facing issue in opening Email in MYApp when I made its launch mode to "singleInstance".
I have attached sample Android project which reads file name from email attachment and displays it on screen. Works fine in case of onCreate but throws error in onNewIntent when apps launch mode is singleInstance.
Launchmode.java
package your.namespace.launchmode;
public class LaunchModeActivity extends Activity {
private static final int OPEN_ACT = 2;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
String name = getAttachmetName(getIntent());
if(null != name)
{
TextView textv = (TextView) findViewById(R.id.attachmentnm);
textv.setText(name);
}
}
@Override
protected void onNewIntent(Intent savedInstanceState)
{
super.onNewIntent(savedInstanceState);
String name = getAttachmetName(savedInstanceState);
if(null != name)
{
TextView textv = (TextView) findViewById(R.id.attachmentnm);
textv.setText(name);
}
}
private String getAttachmetName(Intent intent) {
final Uri documentUri = intent.getData();
if(null != documentUri){
final String uriString = documentUri.toString();
String documentFilename = null;
final int mailIndexPos = uriString.lastIndexOf("/attachments");
if (mailIndexPos != -1) {
final Uri curi = documentUri;
final String [] projection = new String[] {OpenableColumns.DISPLAY_NAME};
final Cursor cursor = getApplicationContext().getContentResolver().query(curi, projection, null, null, null);
if (cursor != null) {
final int attIdx = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
if (attIdx != -1) {
cursor.moveToFirst();
documentFilename = cursor.getString(attIdx);
}
cursor.close();
}
}
return documentFilename;
}
return null;
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
super.onActivityResult(requestCode, resultCode, data);
if((resultCode == RESULT_OK) && (requestCode == OPEN_ACT))
{
Log.d("LaunchMode", "Second activity returned");
}
}
}
AndroidManifest
<?xml version="1.0" encoding="UTF-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="your.namespace.launchmode"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="com.google.android.gm.permission.READ_GMAIL"/>
<uses-permission android:name="com.google.android.gm.permission.WRITE_GMAIL"/>
<uses-permission android:name="com.google.android.providers.gmail.permission.READ_GMAIL"/>
<uses-permission android:name="com.google.android.providers.gmail.permission.WRITE_GMAIL"/>
<uses-sdk android:minSdkVersion="8" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:label="@string/app_name"
android:launchMode="singleInstance"
android:name=".LaunchModeActivity" >
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter >
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<!-- docx -->
<data android:mimeType="application/vnd.openxmlformats-officedocument.wordprocessingml.document" />
<!-- xlsx -->
<data android:mimeType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" />
<!-- pptx -->
<data android:mimeType="application/vnd.openxmlformats-officedocument.presentationml.presentation" />
<data android:mimeType="application/vnd.ms-excel" />
<data android:mimeType="application/msword" />
<data android:mimeType="application/vnd.ms-powerpoint" />
<data android:mimeType="text/plain" />
</intent-filter>
</activity>
</application>
</manifest>
Steps to reproduce 1)Install apk on device. 2)Go to gmail native app on device, open any attachment(office document) to view. 3)Choose LaunchMode app to complete action. 4)LaunchMode app will display file name on screen.
This works fine for first time (onCreate flow) but when this app is switch in background and again I try 2,3,4 steps.. app crashes with error
E/DatabaseUtils(30615): java.lang.SecurityException: Permission Denial: reading com.google.android.gm.provider.MailProvider uri content://gmail-ls/qoconnect@gmail.com/messages/5/attachments/0.2/BEST/false from pid=32657, uid=10058 requires com.google.android.gm.permission.READ_GMAIL
E/DatabaseUtils(30615): at android.content.ContentProvider$Transport.enforceReadPermission(ContentProvider.java:309)
E/DatabaseUtils(30615): at android.content.ContentProvider$Transport.bulkQuery(ContentProvider.java:178)
E/DatabaseUtils(30615): at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:111)
E/DatabaseUtils(30615): at android.os.Binder.execTransact(Binder.java:339)
E/DatabaseUtils(30615): at dalvik.system.NativeStart.run(Native Method)
D/AndroidRuntime(32657): Shutting down VM
I need to fix this as, I need to have single instance of Application and should get email attachment name too. Please let me know If I am missing something here.
My question here is why it work in flow of onCreate and it wont work in case of onNewIntent
Note: 1)Works fine with 2.x phones 2) Works fine with Single top launch mode. 3) Some updates on Gmail app.link here:
Like skoke said, you can no longer read from GMail if the intent that gave your permission is not fresh, i.e., it must be the original activity intent. If your intent is from
onNewIntent
then it probably won't succeed.My solution isn't beautiful but seems to be working. In my
onResume
I called a custom function to see if I could access the Gmail content. If not, I showed the user a message and asked them to close the app and try again. Hey, at least it doesn't crash.You likely got a URI permission to read the file name when you received the intent and aren't using the permissions that you requested (
READ_GMAIL
andWRITE_GMAIL
). The URI permission is valid only until your applicationfinish()
es, so you won't have it when you try to resume.That's consistent with your experiences - it works when the intent is fresh, but not old ones. I think that
WRITE_GMAIL
is a signature permission and I am guessing thatREAD_GMAIL
is as well. In that case, there is not much you can do.READ_ATTACHMENT
might be a more appropriate permission for you to request.More on URI permissions: http://developer.android.com/guide/topics/security/permissions.html#uri
Try removing the
uses-permission
tags from your manifest and see if you have the same experience. You can also try to examine theintent
when you receive it by checking its flags.If you get 0 returned, you have been using URI permissions.