Open email attachment with my app - android

I would like to open email attachments with my app. I added that to my manifest file:
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data
android:host="*"
android:mimeType="*/*"
android:pathPattern=".*.pdf" />
</intent-filter>
but when I click the attachment to open it from the email app I got permission denial error while starting intent.
I tried also add to the manifest that:
<uses-permission android:name="com.android.email.permission.READ_ATTACHMENT"/>
<uses-permission android:name="com.android.email.permission.ACCESS_PROVIDER"/>
but it didn't help either.
I tested on the android 2.3.3 and 4.1.2.
Is there something I forgot?

That was my error. I didn't notice, but I had in the manifest file exported set to false.

Related

How to open an Android application from a webpage

I'm currently trying to open an Android application from a webpage. And to pass two parameters.
I went for the intent solution as it seems that custom scheme are not recommended, and in this case, I don't need a deeplink.
Currently, in debug, the only thing that happens is that my intent url is opened inside chrome and display a white page.
It never opens the application.
This is my AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.MyApp">
<application android:allowBackup="true" android:icon="#mipmap/appicon" android:roundIcon="#mipmap/appicon_round" android:supportsRtl="true">
<activity
android:name="com.MyApp.activity.MainActivity"
android:exported="true"
android:label="MyApp">
<intent-filter>
<action android:name="com.MyApp.LAUNCH"></action>
<category android:name="android.intent.category.DEFAULT"></category>
<category android:name="android.intent.category.BROWSABLE"></category>
<data android:scheme="MyScheme" android:host="MyHost" android:path="/"/>
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
</manifest>
This is my javascript:
if (navigator.userAgent.match(/Android/i)) {
var uri = "intent://MyApp#Intent;scheme=MyScheme;action=com.MyApp.LAUNCH;package=com.MyApp;S.p=" + p + ";S.c=" + c + ";end";
window.open(uri);
}
I've seen a lot of way of doing this and tried a lot of things, but I don't get what is the good way to do with API 33.
I tried to use "intent:#Intent", "intent://#Intent", I tried with and without data property under activity, I tried my own scheme "MyScheme://".
I would like to avoid using deeplink as I would like to keep my website accessible without launching the app (different goals).
You need to check Handling Android App Link documentation.
Basically, to open the app you need to specify some specific scheme, for example:
<activity
android:name=".MyMapActivity"
android:exported="true"
...>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="myapp" />
</intent-filter>
</activity>
And the link to open will be: myapp://anypath_here?param1=value1&param2=value2
Try to use a unique scheme, otherwise, you will have an 'Open with..' dialog opening if another app can open it.
To enable link handling verification for your app, add intent filters that match the following format:
<!-- Make sure you explicitly set android:autoVerify to "true". -->
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- If a user clicks on a shared link that uses the "http" scheme, your
app should be able to delegate that traffic to "https". -->
<data android:scheme="http" />
<data android:scheme="https" />
<!-- Include one or more domains that should be verified. -->
<data android:host="..." />
</intent-filter>
More information you can refer to Verify Android App Links.

Android > 4.4.2 - Setting Default SMS App

I've been walking through the steps required to allow Android to recognize an app as a potential default Messaging (SMS/MMS) app detailed here and I've followed through on several posts on SO that have up-voted answers that fallback to the instructions outlined on the blog posting.
However, even after following these instructions, which I believe I have done so correctly, I'm still not able to get my app to appear in the system dialog which will allow me to choose which app I want as the default Messaging client. I can't help but feel like I'm still missing something in the manifest but I'm not too sure. If anyone has any advice on this, I'd really appreciate it.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.gregfmartin.smsdemo">
<uses-sdk android:minSdkVersion="19"/>
<uses-permission android:name="android.permission.READ_SMS"/>
<uses-permission android:name="android.permission.WRITE_SMS"/>
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<application android:icon="#drawable/icon"
android:label="#string/app_name"
android:name=".ApplicationCore"
android:theme="#style/SmsDemo">
<!-- Listens for incoming SMS Messages -->
<receiver android:name=".components.receivers.SmsReceiver"
android:permission="android.permission.BROADCAST_SMS">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_DELIVER"/>
</intent-filter>
</receiver>
<!-- Listens for incoming MMS Messages -->
<receiver android:name=".components.receivers.MmsReceiver"
android:permission="android.permission.BROADCAST_WAP_PUSH">
<intent-filter>
<action android:name="android.provider.Telephony.WAP_PUSH_DELIVER"/>
<data android:mimeType="application/vnd.wap.mms-message"/>
</intent-filter>
</receiver>
<!-- Activity -->
<activity android:name=".Main">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".components.activities.ConversationThreadViewer">
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<action android:name="android.intent.action.SENDTO"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="sms"/>
<data android:scheme="smsto"/>
<data android:scheme="mms"/>
<data android:scheme="mmsto"/>
</intent-filter>
</activity>
<!-- Headless SMS Handler -->
<service android:name=".components.services.HeadlessSmsSenderService"
android:permission="android.permission.SEND_RESPONSE_VIA_MESSAGE"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.RESPOND_VIA_MESSAGE"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="sms"/>
<data android:scheme="smsto"/>
<data android:scheme="mms"/>
<data android:scheme="mmsto"/>
</intent-filter>
</service>
</application>
</manifest>
You need to add the category
android.intent.category.APP_MESSAGING
Refer http://developer.android.com/reference/android/content/Intent.html#CATEGORY_APP_MESSAGING
I finally figured out what was going on. I know I kicked myself after I figured it out and facepalmed for about ten minutes.
The Service, HeadlessSmsSenderService, the permission is supposed to be android.permission.SEND_RESPOND_VIA_MESSAGE not android.permission.SEND_RESPONSE_VIA_MESSAGE.
Respond/Response
Seriously? Send Respond?
What caught it was I copied and pasted the manifest from the Google Blog Post and just made a new app really quick that used it and low and behold, it showed up in the system dialog. So then I ran a diff against it and my manifest and everything matched up save for that misspelling (and the organizational changes that I had).
The nasty part about this is that there are some permissions and Intent Actions that IntelliJ won't automatically catch while you're typing them. I'm also not sure if Lint will catch these types of semantic errors or not. For all intents and purposes, the app will compile and run cleanly. No output was found on logcat so really this was a near totally silent issue.
Thanks for all of your help!

Security exception on reading attachment from gmail app in my app android

In our application we need to read attachments from email clients and upload it to server.
For default android email client everything works fine,but for gmail application facing
java.lang.SecurityException: Permission Denial: opening provider com.google.android.gm.provider.MailProvider from ProcessRecord (pid=11298, uid=10068) requires com.google.android.gm.permission.READ_GMAIL or com.google.android.gm.permission.WRITE_GMAIL
Have even tried giving Gmail read write permissions but did not work.
Observations are
It is working fine for Nexus but for samsung devices 4.2 and 4.1,working fine initially if activity is created for first time,but if activity is in background throwing above said exceptions.
Trying to get attachment file name using below code.
Cursor cursor = getContentResolver().query(openIntent.getData(),
new String[] { MediaStore.MediaColumns.DISPLAY_NAME }, null,
null, null);
cursor.moveToFirst();
int nameIndex = cursor
.getColumnIndex(MediaStore.MediaColumns.DISPLAY_NAME);
if (nameIndex >= 0) {
NCUtil.clickedImageTitle = cursor.getString(nameIndex);
path = cursor.getString(nameIndex);
}
cursor.close();
My Manifest file
<activity
android:name="com.ncomputing.vspacemobile.NCMainActivity"
android:configChanges="orientation|keyboard|keyboardHidden|screenSize"
android:excludeFromRecents="true"
android:launchMode="singleTask"
android:screenOrientation="sensorPortait"
android:theme="#android:style/Theme.NoTitleBar"
android:windowSoftInputMode="adjustPan" >
<!-- For email attachments -->
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="application/pdf" />
<data android:mimeType="application/msword" />
<data android:mimeType="application/vnd.openxmlformats-officedocument.wordprocessingml.document" />
<data android:mimeType="application/vnd.ms-excel" />
<data android:mimeType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" />
<data android:mimeType="application/vnd.ms-powerpoint" />
<data android:mimeType="application/vnd.openxmlformats-officedocument.presentationml.presentation" />
<data android:mimeType="text/plain" />
<data android:mimeType="text/comma-separated-values" />
<data android:mimeType="application/rtf" />
</intent-filter>
</activity>
User permissions
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
Please let us know how can i make it work,i need the activity launch mode as singleTask and access the attachments.
The intent filter requires both content and file scheme types, with the mimetype application/octetstream
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.BROWSABLE"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="file" android:pathPattern=".*\\.inform" android:mimeType="application/octet-stream"/>
<data android:scheme="content" android:pathPattern=".*\\.inform" android:mimeType="application/octet-stream"/>
as per the Android documentation, "If a scheme is not specified for the intent filter, all the other URI attributes are ignored." With the scheme and URI attributes removed, the only other way to filter the intents is using Mime type, and we all know that custom file extensions do not have registered mime types.
For reference, URI are of the form:
scheme://host:port/path
pathPrefix
pathPattern
So without a scheme, all of that drops. After discovering the above, I tried the obvious -- use a " * " for the scheme, and even tried " .* ". Neither of those worked. I hope someone else can build off my trials. But I believe it has to do with selecting the correct scheme. Unfortunately, the only schemes I know of are http https content and file, and none of the above are the magic bullet.
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="application/*" host="*" android:pathPattern=".*.ext" android:scheme="content" />
</intent-filter>
This intent will cause gmail to display the Download / Preview buttons. In fact, this will also cause your app to open when .ext files are sent as attachments to the regular email client as well.
Source:
Android get attached filename from gmail app
Intent filter to download attachment from gmail apps on Android
Android's ActivityManager automatically clears per-URI permissions when the task of the called application is finished. As per-URI permission are typically granted by setting Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET, the task is cleared when it goes in the background (so that you don't open the attachment viewer if start Gmail again from the launcher). See docs for details.
This is by design and there is no way to 'make it work'. You have to build your app to place nicely with this permission granting scheme. You could read the whole attachment when the app is started, dump to a temporary file/DB and continue uploading in the background by using a service.
Not sure what app you are building, but generally an app that uploads your attachments to a third-party's server sounds like a terrible idea from a privacy and security standpoint.
To read email attachments you need these permissions......
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="com.android.email.permission.READ_ATTACHMENT" />
Notes:
READ_EXTERNAL_STORAGE is assumed from WRITE_EXTERNAL_STORAGE but it is best to add it as best practice.
INTERNET: App might be pulling from a provider that needs the internet because this is email.
Tip: Keep your code clean an easy by making a separate class for each mime type.
<activity
android:name=".KmlReader"
android:configChanges="orientation|keyboardHidden|screenSize"
android:label="#string/title_activity_map"
android:parentActivityName="com.gosylvester.bestrides.ImageTextListViewActivity"
android:theme="#style/Theme.AppCompat" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.gosylvester.bestrides.ImageTextListViewActivity" />
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="application/vnd.google-earth.kml+xml" />
</intent-filter>
</activity>

Android app has been assigned to any possible file - should be assigned to my custom file only

I'm trying to assign my Android app to custom file (json content) with extension "kka".
I'd like to be able to open my app and read *.kka file in following cases:
1. *.kka as email attachment (gmail client)
2. *.kka as file stored in filesystem e.g. Downloads/ folder
My AndroidManifest.xml file looks like this:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.mydomain.kka" >
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.mydomain.kka.MainActivity"
android:label="#string/app_name" >
<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.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="file" android:pathPattern=".*\\.kka" android:mimeType="*/*"/>
<data android:scheme="content" android:pathPattern=".*\\.kka" android:mimeType="application/stream-octet"/>
</intent-filter>
</activity>
</application>
</manifest>
That's the only configuration I found to be able to start my app tapping *.kka as attachment in gmail client and as file in filesystem.
The problem is that my app appears in every possible place where I want to open email attachment or file on filesystem, no matter what kind of file it is, so my KKATest app is on the list of assigned apps for e.g. XMLs, PDFs, even APKs, etc.
It seems to ignore file extension I clearly mentioned in AndroidManifest file.
This situation takes place on Galaxy Nexus with Android 4.4, Galaxy S4 with Android 4.3 and few more.
I've read many suggestions on StackOverflow but no one solves my problem. What's wrong with my manifest file?
I was struggling with the same issue. I need to open my file from both SD card as well as from email attachment. For me it was also trail and error, but this is my solution:
<intent-filter> <!-- Intent filter for opening files from system -->
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="file" />
<data android:host="*" />
<data android:mimeType="*/*" />
<data android:pathPattern=".*\\.locx" />
</intent-filter>
<intent-filter> <!-- Intent filter for open files from email -->
<data android:scheme="content" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:mimeType="application/octet-stream" />
<data android:pathPattern=".*\\.locx" />
</intent-filter>
locx is my file type obviously.
BTW: I only tested with Gmail app, from other forum posts I understand that other email apps might work different.
Indeed, as you pointed out, some email clients replace the mime type with application/octet-stream. So I ended up using an intent filter like this:
<!-- Filters for handling local files -->
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<action android:name="android.intent.action.EDIT" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*" android:scheme="file" android:pathPattern=".*\\.mtype" android:host="*"/>
</intent-filter>
<!-- Filter for email apps -->
<intent-filter>
<action android:name="android.intent.action.VIEW"></action>
<category android:name="android.intent.category.DEFAULT"></category>
<category android:name="android.intent.category.BROWSABLE"></category>
<data android:scheme="content"/>
<data android:mimeType="application/octet-stream"/>
<data android:mimeType="application/mtype"/>
</intent-filter>
This will have your app handle both mtype, and octet-stream. But in the octet-stream case, it may not be actually your file, so you need to do some checking in the app. This means getting the file name, and checking the extension. For this, you can query the content provider, using the uri handled to you in the app, via the intent:
Cursor cursor = mContext.getContentResolver().query(data, null, null, null, null);
int fileNameColumnIndex = cursor.getColumnIndex("_display_name");
if (fileNameColumnIndex != -1) {
String fileName = cursor.getString(fileNameColumnIndex);
}
Now, there are a couple of scenarios:
If you used the gmail client, ther "_display_name" is present;
If you clicked the file, in the Downloader native app, the "_display_name" is present;
If you used the native email client, it is not present; And in this case, i prompt the user to first download the file. If he does so, and then opens the file in the email client again, it will actually open the file, and it will be handled by the first intent-filter.
I've found a solution (almost) and the solution looks like this:
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.mydomain.kka" >
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.mydomain.kka.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:host="*" android:mimeType="*/*" android:pathPattern=".*\.kka" android:scheme="file" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="application/custom-kka" android:scheme="content" />
</intent-filter>
</activity>
</application>
</manifest>
I don't know why entry <data android:host="*" android:mimeType="*/*" android:pathPattern=".*\.kka" android:scheme="file" /> with one backslash ("\") instead of two ("\\") solves the issue with opening all possible files from filesystem - now my app opens only for *.kka files ...
Opening files attached to mails needs to be handled by assigning to mime-type, not file extension. I created custom mime-type "application/custom-kka" and ensured that during sending mail with the file there needs to be set my custom mime-type for attachment.
To do so, I put a piece of code in email composer code:
...
Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
emailIntent.setType("application/custom-kka");
...
which should guarantee me proper mime-type for my attachment. Unfortunately, android mail clients (gmail, generic mail client) on few devices send mails with different then mine mime-type, e.g. "application/octet-stream;", "<nothing here>;" but not desired "application/custom-kka;" and my app can't identify such attachment as assigned to it.
That's the PhoneGap application, so I have also iOS version, where sending this mail with custom mime-type works perfectly and android app can recognise the attachment.
Maybe someone had such issue and could help?

Android: How to use intent-filter to process a PDF email attachment?

I've been trying to have either the email or gmail applications give me the option of using my application to open a PDF attachments to no avail. My intent-filter looks like:
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:mimeType="application/pdf" />
</intent-filter>
When I look in the emulator, the activity manager broadcasts this:
02-04 15:45:03.626: INFO/ActivityManager(59): Starting activity: Intent { act=android.intent.action.VIEW dat=content://com.android.email.attachmentprovider/1/17/RAW flg=0x80001 }
What I'm I doing wrong?
Thanks in advance...
I'm having a similar problem opening csv files from mail (Using Android 2.2). It finally worked using
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="*/*" android:host="*" android:pathPattern=".*.csv" />
</intent-filter>
Changing anything in the data tag made it impossible to call my application from the e-mail application on opening the csv file.
You might also want to check Intent filter to download attachment from gmail apps on Android

Categories

Resources