After throwing an Intent to a PDF app, my activity is finished - android

I'm having an issue trying to open files (can be .jpg or .pdf, mostyl .pdf) this is the code that I use to launch the Intent:
public static void openFile(Context context, File aFile) throws ActivityNotFoundException {
MimeTypeMap myMime = MimeTypeMap.getSingleton();
mLogger.info("Opening file " + aFile.getName());
Intent newIntent = new Intent(Intent.ACTION_VIEW);
String[] nameParts = aFile.getName().split("\\.");
String namePart = nameParts[nameParts.length - 1];
mLogger.info("Searching activity for MIME type " + namePart);
String mimeType = myMime.getMimeTypeFromExtension(namePart);
newIntent.setDataAndType(Uri.fromFile(aFile), mimeType);
newIntent.setFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
context.startActivity(newIntent);
}
I've already tried changing the flags like:
No flags at all.
newIntent.setFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
The weird thing is that somethimes works (doesn't close the Activity from where I launched the intent) and some times does (I press back being in the PDF app, and then when I come back, I'm in the Activity previous to the one where I lauched the intent)
I don't know what other thing I can do, I'm starting to think that is some device related problem. My device is a Moto G.
BTW, this happens with the two kind of files, jpg. and pdf. It's the same, I'm mean, I'm pretty sure that the problem is in the way that I'm setting the flags or It's some kind of device related problem. I don't think that this is a problem related to the applications that I use to open the files.
EDIT
Added the manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="TOP_SECRET_SORRY">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_INTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
<!-- Optional permission for reliable local dispatching on non-Google Play devices -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:name=".app.NAME"
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme">
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
<!-- Optionally, register AnalyticsReceiver and AnalyticsService to support background
dispatching on non-Google Play devices -->
<receiver
android:name="com.google.android.gms.analytics.AnalyticsReceiver"
android:enabled="true">
<intent-filter>
<action android:name="com.google.android.gms.analytics.ANALYTICS_DISPATCH" />
</intent-filter>
</receiver>
<service
android:name="com.google.android.gms.analytics.AnalyticsService"
android:enabled="true"
android:exported="false" />
<activity
android:name=".app.activities.LoginActivity"
android:label="#string/title_login"></activity>
<activity
android:launchMode="singleTask"
android:name=".app.activities.MainActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".app.activities.DisclaimerActivity"
android:label="#string/title_disclaimer"></activity>
<activity
android:name=".app.activities.SubCategoriesListActivity"
android:label="#string/title_file_categories"></activity>
<activity
android:name=".app.activities.SubCategoriesDetailActivity"
android:label="#string/online_file_list">
</activity>
<activity
android:name=".app.activities.UatTestingActivity"
android:label="#string/title_uat_testing"></activity>
<service
android:name=".app.services.SyncService"
android:process="com.SOME_COMPANY.SOME_APP.app.services.SyncService" />
<receiver
android:name=".app.receivers.Boot">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<provider
android:name=".utils.MultiProcessShared"
android:authorities="com.COMPANY.SOME_APP.PREFERENCE_AUTHORITY"
android:exported="false" />
</application>
</manifest>
SubcategoryDetailActivity is the one whose context I use to launch the intent.

The problem was solved when I used this flag:
newIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
IDK why but if someone can explain it to me I'll gladly accept that answer.

Related

permission denial for content provider when called from within the same app

I have only one app. It has a content provider that is not exported (I don't want other apps to have access to the content) I have successfully been using the content provider until now.
I have created a content observer to update a TextView. The onChange method gets called when the content changes and it tries to re-query that content. That's when it gets the security exception that looks like this:
java.lang.SecurityException: Permission Denial: reading org.sil.lcroffline.data.DataProvider uri content://org.sil.lcroffline/users/by_account_name/5555544444 from pid=0, uid=1000 requires the provider be exported, or grantUriPermission()
Here's the code that generates it:
#Override
public void onChange(boolean selfChange, Uri uri) {
Cursor c = null;
try {
c = mContentResolver.query(UserEntry.buildUserPhoneUri(mAccount.name), null, null, null, null);
// do stuff with the data in the cursor
} finally {
if (c != null) c.close();
}
}
The URI looks like it's formed properly, and I don't think there's a problem with matching it in the content provider.
The code above works fine when called programatically from within the app, it's only when it's triggered by a change in the observed data that the Exception occurs.
How could I get a permission denial from within the same app, and how do I fix this?
Behold the manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.sil.lcroffline">
<!-- To communicate with LCR -->
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- Required because we're manually creating a new account. -->
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"/>
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".authentication.LoginActivity"
android:label="#string/app_name"
android:exported="true">
</activity>
<activity
android:name=".MainActivity"
android:label="#string/title_activity_main"
android:theme="#style/AppTheme.NoActionBar"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".ReportActivity"
android:parentActivityName=".MainActivity"></activity>
<service android:name=".authentication.AuthenticatorService">
<intent-filter>
<action android:name="android.accounts.AccountAuthenticator" />
</intent-filter>
<meta-data android:name="android.accounts.AccountAuthenticator"
android:resource="#xml/authenticator" />
</service>
<provider
android:authorities="#string/data_authority"
android:name=".data.DataProvider"
android:exported="false" />
<service
android:name=".data.SyncService"
android:exported="true"
android:process=":sync">
<intent-filter>
<action android:name="android.content.SyncAdapter"/>
</intent-filter>
<meta-data android:name="android.content.SyncAdapter"
android:resource="#xml/syncadapter" />
</service>
</application>
</manifest>
It turns out this is caused by me not using a Handler in the ContentObserver
When you don't pass a handler to the content observer the onChange method gets called directly instead of a message to call it being posted through the handler. This is all well and good, except that the process that calls the onChange method in that situation is the System OS, which doesn't have the necessary permissions to query my content provider.
To fixed this I changed the code where my content observer is created from this:
mUserObserver = new ContentObserver(null) {
// override onChange methods here
}
To this:
mUserObserver = new ContentObserver(new Handler()) {
// override onChange methods here
}
I was clued in by this question

Android : what category of intent filter should i use

In the second and third activity, in the intent filter what should i use in category.In the second activity i used default but after making third activity i do not know what category should i use.
This is the first android app i am trying to make.Please help me,which categoty should i use in second and third activity.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="csimplifyit.mobileapp.myschool">
<!-- To auto-complete the email text field in the login form with the user's emails -->
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.READ_PROFILE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<!-- for json call -->
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="#mipmap/login"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".login.Login"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".login.Menu"
android:label="#string/second_activity">
<intent-filter>
<action android:name="csimplifyit.mobileapp.myschool.login.Menu" />
<category android:name="android.intent.category. " />
</intent-filter>
</activity>
<activity
android:name=".login.Attendance"
android:label="#string/attendance_activity">
<intent-filter>
<action android:name="csimplifyit.mobileapp.myschool.login.Attendance" />
<category android:name="android.intent.category. " />
</intent-filter>
</activity>
</application>
Most likely, you get rid of the second and third <intent-filter> elements entirely. Only have <intent-filter> elements on activities that you expect other apps to link to. You do not need action strings for starting your own activities -- you can use explicit Intents (e.g., new Intent(this, csimplifyit.mobileapp.myschool.login.Menu.class)).
If, for some reason, you are expecting other developers to directly start your Menu or Attendance activities, then the simplest thing is to put them in the DEFAULT category as well. A call to startActivity() automatically adds the DEFAULT category to the Intent, if the Intent has not specified another category.

Android Permission Denial starting Intent for Wallpaper Settings

Unfortunately when I try to run my wallpaper I get an error message saying Permission Denial starting Intent and requires android.permission.BIND_WALLPAPER but I can't seem to figure out why. My manifest looks like the following:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.package">
<uses-feature android:name="android.software.live_wallpaper" />
<uses-permission android:name="android.permission.SET_WALLPAPER" />
<application
android:exported="true"
android:icon="#drawable/icon"
android:label="#string/app_name"
android:permission="android.permission.BIND_WALLPAPER">
<service
android:name="WallpaperService"
android:icon="#drawable/icon"
android:label="#string/app_name"
android:permission="android.permission.BIND_WALLPAPER">
<intent-filter>
<action android:name="android.service.wallpaper.WallpaperService" />
</intent-filter>
<meta-data
android:name="android.service.wallpaper"
android:resource="#xml/livewallpaper" />
</service>
<activity
android:name=".WallpaperSetClass"
android:exported="true"
android:permission="android.permission.BIND_WALLPAPER"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
The live wallpaper does run perfectly if I set it through the live wallpaper part of my phone, but I would like to have a settings area as well to be able to open in which I can't.
At the moment my settings class is basically empty containing just an onCreate function and a layout with a button.
Is there something I'm missing? I seem to have the permissions along with android:exported
Turns out I had
android:permission="android.permission.BIND_WALLPAPER"
In the wrong spot, it should be in the service tag, and only have ONE, having multiple will break it.

Android GCM receive not working

I'm trying to set up push notifications in an app for the first time. I think the server side is OK (the message send to google comes back with status code 200, and I see a success result in the response body).
But the device never does anything :(
Manifest is set as follows:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="my.package" >
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<permission android:name="my.package.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="my.package.permission.C2D_MESSAGE" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/appName"
android:theme="#style/AppTheme" >
<activity
android:name="my.package.activity.MainActivity"
android:label="#string/title_activity_main" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name="com.google.android.gms.gcm.GcmReceiver"
android:enabled="true"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="my.package" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
</intent-filter>
</receiver>
<service
android:name=my.package.NotificationListenerService"
android:exported="false" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
</application>
</manifest>
And the NotificationListenerService is like this:
public class NotificationListenerService extends GcmListenerService {
#Override
public void onMessageReceived(String from, Bundle data) {
String message = data.getString("message");
Log.d("MyApp", "message);
Notification.ShowNotification("test", getApplicationContext());
}
}
I think that's all I need according to https://developers.google.com/cloud-messaging/android/client (asides from the stuff to handle reset tokens which I've not added yet. My token registration seems to work as I can see the token in the dev console data store.)
I've tried looking at logcat but nothing obvious seems to appear. Do I need to "start" the service in some way? The documentation suggests not... I'm obviously missing something fundamental though!
When you send a message, your server normally gets a message_id as a response. Using the diagnostics tool with the message_id could be useful to make sure that GCM correctly relayed the message.
Is Google Play Services up-to-date on your device ?

Launch Intent from and to a WallpaperService

I have a live wallpaper which displays an image. I change that image in an activity. I then need to notify the live wallpaper, so it knows to reload the resources.
Intents seemed like the perfect, simple, solution:
Intent intent = new Intent(MyActivity.this, MyWallpaperService.class);
startService(intent);
I and in MyWallpaperService
#Override
public int onStartCommand (Intent intent, int flags, int startId) {...}
I also need to know, in another service, when the user taps the screen. I use the exact same mechanism of sending and receiving the intent.
Everything is working perfectly on Android 4.0+ devices and emulators.
But I tested on Android 2.2 and 2.3.3 emulator and get the following error:
java.lang.SecurityException: Not allowed to start service Intent { cmp=com.domain.name/.liveWallpaper.MyWallpaperService } without permission android.permission.BIND_WALLPAPER
My manifest contains the correct android:permission inside the service tag:
<service
android:name=".liveWallpaper.MyWallpaperService"
android:label="#string/app_name"
android:permission="android.permission.BIND_WALLPAPER" >
<intent-filter>
<action android:name="android.service.wallpaper.WallpaperService" />
</intent-filter>
<meta-data
android:name="android.service.wallpaper"
android:resource="#xml/livewallpaper_data" />
</service>
Why do I get this error only on old versions(Android 2.2 and 2.3.3)? Is sending Intents to a WallpaperService not allowed or recommended? Does it have something to do with the fact that only the system can bind to a service with the BIND_WALLPAPER permission?
In the end, if intents do not work, what is an alternative, simple, solution?
try to add the permission to your Service in the manifest file , like the following :
<service android:name=".LiveWallpaper"
android:label="#string/app_name"
android:icon="#drawable/icon"
android:permission="android.permission.BIND_WALLPAPER">
Hope that Helps
java.lang.SecurityException: Not allowed to start service Intent {
cmp=com.domain.name/.liveWallpaper.MyWallpaperService } without
permission android.permission.BIND_WALLPAPER
means you probably forgot to declare the BIND_WALLPAPER permission within your AndroidManifest.xml like this:
<service
android:enabled="true"
android:name="MyWallpaperService"
android:permission="android.permission.BIND_WALLPAPER" />
Android Livewallpaper settings fail to load from 'configure...' menu
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.RrD"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="8" />
<uses-feature android:name="android.software.live_wallpaper" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.BIND_WALLPAPER" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:icon="#drawable/icon"
android:label="#string/app_name"
>
<service android:name=".LiveWallpaper"
android:label="#string/app_name"
android:icon="#drawable/icon"
android:permission="android.permission.BIND_WALLPAPER">
<intent-filter>
<action android:name="android.service.wallpaper.WallpaperService" />
</intent-filter>
<meta-data android:name="android.service.wallpaper"
android:resource="#xml/livewallpaper" />
</service>
<activity android:label="PAM_Prefs"
android:name=".PAM_Prefs"
android:exported="true" android:icon="#drawable/icon">
<intent-filter>
<category android:name="android.intent.category.PREFERENCE" />
</intent-filter>
</activity>
</application>
</manifest>
I still haven't found a exact explanation for why this isn't working, but I found a solution:
Creating a BroadcastReceiver that will receive my custom Intents. This means I will no longer be using startService(intent), but sendBroadcast(intent), which will not cause permission issues.
See the references for more explanations and code.
References:
https://groups.google.com/forum/#!topic/android-developers/N8TzbbKwd5o
Permission to BIND_WALLPAPER required when messaging WallpaperService from Settings Activity

Categories

Resources