I am working on an app were I am going to open other apps. The only problem is that I do not know how to refer to third party apps. I am planing to use an intent. Can you refer to it useing only the packagename, or do you need the Main Activity intent. Are there any simple ways of finding the right intent, and then refer to it.
I am working on an app were I am going to open other apps.
I am interpreting this as meaning that you are creating a launcher, akin to the ones found on home screens.
Can you refer to it useing only the packagename, or do you need the Main Activity intent.
Launchers use an ACTION_MAIN/CATEGORY_LAUNCHER Intent.
Are there any simple ways of finding the right intent, and then refer to it.
Use PackageManager to find all the possible ACTION_MAIN/CATEGORY_LAUNCHER activities on the device, and then display those to the user to choose from. You can then construct a suitable Intent for starting up their specific choice.
Here is a sample project that implements a launcher.
To come up with the list of things that could be launched, that sample app uses:
PackageManager pm=getPackageManager();
Intent main=new Intent(Intent.ACTION_MAIN, null);
main.addCategory(Intent.CATEGORY_LAUNCHER);
List<ResolveInfo> launchables=pm.queryIntentActivities(main, 0);
And here is the actual launching logic, based upon the user clicking on one of those "launchables" in a ListActivity:
#Override
protected void onListItemClick(ListView l, View v,
int position, long id) {
ResolveInfo launchable=adapter.getItem(position);
ActivityInfo activity=launchable.activityInfo;
ComponentName name=new ComponentName(activity.applicationInfo.packageName,
activity.name);
Intent i=new Intent(Intent.ACTION_MAIN);
i.addCategory(Intent.CATEGORY_LAUNCHER);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
i.setComponent(name);
startActivity(i);
}
Related
I have a problem (2 problems to be exact) with launching intents from a Notification.
My current situation is that I have a family of apk that all can use a remote service launched by the first of them. The service creates an Notification and when clicked the opens back the application that launched the service. This works ok.
I wanted to improve that so when there is more than one application from the family installed, instead of just going to the apk that launched the service an chooser Intent would appear and the user would be able to choose the apk to come back to.
I managed to do this.
ArrayList<String> myApps = Lists.newArrayList(
"com.myapp1",
"com.myapp2",
"com.myapp3",
"com.myapp4"
);
List<Intent> targetedIntents = new ArrayList<Intent>();
Intent baseIntent = new Intent(Intent.ACTION_MAIN, null);
baseIntent.addCategory("android.intent.category.LAUNCHER");
final PackageManager packageManager = getApplicationContext().getPackageManager();
List<ResolveInfo> list = packageManager.queryIntentActivities(baseIntent, 0);
for (ResolveInfo resolveInfo : list) {
String packageName = resolveInfo.activityInfo.packageName;
if (packageName != null && myApps.contains(packageName)) {
Intent targetedIntent = new Intent();
targetedIntent.setPackage(packageName);
targetedIntent.setClassName(packageName, resolveInfo.activityInfo.name);
targetedIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
targetedIntents.add(targetedIntent);
}
}
Intent intent = Intent.createChooser(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=whatever")), "Select app to return to");
intent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetedIntents.toArray(new Parcelable[]{}));
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, intent.getFlags());
notification.setLatestEventInfo(this, notificationTitle, notificationMessage, contentIntent);
This works mostly as it should. The chooser appears and the selected option launches the desired apk.
But I came across 2 problems:
I. When I create the intent chooser with only the intents that interest me, the chooser is empty with the message "no application can perform this action"
intent = Intent.createChooser(targetedIntents.get(0), "Select app to return to");
intent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetedIntents.toArray(new Parcelable[]{}));
But if I put an existing apk there first (such as google play) everything works and my options show along with the google play option.
intent = Intent.createChooser(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=whatever")), "Select app to return to");
intent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetedIntents.toArray(new Parcelable[]{}));
This is something I can live with, but it would be better if onlye the proper apks were there.
II. When I click the apk from the list, instead of coming back from the background (if the apk was already running there) it restarts it. I have the proper flags set.
Intent targetedIntent = new Intent();
targetedIntent.setPackage(packageName);
targetedIntent.setClassName(packageName, resolveInfo.activityInfo.name);
targetedIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
Before using the chooser I launched only one intent and it resummed the background apk normally.
intent = new Intent(this, MainActivity.class);
intent.setAction("android.intent.action.MAIN");
intent.addCategory("android.intent.category.LAUNCHER");
Not sure what I am doing wrong here that the apk restarts insted of resuming.
For the first problem (chooser issue), the reason you are getting the error "no application can perform this action" is because the Intent you are passing to getChooser() doesn't have an ACTION in it that Android can use to search for applications that can handle the Intent. getChooser will use the ACTION, CATEGORY and DATA in the Intent to search for suitable applications. It will then use package and component names to filter this list. In your case, because you've only provided the package and component names (but haven't specified ACTION), Android can't find any suitable applications. I'm not sure there's a way around this, since you want to build a list with different packages. You may just need to create your own chooser dialog (which is probably the correct thing to do here anyway, as you don't really get any advantages using the Android chooser because you've already decided what the list should contain).
For the second problem (if application is in background, it gets restarted) you need to use the following flags:
targetedIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
Specifying Intent.FLAG_ACTIVITY_NEW_TASK when launching the root activity of a task will bring an already existing task to the foreground.
NOTE: If you want to just bring the existing task to the foreground (in whatever state it happens to be), then just use Intent.FLAG_ACTIVITY_NEW_TASK and remove the other 2 flags.
I have two standalone applications i.e A and B. A needs some functionality from B. Application A calls an intent of Application B. Application B receives the request and process it and send back the result to A. Just like the Zxing Barcode Application.
How could i achieve the above? Any idea?
final Intent intent = new Intent(Intent.ACTION_MAIN, null);
final ComponentName cn = new ComponentName("com.your.package","package.class");
intent.setComponent(cn);
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivityForResult(intent);
or
Intent intent = getPackageManager().getLaunchIntentForPackage("com.your.package");
startActivityForResult(intent );
Replace com.your.package with Application B package id.
Actually, it reminds me of startActivityForResult method.
http://developer.android.com/reference/android/app/Activity.html#startActivityForResult(android.content.Intent, int)
Rather good example:
http://www.vogella.com/articles/AndroidIntent/
I created an app that acts as a launcher, which works as expected, but I'd like to give the user the ability to launch the native Android Launcher.
I know that the package name for the Android Launcher is com.android.launcher
However, when I try to get the Launch intent name from this package by calling
packageManager.getLaunchIntentForPackage("com.android.launcher");
that comes up null.
So, I'm at a loss as to how to use the package name to launch it, and am wondering if perhaps there's some alternate way?
TIA
I know that the package name for the Android Launcher is com.android.launcher
Except that may or may not be on any given device. In fact, I would expect it to be on maybe a few percent of devices. Most manufacturers replace the stock home screen with their own.
am wondering if perhaps there's some alternate way?
Use PackageManager and queryIntentActivities() to find all activities that support ACTION_MAIN and CATEGORY_HOME. Remove your activity from the list. If there is only one left, launch that activity. If there is more than one left, whip up your own chooser to show the available options. That way, no matter what other home screen(s) exists, you will be able to launch it.
UPDATE
Given a ResolveInfo named launchable, and an ACTION_MAIN/CATEGORY_HOME template Intent named i, to launch that activity, do:
ActivityInfo activity=launchable.activityInfo;
ComponentName name=new ComponentName(activity.applicationInfo.packageName,
activity.name);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
i.setComponent(name);
startActivity(i);
I am working on an app where I am useing a PackageManager to import all the package names on the device using this code:
protected void onListItemClick(ListView l, View v, int position, long id) {
ResolveInfo launchable=adapter.getItem(position);
ActivityInfo activity=launchable.activityInfo;
ComponentName name=new ComponentName(activity.applicationInfo.packageName,
activity.name);
Intent i=new Intent(Intent.ACTION_MAIN);
i.addCategory(Intent.CATEGORY_LAUNCHER);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
i.setComponent(name);
startActivity(i);
}
This code manage to start the app from a ListView. But I want to send the app details to another class to start it from there instead of starting it from this class. Then I want the result to be saved but changeable by clicking on another app later.
Are there any ways of doing this?
If you only want to select the app from the list and start it using a separate button click, then how about storing the activity.applicationInfo.packageName and activity.name to SharedPreferences once list item is selected. In case the user select other item from the list overwrite the SharedPreferences parameters.
When the start button is clicked read these parameters and launch the app.
How about binding to a service, sending a message to that service, and the service will start the activity?
Or registering a broadcast receiver, sending an intent to that receiver, with the requested application as extra information, and having the broadcast receiver do the work?
I am trying to get the following code to execute:
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
intent.setComponent(new ComponentName(" **Home package** "," **Home class** "));
startActivity(intent);
Essentially I am looking for a way to specifically target and load the exact, original, home application.
Technically, you have no way of always knowing "the exact, original, home application".
You can use PackageManager and queryIntentActivities() to find find who all responds to MAIN/HOME Intents. If there are two answers, and yours is one (which I am guessing is your situation), then the other is "the exact, original, home application" pretty much by definition. You can further verify this by getting to the ApplicationInfo object associated with the resolved activity and checking for FLAG_SYSTEM to see if it is installed in the system image. This approach is probably not completely bulletproof, but it may be close enough for your needs.
Yet another option is for you to simply record the current default MAIN/HOME activity when you are run for the first time. Odds are decent that your application will be run before the user elects to make you the default. Again, this has holes (e.g., they make you the default before running you for the first time).
EDIT: SOLUTION:
PackageManager pm=getPackageManager();
Intent main=new Intent(Intent.ACTION_MAIN, null);
main.addCategory(Intent.CATEGORY_HOME);
List<ResolveInfo> launchables=pm.queryIntentActivities(main, 0);
Collections.sort(launchables,
new ResolveInfo.DisplayNameComparator(pm));
int launcher_flag = findLauncherApp(launchables);
ResolveInfo launchable = launchables.get(launcher_flag);
ActivityInfo activity=launchable.activityInfo;
ComponentName name=new ComponentName(activity.applicationInfo.packageName,
activity.name);
Intent i=new Intent(Intent.ACTION_MAIN);
i.addCategory(Intent.CATEGORY_LAUNCHER);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
i.setComponent(name);
startActivity(i);
Where findLaucherApp() turns the List into an array of strings and interrogates each one to see if it contains "com.android.launcher2" and then returns its id.