Android: how to verify package is genuine - android

In one of my apps, I would like to detect if the user has got another app of mine installed.
This code works:
PackageManager pm = mAppContext.getPackageManager();
try {
pm.getPackageInfo("com.example.packagename", PackageManager.GET_ACTIVITIES);
// do something
} catch (PackageManager.NameNotFoundException e) {
// nothing to do
}
But I wonder how I can verify that the user has genuinely downloaded the app from Google Play. I guess it would be possible to install a non genuine package with the same package name, right?

PackageManager has a method getInstallerPackageName that for given package name gives you name of the installer. For pre-loaded(unless they are not installed from other 'market' like SamsungApps) and self-installed applications will return null. For applications originating from Google Play you should get com.android.vending. And I don't think that you are able to install two applications with the same package names declared in the manifest.

Related

Get Split APK Info in Android

I have a 3p appstore app which installs other apps. From my app, installing both single and split APKs are supported.
For apps with split APKs, during install time, I only install the required APKs like only the APK for the selected language on device.
Now when the device language changes, I want to install the new language APKs for all the apps which my app has installed. Before triggering install, I need to first check if that language APK is already installed or what all APKs are installed for a specific package name.
In Android, I didn't find any APIs which can give me if some language APK is installed or the info about all the installed APKs. Any way to get this info?
Edit-1: I cannot use Play core libraries. I am looking for a way using the classes from Android.
This is not possible.
Using the package names of the apps you have installed, you can get all the split APKs from PackageInfo.#applicationInfo but doesn't provide any additional info about that.
Playcore has some classes like SplitInstallManager which has methods getInstalledModules, getInstalledLanguages etc which can be used to get installed APKs but not sure if you can get info about other apps too.
Code:
public static boolean isConfigInstalled(PackageManager pm, String pkg, String conf) throws PackageManager.NameNotFoundException
{
// get application info for installed app
ApplicationInfo ai=pm.getApplicationInfo(pkg, 0);
// get installed split's Names
String[] sn=ai.splitNames;
// check whether if it's really split or not
if (sn != null && sn.length > 0)
{
// search installed splits
for(String n:sn){
// check whether is the one required
if(n.equals("config." + conf)){
// yes, it's installed!
return true;
}
}
}
// couldn't find!
return false;
}
How to use:
Just pass the package manager that you get by context.getPackageManager() along with the App's package name and the language code
Example:
PackageManager pm=getPackageManager();
String pkg="com.snapchat.android";
String languageCode="ur";
if(isConfigInstalled(pm, pkg, languageCode)){
System.out.println("Snapchat has Urdu Installed!");
}else{
System.out.println("Snapchat doesn't has Urdu Installed!");
}
Output:
Snapchat has Urdu Installed!

Create secondary app manager such as (facebook app manager)

Is there away to install secondary app when the user installs the APK?
The secondary app porpoise is to save local data that will be shared between multiple apps and detect + listen to app removal package.
I have seen that Facebook is doing something similar they have 2 apps called (Facebook App installer + Facebook App Manager)
you can do with the help of package name of the other app.
so once your first app is installed in phone , at some point yo can check for other app with the help of package name if it is installed or not by using below code
PackageManager pm = getPackageManager();
try {
pm.getPackageInfo(uri, PackageManager.GET_ACTIVITIES);
return true;
} catch (PackageManager.NameNotFoundException e) {
}
and if that is not the case you can take user to play store to get it installed.
Happy Coding :) !!

Allow only selected apps for sideloading in Android

I am trying to customize Android for a media device. We got the firmware from the manufacturer and it's based on Android 7 with minor modifications.
One of the things we would like to do is to restrict installation of apps on the device to certain apps only. We won't install any app store like Google Play on the device. We will build the firmware and install all apps onto the devices at our workshops and deliver to the customers. In future, we may want to install more apps on the devices via OTA or some mechanisms.
We would like to disallow customers sideloading other apps via USB port. We created a file (eg., whitelisted_apps.txt) that has the list of all approved app names, such as -
com.mycompany.android.app1
com.mycompany.android.app2
com.ourpartner.android.appx
We tweaked the PackageInstaller app of AOSP so that when a *.APK file is opened via the file browser and when the methods in PackageInstallerActivity.java are called, it will compare the name of the app to be installed against those in whitelisted_apps.txt and if the name is not found, disallow installation of the new app. It's working.
Now, we want to improve it further because whitelisted_apps.txt can be manipulated. Some people suggest using sqlite to keep the list. We are not sure if it will be the best solution.
Some suggest using certificates and signing and we think it's a better solution than others. We will sign all the apps we want to install on the device with our key. When a *.APK file is sideloaded, the PackageInstaller will get the signature of the APK and compare against ours. If they match, the app can be sideloaded.
We followed this excellent resource: SignatureCheck.java. It's working with the hardcoded APP_SIGNATURE. We have this currently:
public boolean validateAppSignature() throws NameNotFoundException {
boolean sigMatch = false;
String APP_SIGNATURE = "123456784658923C4192E61B16999";
PackageInfo packageInfo3 = mPm.getPackageInfo(
getPackageName(), PackageManager.GET_SIGNATURES);
try {
for (Signature signature : packageInfo3.signatures) {
// SHA1 the signature
String sha1 = getSHA1(signature.toByteArray());
Log.i(TAG, "got this SHA1 of the signature ... "+sha1);
// check if it matches hardcoded value
sigMatch = APP_SIGNATURE.equals(sha1);
if (sigMatch){
return sigMatch;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
Just that we don't know how to do that in a real world situation. When we build, install apps or release with OTA, we sign those apps with our private key and then on the device (PackageInstaller app), we hardcode our certificate's SHA1 signature as APP_SIGNATURE so that we can compare? Any other ideas?
Thank you so much.
Seems like you're trying way too hard to partially shut down sideloading. Use a Device Owner to completely turn off installation, and just preload the apps you want. Or make it so the only app that can install is your own downloader that only looks at your server.

How one does an app detect wheteher another app is installed and signed up by the user in their phone?

There are many android apps promoting other apps and gives rewards for installing the apps.So actually how , in android it is done - that in an app we can check the user's android pone if the targeted app is installed or not and even more than that they check whether an user is signed up for that app or not and then they give the rewards once they find out that the other app is installed and signed up by user..(I am obviously not talking about launching intent to open the app which easilyb detects wheteher the app is installed or open play store).
Thanks in advance for help..
Check if application is installed with packagename
Ask Question
Try this:
private boolean isPackageInstalled(String packagename, PackageManager packageManager) {
try {
packageManager.getPackageInfo(packagename, 0);
return true;
} catch (NameNotFoundException e) {
return false;
}
}
It attempts to fetch information about the package whose name you passed in. Failing that, if a NameNotFoundException was thrown, it means that no package with that name is installed, so we return false.
Note that we pass in a PackageManager instead of a Context, so that the method is slightly more flexibly usable and doesn't violate the law of Demeter. You can use the method without access to a Context instance, as long as you have a PackageManager instance.
public void someMethod() {
// ...
PackageManager pm = context.getPackageManager();
boolean isInstalled = isPackageInstalled("com.somepackage.name", pm);
// ...
}

Android: How can I tell if Samsung Apps market is installed on the device?

[edit: answer]
isInstalled("com.sec.android.app.samsungapps") is the correct packageName for determining installation of Samsung Apps.
AndroidManifest: There are no special permissions required.
[original post]
Trying to find out whether Samsung Apps is installed. Based on the method provided in this link.
I want to detect if:
isInstalled("com.sec.android.app.samsungapps");
Is this package name string correct for Samsung Apps?
Is there a security/permissions scenario where I might not be able to find out about the existence of other installed packages?
For reference, here is isInstalled():
private boolean isAppInstalled(String packageName) {
PackageManager pm = getPackageManager();
boolean installed = false;
try {
pm.getPackageInfo(packageName, PackageManager.GET_ACTIVITIES);
installed = true;
} catch (PackageManager.NameNotFoundException e) {
installed = false;
}
return installed;
}
Thanks.
There should be no reason why you shouldn't be able to check a package is installed, even system ones, however im unsure as to wether or not your samsung apps package name is correct but you can check what it is by using this https://play.google.com/store/apps/details?id=com...pkgnameviewer
1) Samsung Apps package name is "com.sec.android.app.samsungapps"
2) There are no restrictions on checking for package names using isInstalled()

Categories

Resources