I have an app that requires temporary access to the device's SMS. In KitKat and above, this access is only granted to the default SMS app, so I'm using:
Intent intent = new Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT);
intent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME, getPackageName());
startActivity(intent);
This brings up a dialog asking the user if they let my app become the default SMS app. So far so good. Problem is, once my app completes its operation, I have to ask the user again, if they want to restore their previous app as their default SMS app.
I'd like a way to avoid the second dialog, perhaps by having my app tell the Android OS that it no longer wishes to be the default SMS app, so that the previous app can automatically take over again. I know Android supports this, because if I uninstall my app while it is the default SMS app, Android will revert to the previous one automatically, with no need for user input. Any way to replicate this behaviour of ceding control without uninstalling?
To be eligible to be the default messaging app, your app has to have certain active components registered in the manifest. Disabling any one of them will make your app ineligible, and the system should automatically revert the default. We can use the PackageManager#setComponentEnabledSetting() method to disable a manifest-registered component.
For example, if the Receiver you have registered for the SMS_DELIVER action is named SmsReceiver:
getPackageManager()
.setComponentEnabledSetting(new ComponentName(this, SmsReceiver.class),
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);
Obviously, before your app could be set as the default again, you would need to re-enable that component, which you can do by calling the above method with PackageManager.COMPONENT_ENABLED_STATE_ENABLED as the second argument.
Related
I have two apps on the play store . Both of them handle an intent and run a service based on it.
However I do not want them to compete and if both are installed I only want App A to show in the Android App chooser and not App B.
How would I keep App B from trying to handle the intent if App A is installed?
Android handles intents internally so when you say an activity is registered for handling an intent it will most likely be via Action field.
If you want two activities to have the same action and to suppress one Activity from showing in Chooser, then it is not possible unless you modify the Android OS.
However I do not want them to compete and if both are installed I only want App A to show in the Android App chooser and not App B
Activities do not "compete" for starting up, its usually the user who chooses which activity to start when an action is specified. So if you want AppA to only show in the chooser, you can declare a different action for AppB.
Hope this helps!
I understand that Android does not allow you to call an emergency number (911) directly. So I have decided to use Intent.ACTION_DIAL instead to leave the app and have the number pre-dialed, ready to call. However, the app chooser appears when I hit my 'Dial 911' button, adding another unnecessary step to the process (the other option besides the Phone app is to scan the number using Lookout Security).
Is there anyway to bypass the app chooser by pre-defining the app to handle the Intent?
There are many possible dialers. You have no good way of determining a priori which is the "one true dialer" that the user wants to use. Moreover, the user should be able to click "Always" on the chooser and therefore only encounter this once.
If you want, you could allow the user to choose their dialer up front, perhaps as part of configuring your app. You can use PackageManager and queryIntentActivities() to find out what all supports ACTION_DIAL, presenting that to the user to choose from. You would remember the ComponentName of their choice, and add that ComponentName to the ACTION_DIAL Intent that you use "for realz" when the user presses the button in your app.
I am trying to open a PendingIntent that opens the Gmail App in the background through a notification.
The steps are as follows:
Show notification with action button
On click of action button (which has a PendingIntent), I want start the PendingIntent (which launches the Gmail app) but in the background.
Dismiss Notification
The notification remains the only thing that the user has seen (i.e. the UI has not changed but only the notification has itself been dismissed after clicking the action button).
It may be "hack-y" but I could also quickly open and then "minimize" the gmail app?
Any ideas?
OK, I really don't understand what you can achieve from such behavior.
you definitely could not provide any meaningful extra data on the intent (unless you are the developer of gmail, which I don't believe is the case..).
actually, if you provides intent to launch explicitly Gmail app (by specifying the package name) - your code would break if Gmail app package name would change.
now to your question:
it is possible to launch activity without bringing it to foreground:
all you have to do is add to the intent been held by the pending intent to flags: FLAG_ACTIVITY_NEW_TASK and FLAG_ACTIVITY_MULTIPLE_TASK
FLAG_ACTIVITY_MULTIPLE_TASK flag is not recommended for use unless your application is the launcher.
gmail main activity would create in background new task, and that's it.
note that the gmail activity would not go threw the onResume and onStart callbacks (because it's not on foreground..) , so if any meaningful code happens from this callbacks - they won't be executed anyway..
UPDATE
now that I know that your purpose is to mark an emails as "read", I can tell you that any attempts to launch gmail app want do to you any good. as I mentioned, you can't pass extra meaningful data to gamil launching intent. there is simply no such API's, and launching main activity simply won't do anything that would help you.
instead, I'll suggest you to use Gmail API's for control user's inbox
Background: I have an app which needs to use an intent from an other app. If this other app is not installed when its intent is needed, I would like to offer it for download and install.
Question: If the downloaded app is opened (by the user) immediately after installing it, I would need it to open the specific intent the first app needs instead of opening it as normal. See image below.
What options do I have available, is there a common pattern for this? Thanks in advance.
If the downloaded app is opened (by the user) immediately after installing it, I would need it to open the specific intent the first app needs instead of opening it as normal.
That is not possible, strictly speaking. There is nothing stopping the user from pressing Open, and that will behave as normal -- you cannot change this.
If you are the author of the, um, "Monkey Trampoline" app, you could work out various hacks to recognize that it is being opened after an install from, um, "Animal Olympics", so it can route its logic accordingly (use a custom sticky broadcast, have the second app use some IPC to ask the first app "yo, am I supposed to do something special?", etc.).
It is also conceivable that ACTION_PACKAGE_ADDED will be broadcast before the user clicks either Done or Open (or HOME or BACK or whatever). In that case, you could listen for that broadcast, determine that, indeed, the app just installed does involve simian somersaults, and call startActivity(). This will be a bit jarring for the user, insofar as all of a sudden they'd be transported from the install process into this new app. And, since the precise timing of ACTION_PACKAGE_ADDED is undocumented, your mileage may vary (e.g., the user could still get a chance to tap Open before the broadcast winds its way to your app).
I want to create an app or background service that just listens for the launch of a 'default' app, say Contacts or the built-in Gmail app. If the contact app is clicked, I want to transfer control to my app temporarily (e.g. present a Yes/No popup to the user or increment an internal counter of my app ) and then redirect the user back to the app that was clicked. I want to do this only for a couple of 'well-known' built-in default apps, not any third party apps.
Is this possible? May be using some special intents?
Have you tried registering broadcast receivers for the intents that would launch those built-in apps? This might not work since that might confuse Android into thinking your app is a potential target for those intents (e.g. that it should be used to actually write and send the email in the case of a 'compose an email' intent), but it should be a good place to start.