I'm trying to have other apps share PDF files with mine, I have an intent filter for android.intent.action.SEND type pdf files but some apps send the intent with the FLAG_ACTIVITY_CLEAR_TASK which closes the activity that was already running.
Is there any way to ignore this flag? I want to keep the current activity running when shared to my app.
EDIT: a good example
I share a PDF with google drive pdf viewer, my activity that is already running picks it up and the intent is received in "onNewIntent" (desired).
When I do the same thing with Samsungs "my files" my activity gets restarted and the intent is given to "onCreate" (not desired)
I share a PDF with google drive pdf viewer, my activity that is already running picks it up and the intent is received in "onNewIntent" (desired).
When I do the same thing with Samsungs "my files" my activity gets restarted and the intent is given to "onCreate" (not desired)
Your app should work correctly regardless of how it's invoked. What difference does it make to you whether it's a new instance receiving the intent or the existing one? You're not always going to have an existing instance around, right? If you share from Google before starting your activity, you'll be in the same position, won't you?
Related
Refering to this post I need to ask something else.
I have an application "A" which download and install another app "B".
I want B to "transfer" data to A and then A will use this data to do work.
I know that we can transfer data with intent.
After installing B app with A, Android provide a choice with "Ok" or "Launch" ; my question is :
Is that possible to pass data from B to A when we click on "Ok"? (So we stay in A app without launching B)
If yes, how? Is that possible to "invisible" launch B? How should I code B to get this comportement?
I know that might be hard to understand, you can try to check my previous draw (here again).
EDIT:
I use this code to launch B installation from A.
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Uri uri = Uri.fromFile(new File(Environment.getExternalStorageDirectory().toString() + "/downloadedfile.apk"));
Intent.setDataAndType(uri, "application/vnd.android.package-archive");
getApplicationContext().startActivity(intent);
There are many ways to handle this, here is one that (I believe) is quite simple to implement. Since your A app [presumably] knows what it is installing:
App A: Add a BroadcastReceiver to react to the installation, though by default it is off.
Android: BroadcastReceiver on application install / uninstall
App B: Add a Service for background communication.
Note: A Service must be exported to be accessible to other apps via explicit intent, but this creates a security concern, as it is open to all other apps.
When a user of App A clicks to install App B:
Start the BroadcastReceiver with a filter set to detect the install:
stackoverflow...android-broadcastreceiver-on-application-install-uninstall
App A starts the install.
When the BroadcastReceiver detects the package has been added (the package name will be in the received intent,) it can stop the BroadcastReceiver, and can send an explicit Intent naming the Service in AppB. You can pass whatever data you need in the intent.
When the AppB service receives the intent, it can act in any way you'd like.
Service is always created using a non-null Intent, though the 'action' of explicit Intents is null.
Service.onStartCommand() might receive a null Intent if the service was re-created.
I'd fill in more of the code, but I have a day job ;)
Note:
Intent.ACTION_PACKAGE_ADDED called when a package is installed.
Intent.ACTION_PACKAGE_INSTALL was never used, and was deprecated in API 14.
http://developer.android.com/reference/android/content/BroadcastReceiver.html
http://developer.android.com/reference/android/content/Intent.html
Our activity can be launched from a GCM notification. We set extras in the GCM intent to ensure the user is taken to the message thread for that GCM notification, and we call removeExtra afterwards to remove it from the intent.
If the user launches our app from the recent history menu, then the activity is started with the same intent as from the previous launch (e.g. from the GCM notification).
This scenario is quite easy to detect:
Intent i = getIntent();
// If the caller intent is from the recent apps and has the RECIPIENT_ID_KEY
// extra we should remove it to avoid open the messages thread again
if (((i.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0) &&
i.hasExtra(MyConstants.RECIPIENT_ID_KEY)) {
i.removeExtra(MyConstants.RECIPIENT_ID_KEY);
}
However, we also want this to work if the activity has been destroyed by the OS. At the moment, when the Developer option "Do not keep activities" is set (only available on OS 4.0+), then the activity keeps being recreated with the same intent when pressing the Back button from another one of our screens, resulting in bad things happening.
I considered adding a unique extra in our GCM intent and saving that in Shared Preferences once we have processed it. However, we also need this to work when sharing an image into our app through a SEND image/jpg intent. We don't control that intent, so how will we know if we've already processed it? I guess we could use the file/URI information, although that means if a user shares the same image twice in a row, we'll ignore the second one.
Is there a clean and simple way to solve this problem?
We currently support OS 2.3+, and our application is available all around the world. Here's the relevant section of my AndroidManifest.xml:
<activity
android:name=".ui.MyClass"
android:configChanges="orientation|screenSize"
android:launchMode="singleTop"
android:windowSoftInputMode="stateHidden" >
I was interested in how to solve the part:
However, we also need this to work when sharing an image into our app
through a SEND image/jpg intent.
As soon as I handle the images I put an extra flag on the Intent. As you can imagine, I check for that flag before doing the files processing. This worked even if the Intent was created by another application.
I have to attach an image file with the sms on button click i use this code
final Intent smsIntent = new Intent(android.content.Intent.ACTION_SEND);
smsIntent.putExtra("sms_body", "Hello World!");
smsIntent.putExtra("address", "0123456789");
smsIntent.putExtra(Intent.ACTION_ATTACH_DATA,screenshotUri);
smsIntent.setType("image/png");
startActivity(smsIntent);
But this shows a chooser to choose an action like Facebook,Email,Messages etc.
But i do not want any the chosser view it will directly show the message intent with attached file.
What you are looking for cannot be done using implicit Intents. Because that is how the Android system is designed to handle implicit intents. If you want your intent to be handled by a specific application then you have to make them explicit, i.e., specify a component that has to handle the intent. But when you use explicit intents to handle any situation such as yours, then there is a great chance of your app to break when the specific component (i.e. Application) doesn't not exist in the target device. Android is being adopted by several OEMs, therefore each of them tend to replace the stock Messaging application with their own. So what seems to work on one device may not work on the other.
If you want to achieve what you want then you may have to get the list of Messaging applications on various devices, (you can find the stock Android app's component name from the emulator itself). And use the PackageManager to find if the component exists. If it does, the start and explicit intent, in which you won't receive an IntentChooser. If the component doesn't exist send an implicit intent.
You can learn more about intents from here.
Determining if an Activity exists on the current device? - This post will help you to find if the target component exists.
I have this piece of code
private void initiateInstallation() {
Intent intent = new Intent(Intent.ACTION_VIEW);
Uri uri = Uri.fromFile(new File("/sdcard/example.apk"));
intent.setDataAndType(uri, "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
that from within my service installs an application named example.apk
I want after the installation is finished to run an activity which notifies the user about the installation.I did that except the activity appears before the installation finishes.
The problem is that within a service I cannot use startActivityForResult. So, I need a way around this so that I can start my notification activity(or for the sake of example just print something out with Toast within the service) only AFTER the installation is complete.
I already tried some answers from other questions like "alternative to startActivityforResult in services" but still I couldn't figure this out.
I also put the code so that maybe there may be something done in there.
Thanks in advance ... any suggestions are welcome.
You could listen to the PACKAGE_ADDED broadcast intent: http://developer.android.com/reference/android/content/Intent.html#ACTION_PACKAGE_ADDED
As far as I know, these are sent after the installation is done, and you can listen to those from the service.
Just note that if the application was already installed, you will get ACTION_PACKAGE_CHANGED (as far as I know).
Also you must know the package name as well, not just the apk name, since the intent will contain the package name.
The answer given by #Pal Szasz is technically correct (as far as I know ;-) ).
However, based on the information given in your question, I assume you only wish to show a notification (no further programmatically actions are to be performed). If my assumptions are correct I would respectfully advise you NOT to show such a notification. And this is why:
The Android system already has a standard means of passing notifications to the user. The status bar will in this case already show you a message saying that the new app is successfully installed (or not installed in case of an error). If you implement yet another notification channel you will most likely confuse or irritate your users by diverging from the standard, expected behaviour.
Taking this beyond the borders of sanity one could also argue for the fact that you in some sense also would contribute to the fragmentation of Android (in a very small scale, but nevertheless).
I'm trying to write a launcher-like application (I'm not planning to release it, it's just for me to use) but I don't seem to find any way to launch the Market.
All of the answers I've found actually perform a search on the Market (using a uri "market://") or even worse they run the Market on a specific app page, while I'm trying to show the main page of the Market, i.e. the page shown when you run it from the launcher.
I tried using just "market://" as a Uri, without query strings, but it doesn't work; I also tried to get exactly the same "signature" of the "start activity command" that appears in the LogCat when I run the Market from the Launcher (by manually editing component, flags and categories), but it still doesn't work.
Is there any way to get it to show the main page?
Thanks in anticipation.
Intent intent = new Intent();
intent.setClassName("com.android.vending", "com.android.vending.AssetBrowserActivity");
startActivity(intent);