I have a keyguard appwidget where I'm launching a few different Intents. It seems I can launch /system apps (mms, settings etc. ) . but not /data apps ( chrome for example )
I have the following PendingIntentTemplate defined:
Intent startApplicationIntent = new Intent();
PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, startApplicationIntent, 0);
mainLayout.setPendingIntentTemplate(R.id.stackview, pendingIntent);
In my RemoteViewsFactory, I have the following FillInIntent:
Intent i = pm.getLaunchIntentForPackage(pkgName);
i.addCategory(Intent.CATEGORY_LAUNCHER);
i.setAction(Intent.ACTION_MAIN);
stackviewRemoteView.setOnClickFillInIntent(R.id.stackview_image, i);
There are no errors, the intent just unlocks the keyguard.
It also definitely isn't null as the toString() method shows the following:
Intent { act=android.intent.action.MAIN cat=
[android.intent.category.LAUNCHER] flg=0x10000000
pkg=com.android.chrome
cmp=com.android.chrome/com.google.android.apps.chrome.Main }
Is there something special I need to do for non-system apps? I thought getLaunchIntentForPackage would give me everything I needed to launch an app the same way as it would launch if it were selected from the home screen.
Seems that the way I was doing this was making a few assumptions.
PendingIntent.getActivity calls startActivity(), which requires CATEGORY_DEFAULT to be specified.
The following code is probably 'more correct' and less likely to throw errors that CATEGORY_DEFAULT can't be found:
Intent i = new Intent();
i.setPackage(pkgName);
i.addCategory(Intent.CATEGORY_DEFAULT);
Related
I am using the code to call an intent in Android
Intent intent = new Intent();
String PACKAGE_NAME="com...."
intent.setPackage(PACKAGE_NAME);
intent.setAction(Intent.ACTION_VOICE_COMMAND);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
getApplication().startActivity(intent);
Unfortunately, in some case, I do not know the PACKAGE_NAME. So, another method is using broadcast. How can I use it? Thanks all
You cant call Activity directly if you dont know package and name of that Activity.
Since you dont know package and Activity name you can only ask OS to show all possible variants for your Intent Action. In most cases user click "always open this app for this action" what means that you will directly open another app.
So in your case your code should looks like
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VOICE_COMMAND);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
//dont forget to check if user has at least one application for your Intent Action
if (intent.resolveActivity(getPackageManager()) != null) {
context.startActivity(intent);
}
I have yet another question. I did some research into how to properly send an intent from a BroadcastReceiver to an activity. everyone suggests doing the following:
To construct an intent and use the context provided in the receiver to start that intent. However, I would always get an error when trying to do so saying
AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
So when I googled about that error, people seemed to suggest that you want to add specific flags to the intent. But even with this flags present I am getting the same error. Any help would be appreciatd.
Intent intentMain = new Intent(context.getApplicationContext(), MainActivity.class);
intentMain.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
intentMain.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent.putExtra("com.hennessylabs.xxx.FROM", senderNum);
intent.putExtra("com.hennessylabs.xxx.MSG", message);
context.startActivity(intentMain);
It looks like you are trying to start MainActivity.class from your BroadcastReceiver. That is fine. Though I don't see why you have done what you did in the 2nd and 3rd lines you provided when adding flags. Why don't you just do this:
intentMain.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
So your whole code block should look like this:
Intent intentMain = new Intent(context.getApplicationContext(), MainActivity.class);
intentMain.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("com.hennessylabs.xxx.FROM", senderNum);
intent.putExtra("com.hennessylabs.xxx.MSG", message);
context.startActivity(intentMain);
Intent intent = new Intent(context,MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
and then in manifest file
in mainactivity
launchmode= singleTask
or as per your requirements, you can use some other combinations also
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 encounter this flag - FLAG_ACTIVITY_RESET_TASK_IF_NEEDED paired with FLAG_NEW_TASK.
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.applicationA", "com.applicationA.Activity1"));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
startActivity(intent);
This was in the following context:
1. The browser application recognized a phone number.
2. User can long press it and get a context menu with a "dial" option.
3. the browser then fires the above intent to open the dialer.
I have read the documentation for this flags over and over again, and tried playing with it, changing the activities affinities and still have no clue as to what should be the expected behavior here.
Any help is appreciated.
Merged with Android-Close Other Apps.
How can I kill other applications? I can launch other applications using intents but can't find a way to kill them.
This launches the application:
Intent i = new Intent();
i.setAction(Intent.ACTION_MAIN);
i.addCategory(Intent.CATEGORY_LAUNCHER);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.setComponent(
new ComponentName("com.bla.bla...",
"com.bla.bla.Main"));
context.startActivity(i);
I've tried to use the activity manager's kill
killBackgroundProcesses(String packageName)
but that does nothing.
I've also tried
appContext.stopService(intent)
but that did nothing