My app has two versions Free and Paid in Google Play.
I want to add inappbillingv3 to the free version and remove the paid version from Google Play.
If users install the free version and purchase the item to upgrade to the PRO version, then can I know If they have already installed the paid version?
You can check if app is installed by using PackageManager's getApplicationInfo method
public abstract ApplicationInfo getApplicationInfo (String packageName, int flags)
Retrieve all of the information we know about a particular
package/application.
Throws PackageManager.NameNotFoundException if an application with the
given package name cannot be found on the system. Parameters
packageName The full name (i.e. com.google.apps.contacts) of an
application. flags Additional option flags. Use any combination of
GET_META_DATA, GET_SHARED_LIBRARY_FILES, GET_UNINSTALLED_PACKAGES to
modify the data returned. Returns
ApplicationInfo Returns ApplicationInfo object containing information about the package. If flag GET_UNINSTALLED_PACKAGES is set
and if the package is not found in the list of installed applications,
the application information is retrieved from the list of uninstalled
applications(which includes installed applications as well as
applications with data directory ie applications which had been
deleted with DONT_DELETE_DATA flag set).
Related
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!
I am getting list of packages using packagemanager with GET_UNINSTALLED_PACKAGES flag,
PackageManager pm = getPackageManager();
List<ApplicationInfo> packages = pm.getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES);
but since it returns: "information about all applications (even uninstalled ones) which have data directories." I am unable to get reliable list of previously uninstalled package including apps that didn't left a data directory behind.
Is there any way to achieve this?
Disclaimer : I didn't try this solution, but it may help (requires Android 5)
With android 5, there is this new API : UsageStatsManager with this method :
usageStatsManager.queryAndAggregateUsageStats(startTime,endTime)
returning an Map where keys are the package name (and values are usage statistics). Hopefully, this will include uninstalled apps (but I'm not sure !). Of course you won't get the AppInfo (only the package name)
Note also this important remark about required permissions:
NOTE: This API requires the permission android.permission.PACKAGE_USAGE_STATS, which is a system-level permission and will not be granted to third-party apps. However, declaring the permission implies intention to use the API and the user of the device can grant permission through the Settings application.
I am developing an Android application where I want people to buy a licence, and based on that licence I will need to push plugins to my application.
e.g. if the licence maps to 3 plugins (or premium features), I want to push only those 3 to the application at run time. Since it's not possible to change the APK like this AFAIK, and I don't want to include all the features in a single APK.
How can I maintain multiple versions of the app, like a premium app and free app without maintaining multiple apks?
Best Regards
Plugins are nothing but APKs without a launcher activity AFAIK. Just take the example of the Facebook. How does the application know whether you have their Pages Manager or Messenger installed ? I can only think of one way of achieving this so-called Plugin Based Architecture i.e. Create multiple APKs, one for each plugin, acting as a stand-alone application. And check if the package exists at Runtime with the Main APK.
public boolean isPackageExisted(String targetPackage){
List<ApplicationInfo> packages;
PackageManager pm;
pm = getPackageManager();
packages = pm.getInstalledApplications(0);
for (ApplicationInfo packageInfo : packages) {
if(packageInfo.packageName.equals(targetPackage)) return true;
}
return false;
}
If not downloaded and install the package if it meets your criteria.
How do I make sure that only my "master" apk is able to call the functions in the plugin apk?
You can do that by adding this to your Manifest file
android:protectionLevel="signature".
You can read about it more here.
Hope this helps.. :)
I know in Android, I can invoke getInstalledPackages(0) of PackageManager API to get all the installed apps on device.
I am wondering is there a way or workaround to get the publisher's name of installed app by using Android SDK (i.e. no 3rd party library)??
The package that contains related classes, especially ApplicationInfo, there is no public interface for this (http://developer.android.com/reference/android/content/pm/package-summary.html). So i belive there's no way to do that.
I think there is no direct way to do that. Because that information is not available anywhere in the manifest or source code.
As a workaround, you can get the process name/package name, and find publishers name from google play store:
Pseudo code:
List<ApplicationInfo> appInfos = context.getPackageManager().getInstalledApplications(0);
for (ApplicationInfo appInfo : appInfos) {
String processName = appInfo.processName; // Example: com.google.android.youtube
String url = "https://play.google.com/store/apps/details?id=" + processName;
// Fetch publisher name from web here
...
}
I think, there is no android API to get the publisher's name of the application. You can get the publisher's and more information from the play store using this 3rd party API.
https://api.appmonsta.com/v1/stores/android/details/your-package-name.json?country=us
Replace the 'your-package-name' from API to the application package name.
First, you have to register with api.appmonsta.com to run this API.
I'm developing an App that is distributed in two versions: free with ads and payed with no ads. A part from the presence of ads, the apps are completely identical.
Generally users are thought to get the free version and then - if they like - upgrade to the commercial version.
When I upload the app to google play, I must create a completely new app, with a new unique id. In other words, these two versions of the same app are actually two completely different projects, and, as I see, there's no way to avoid this.
This makes sense, as soon as I have to monitor which app provides me which income.
BUT - now comes the problem - when a user decides to upgrade from the free to the commercial version, I would like him to keep all his local data. Obviously this does not happen, as soon as the two applications have different name.
Is there an easy solution for this problem?
Thank you.
How to share data between free and paid apps when the user upgrades from the the free to the paid version
This is a very common problem fraught with all sorts of issues, including the following:
When the user installs AND RUNS the paid app, all user data should be
copied from the free app.
If the user tries to use the free app after he has completed the
upgrade to paid, he should be automatically redirected to the paid
app.
When the user deletes the paid app, then the free app should be permitted to continue working as previously.
The easiest solution is to maintain all data that must be shared in a database instead of user preferences. Then, the database file can be literally copied from the free to the paid application when the paid app is run for the first time.
I have found this to work better than Content Providers for me because of all the special use case conditions regarding only one or the other or both apps being installed at any one time.
In order for this system to work, several key tools have to be in place:
The apps have to be able to detect if each other are installed at
runtime.
The apps have to know where their counterparts save their database
file.
Several flags have to be saved in the database file to indicate what
has happened.
How to determine if the other app is installed:
final String packageName = "com.company.other-app-name";
android.content.pm.PackageManager pm = getPackageManager();
PackageInfo info = pm.getPackageInfo(packageName, 0);
If info==null or a NameNotFoundException is thrown, then the app is not installed.
How to copy the database file:
Your database files are stored like this:
paidDb = "/data/data/<paid-app-package-name>/databases/<db-name>.db"
freeDb = "/data/data/<free-app-package-name>/databases/<db-name>.db"
Your copy function should open FileInputStream and FileOutputStream objects on these files and copy them by any number of standard methods such as this:
while ((length = fis.read(buffer))>0) {
fos.write(buffer, 0, length);
}
This should provide all the tools you need in order to allow the paid app to determine if the free app is installed, and if it is installed copy the database and continue from there. The free app should check to see if the paid app is installed. If so, either quit with a friendly warning or redirect to the paid app, like this:
android.content.pm.PackageManager pm = getPackageManager();
final Intent intent = pm.getLaunchIntentForPackage(packageName);
startActivity( intent );
finish();
Optional Delete the Free App:
After the paid app detects the free app and copies the database, you can optionally ask the user to delete the free app, like this:
Uri uri = Uri.parse("package:<free-app-package-name>");
Intent intent = new Intent(Intent.ACTION_DELETE, uri);
startActivityForResult(intent, REQUEST_CODE_UNINSTALL_FREE_APP);
Note: You cannot guarantee that the user will actually uninstall the free app as requested. The value REQUEST_CODE_UNINSTALL_FREE_APP is used so that when you return from the uninstaller in onActivityResult() of the paid app, you can check to see if the user completed the delete. Then, if the uninstall didn't happen you can provide the usual 'Are you sure?' or 'Try again?' dialogs or even get all draconian on him (not recommended) and force him to finish the uninstall before allowing him to continue using the new paid app.
Further Consideration:
All of your shared code should be in an Android LIbrary Project and
each of the apps should be lightweight wrapper projects using the
shared library. All three projects will be in a single Eclipse
workspace.
Consider using Android License Verification Library (LVL) for
the paid app project (you will not need LVL for the Library Project
or for the free app).
Also consider scrapping all of these ideas, making just one single
application, and using In-app Billing to upgrade from free to paid.
This is way beyond the scope of this question.