Security exception on reading attachment from gmail app in my app android - 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>

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: How to get app to appear in list of default apps? [duplicate]

I am following this tutorial on setting my app as the default SMS app, but for some reason, my app does not appear in the list of available options. I have tried to research this as much as possible, but everything points back to that same tutorial, or is outdated. Do I need a <receiver> as well? Can someone explain what I am doing wrong?
The code:
#Override
protected void onResume()
{
super.onResume();
Log.i("MainAcitvity", "On Resume Called");
// Only do these checks/changes on KitKat+, the "mSetDefaultSmsLayout" has its visibility
// set to "gone" in the xml layout so it won't show at all on earlier Android versions.
final String myPackageName = getPackageName();
if (Utility.hasKitKat())
{
if (Utility.isDefaultSmsApp(this))
{
// This app is the default, remove the "make this app the default" layout and
// enable message sending components.
mSetDefaultSmsLayout.setVisibility(View.GONE);
}
else
{
Log.i("MainActivity", "Not Default App");
// Not the default, show the "make this app the default" layout and disable
// message sending components.
mSetDefaultSmsLayout.setVisibility(View.VISIBLE);
Button button = (Button) findViewById(R.id.set_default_sms_button);
button.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View view)
{
Log.i("MainActivity", "Button Pushed");
//Utility.setDefaultSmsApp(MainActivity.this);
Intent intent = new Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT);
intent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME, myPackageName);
startActivity(intent);
}
});
}
}
}
The manifest:
<activity
android:name=".MainActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<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>
In order for your app to be eligible to be selected as the default messaging app (as far as the system is concerned), its manifest must list each of the four components as described in that blog post, whether those components' classes are actually present and functional, or not. The class names can be whatever valid names you like, but the rest of each component should be pretty much exactly as shown:
<manifest>
...
<application>
<!-- BroadcastReceiver that listens for incoming SMS messages -->
<receiver
android:name=".SmsReceiver"
android:permission="android.permission.BROADCAST_SMS">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_DELIVER" />
</intent-filter>
</receiver>
<!-- BroadcastReceiver that listens for incoming MMS messages -->
<receiver
android:name=".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 that allows the user to send new SMS/MMS messages -->
<activity android:name=".ComposeSmsActivity">
<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>
<!-- Service that delivers messages from the phone "quick response" -->
<service
android:name=".HeadlessSmsSendService"
android:exported="true"
android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE">
<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>
Since the system only inspects an app's manifest to determine if it can act as the default messaging app, you don't actually need any of those classes, though you might have to suppress some warnings/errors, or provide stub classes, to make your IDE happy.
Obviously, if your app is to act as a user's default messaging client, it should fully implement all of the specified components. However, an incomplete implementation can certainly be useful; e.g., during learning and testing, or in apps that only need partial access temporarily, like message backup and restore apps.
If you do intend to perform any SMS/MMS-related tasks, you will also need the relevant permissions. Though the system apparently doesn't check for these when determining eligible default app candidates, the following permissions are necessary for their corresponding operations:
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.WRITE_SMS" />
<uses-permission android:name="android.permission.RECEIVE_MMS" />
A SecurityException will be thrown if you're missing the relevant permission for a given operation when it happens, though some might be easy to miss; e.g., if the RECEIVE_SMS permission is missing when the system tries to deliver an incoming SMS to a manifest-registered Receiver. Be sure to inspect your logs if you observe unexpected behavior, even if there is no apparent crash.

Android Instant App Play Store Errors

Whenever I upload my base and feature APKs to Play Store I got these errors :
You must provide a default URL for your Instant App APKs. Learn More
Your site 'www.example.com' has not been linked through the Digital
Assets Link protocol to your app. Please link your site through the
Digital Assets Link protocol to your app.
You should have at least one active APK that is mapped to site
'www.example.com' via a web 'intent-filter'.
And here is my manifest file : (EDITED)
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.ex.example.feature.productdetail">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<application>
<activity
android:name=".activity.ProductDetail"
android:configChanges="orientation|screenSize"
android:screenOrientation="portrait">
<meta-data
android:name="default-url"
android:value="https://www.example.com/product/12345" />
<meta-data android:name="asset_statements" android:resource="#string/asset_statements"/>
<intent-filter
android:autoVerify="true"
android:order="1"
>
<category android:name="android.intent.category.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="http" android:host="www.example.com"/>
<data android:scheme="https" android:host="www.example.com"/>
<data android:pathPattern="/product/12345"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<meta-data
android:name="com.facebook.sdk.ApplicationId"
android:value="#string/facebook_app_id"/>
</application>
</manifest>
I put the assetlinks.json file to my web site, and when I proceed test link file, it gives success.
What am I doing wrong any idea?
Thanks your help in advanced
This is because the default URL you specified (https://www.example.com) is not supported by the intent-filters in your Instant App (https://www.example.com/product/productId).
You will either need to update the default URL so it points to a supported URL, or add a new intent-filter that supports the default URL.
You must specify the host of your domain in the manifest, you can not use www.example.com
> <data android:scheme="http" android:host="www.yuorwebsite.com"/>
> <data android:scheme="https" android:host="www.yuorwebsite.com"/>
, also before the intent - filter in manifest, specify
<meta-data
Android: name = "default-url"
Android: value = "https://yourwebsite.com/main" />
I agree with #KitKat and AdamK. Based from this documentation. To allow Google Play and Android launcher to discover your app, you must provide at least one activity as the entry point for your app. In the manifest for your app, the entry point activity must have an <intent-filter> element that includes the CATEGORY_LAUNCHER and ACTION_MAIN intents.
Your app must also define a default URL for your app. Within the same Android manifest as your entry-point activity, you define the default URL for your app by adding a <meta-data> element with a value attribute that provides a valid HTTPS URL that the activity can handle. Further, this default url must also be part of the CATEGORY_LAUNCHER activity's intent filter in the installed app.

Open email attachment with my app

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.

Oauth Callback not found after allowing the app on Twitter

Hey. I am developing an application using the Twitter4j api. In order to allow the application and get an access token, I launch the browser with the callback parameters which I had set in the manifest file.
<data android:scheme="scheme" android:host="authenticatorapp"></data>
After allowing the application, the browser calls the following and fails with a not found message.
scheme://authenticatorapp?oauth_token=n5vd99dfnmnf...
I tried it both on the emulator and the device.
In the emulator, LogCat gives me this :
12-12 15:04:05.743: ERROR/browser(230): onReceivedError -10 scheme://authenticatorapp?oauth_token=Jj...M&oauth_verifier=3ZfuY... The protocol is not supported.
-- The manifest file :
<activity android:name=".AuthenticatorApp"
android:launchMode="singleInstance"
>
<intent-filter>
<category android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.LAUNCHER" />
<data android:scheme="scheme" android:host="authenticatorapp"></data>
</intent-filter>
</activity>
<!-- Broadcast Receiver that will process AppWidget updates -->
<receiver android:name=".ZaytungWidget" android:label="#string/widget_name">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="#xml/tweet_metadata" />
</receiver>
<!-- Service to perform web API queries -->
<service android:name=".ZaytungWidget$UpdateService" />
</application>
<uses-sdk android:minSdkVersion="4" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.INTERNET" />
Can you please post the whole manifest file?
I found the following question which may be useful later on: OAuth instance state in Android
The question linked to the following example application, which may be helpful:
http://code.google.com/p/jpoco/source/browse/trunk/jpoco-android-app/AndroidManifest.xml
This is what I have in my working Manifest.xml, where org.gpsagenda.OAUTH is the activity doing the Authenticating.
<activity android:name="org.gpsagenda.OAUTH" >
<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="gpsagenda" android:host="twitt" />
</intent-filter>
</activity>
If you're developing a native app, you don't use the callback parameters, but need to let the user enter the pin in your app somewhere - which he gets when you open the authorization_url in a browser or probably more comfortably within your app in a webview.
You could also automatically fetch the pin after the user has clicked on 'yes' in the authorization twitter webpage, but not sure if it's against the twitter ToS.

Categories

Resources