What's the function of `Intent.setPackage()` - android

What's the function of Intent.setPackage(String packageName), since the intent will find a match through the componentName set by Intent.setClassName(Context packageContext,String className) or Intent.setComponent(ComponentName component), you can find a match even you set a wrong packageName to the Intent.setPackage(String packageName).

setClassName() Targets an exact package name and exact component you want to run.
e.g. if you want to use the Gmail app to send an email using this to run the exact Activity(Component) you want to run.
setPackage() targets an exact application and offers you all components that can handle your intent.
If you don't fill these two it targets all apps and components which is not ideal in some cases e.g. you want to target only WhatApp to share content. If there is a case that you want to share that content on any social media app just ignore these two and stick with action, data, and ... fields.

Related

Start activity in another app with restricting receiving app to have same signature

I have two apps A and B. At some point A calls startActivityForResult() with Intent that points to activity in B (using "action" attribute). Both apps will be downloaded from Google Play and will be signed with the same certificate.
Since some sensitive information will be exchanged in the Intent's data I want to prevent a bad actor from replacing app B and installing his own version with same package name and action attribute which will receive the control from app A when startActivityForResult() is called.
I know how to ensure that app B is called only from app A (custom permission) but I was wondering, is there a way to ensure that when app A class startActivityForResult() that only my app B will receive the Intent?
"installing his own version with same package name"
although playstore allows for apps to have duplicate names it enforces the uniqueness of any app package name. so this shouldnt happen.
moreover, you can use a custom action attribute name for starting B .
hope this is helpful for now .

How to get available "app shortcuts" of a specific app?

Background
Starting from API 25 of Android, apps can offer extra shortcuts in the launcher, by long clicking on them:
The problem
Thing is, all I've found is how your app can offer those shortcuts to the launcher, but I can't find out how the launcher gets the list of them.
Since it's a rather new API, and most users and developers don't even use it, I can't find much information about it, especially because I want to search of the "other side" of the API usage.
What I've tried
I tried reading the docs (here, for example). I don't see it being mentioned. Only the part of other apps is mentioned, but not of the receiver app (the launcher).
The questions
Given a package name of an app, how can I get a list of all of its "app shortcuts" using the new API?
Is it possible to use it in order to request to create a Pinned Shortcut out of one of them?
You need to make yourself the launcher app. After that you can query the packagemanager to get the shortcutinfo for a particular package:
fun getShortcutFromApp(packageName: String): List<Shortcut> {
val shortcutQuery = LauncherApps.ShortcutQuery()
shortcutQuery.setQueryFlags(FLAG_MATCH_DYNAMIC or FLAG_MATCH_MANIFEST or FLAG_MATCH_PINNED)
shortcutQuery.setPackage(packageName)
return try {
launcherApps.getShortcuts(shortcutQuery, Process.myUserHandle())
.map { Shortcut(it.id, it.`package`, it.shortLabel.toString(), it) }
} catch (e: SecurityException) {
Collections.emptyList()
}
}
A full implementation of this can be found here:
https://android.jlelse.eu/nhandling-shortcuts-when-building-an-android-launcher-5908d0bb50d2
Github link to project:
https://github.com/nongdenchet/Shortcuts
LauncherApps is a class provided by the Android framework:
https://developer.android.com/reference/android/content/pm/LauncherApps.html
"Class for retrieving a list of launchable activities for the current user and any associated managed profiles that are visible to the current user, which can be retrieved with getProfiles(). This is mainly for use by launchers. Apps can be queried for each user profile. Since the PackageManager will not deliver package broadcasts for other profiles, you can register for package changes here."
Great Question this was what i was looking for and I get one that might be useful
(Its all about Intent)
https://github.com/googlesamples/android-AppShortcuts
Note: If your app is static its simple to implement.
Updated:::
Here is a link that will show you the difference of dynamic or static shortcuts and its implementation if you like it please up vote.
https://www.novoda.com/blog/exploring-android-nougat-7-1-app-shortcuts/

Is there an intent for uninstallation of an app for ALL users?

Background
The normal way to call for the uninstallation an app is simply by using the "ACTION_DELETE" intent :
startActivity(new Intent(Intent.ACTION_DELETE, Uri.parse("package:" +packageName)));
The problem
starting with some Android version (don't remember which) , apps can be installed for multiple users on the same device.
This means there is a new way to uninstall an app, one which will uninstall it for all users (image taken from Lollipop - Android 5.0 ) :
The question
I've searched in the documentation, but couldn't find the answer those questions:
Is there any way to perform this operation via an intent? Maybe something to add to the intent I've written above ?
Does ADB have a new command to remove an app for all users?
Is there a way to check if an app is installed for multiple users?
Is there any way to perform this operation via an intent? Maybe
something to add to the intent I've written above ?
Yes, but be careful. You can pass in Intent.EXTRA_UNINSTALL_ALL_USERS.
However, it's hidden because it:
should not be part of normal application flow
You could just pass in the constant anyway, if you feel it's necessary and disagree with Google on that one. Just for example, here are the differences between passing in false and true with that constant
final Uri packageURI = Uri.parse("package:" + "some.package.name");
final Intent uninstallIntent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE, packageURI);
uninstallIntent.putExtra("android.intent.extra.UNINSTALL_ALL_USERS", false or true);
startActivity(uninstallIntent);
Results
Does ADB have a new command to remove an app for all users?
No, the command remains the same.
`adb uninstall 'some.package.name'`
This will remove that app for all users. I'm unaware of a way to specify a particular user.
Is there a way to check if an app is installed for multiple users?
No, not that I'm aware of. In fact, when the Settings apps decides to place the "Uninstall for all users" option in the options menu, it's basically doing so based on whether or not there are multiple users period, not if both the current user and another user have an app installed.
Not to mention, most of the methods in UserManager that you'd need to even tell if there are multiple users on the device, like UserManager.getUserCount, require the MANAGE_USERS permission which is a system API and hidden. So, I'm not even sure why that's a public method.
Also, you can easily test all of your questions, much like I did, by creating a dummy user on your device. You don't even need to log into a Google account.

Tell if running AOSP or Google Android?

I've searched and cannot find this, though mainly a challenge of knowing what to search for, I'm sure it's been asked before.
How does an app deduce whether it is running on a "Google Android" device, or an AOSP device (e.g. Kindle Fire etc)?
You can try to enumerate an existing accounts on device using AccountManager class: getAccountsByType(), passing com.google as desired account type. If there is no accounts of this type, this mean either it is AOSP device or the user didn't create Google account yet.
If it is not enough for you, you can use PackageManager class and query some Google-specific package using getPackageInfo() method. For example, com.android.vending - Google Play app.
But pay attention that no one of these methods can guaranty you that target device is running AOSP.
This is not trivial, but most apps do not need to even care. If you do, then it usually means you need some unique features therefore it's simpler to check if certain feature is present or not, instead of what label is on the device. You may also check for presence of certain packages (like Google Play), but lack of it does not mean automatically it is i.e. Fire.
You can check whether you can open market urls by using an Intent.
Documentation on the intent's extras is here.
The Intent would look like this:
try {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("market://details?id=com.example.android"));
//you can use any package identifier for the check.
startActivity(intent);
} catch (ActvitiyNotFoundException anfe) {
//There's no market installed.
//So you can guess that you're not on a device with Google experience
}
The downside of this method would be, that the user will be taken to the Play Store if it's available.

create a permissions to restrict third party apps calling an activity android

I am having two android apps signed with same certificate. Also i am using the activity of one app in other android app by specifying a name in "intent-filter" tag. But because of "intent-filter" tag any third party app can call my activity.
Since both the apps are having the same certificates signed, can i restrict other apps calling my activity by providing some permisions? Any suggestions on this would be helpful to me.
-Ron...
First you could maybe remove the intent-filters if your activity is not meant to be used by other applications than yours ; why not use an explicit intent instead?
Thus your activity couldn't be created "by mistake" but only intentionally, ex :
Intent explicitIntent = new Intent(InvokingActivity.this, InvokedActivity.class);
startActivity(explicitIntent);
Then, to even prevent that from the outside, you could define your own custom permission and add it to your activity ; have a look at the android:protectionLevel attribute of a permission, whose value can be "signature".

Categories

Resources