I have read the google provided In-app billing sample for billing library v3, link is as follow:
https://github.com/android/play-billing-samples/tree/main/ClassyTaxiJava
In the sample, it use public class Constants
public static final String BASIC_SKU = "basic_subscription";
public static final String PREMIUM_SKU = "premium_subscription";
for the whole app.
I am wondering if a user can decompile or unpack the apk and change the product string or exchange the SKU string so that there may happen that the bought item A but receive bought item B function.
So I want to use getString(R.string.SKU_itemA) and getString(R.string.SKU_itemB) to try to make the text less explicit in code searching. Will I do this be safer to avoid user change?
If you have signature verification in your app, the only way to modify your app is to somehow defeat the signature verification. I suggest that you verify your app's signature, and it will protect you from any issues related to app cloning or app modification.
It does not make sense to just protect the SKU somehow: if the users are able to modify your app, they are also able to remove the check if the subscription has been purchased.
I recently came across this app Purchase Apps, which is somehow able to retrieve apps I've paid for in google play after I signed in using my google account.
I'm trying to find out how it is being done as I want to build a similar app, but for the free apps which were downloaded.
However, I can't find which OAuth API Scope was used for retrieving that information, even after going through the entire list of APIs.
EDIT:
I'm putting a new bounty on this question, as suggested by a similar question I've asked about here, and because here and there I don't see a real answer about how to do it, and what can be done with it.
I'd like to refine the questions into multiple pieces:
What is the API that can be used to get information of purchased apps? Where can I read about it? Please show a full, working example of how to do it.
Can it do more ? Maybe perform search? Maybe show free apps that were installed? Maybe the time they were installed and uninstalled? And the categories of those apps?
Are there any special requirements for using this API ?
EDIT: I'm putting a max bounty on this, because no matter how much I've read and tried, I still failed to make a POC that can query the apps from the Play Store that the user has ever downloaded (name, package name, date installed and/or removed, icon URL, price...), including both paid and free apps.
If anyone finds a working sample, show how it's done, and also show how you've found about it (documentation or anything that has led you to the solution). I can't find it anywhere, and the current solutions here are too vague for me to start from.
Issue is resolved. The exploit has been closed.
We will be closing this bug due to being logged in a Preview version of Android. If the issue is still relevant and reproducible in the latest public release (Android Q), please capture a bugreport and log the bug in https://source.android.com/setup/contribute/report-bugs. If a reply is not received within the next 14 days, this issue will be closed. Thank you for your understanding.
Latest update:
This is a bug and Google will address it in the next update.
We've deferred this issue for consideration in a future release. Thank
you for your time to make Android better
This answer has turned into a conglomeration of ideas and been edited to include information from discussion in the comments.
The androidmarket api, would be a customised api written by the developer. It's not available to the public.
To address your concerns in the comments. The developer would have utilised the current apis available through Android Developer and Google to create a project that manages all of these.
As for accessing Full Account Access, I'm not sure exactly how these developers have achieved this.
I'd recommend using the AccountManager, which is part of android.accounts, has access to credentials and a method getUserData. The account manager has access to passwords and is capable of creating and deleting accounts. This, possibly used with Content Provider
See Udinic/SyncAdapter Authentication.
To reply to your comment:
This blog should help you to get started. Write your own Android Authenticator.
How these apps actually work, I cannot tell you. They may also have different implementations (unless they're a collaborative effort behind the scenes, they most certainly will be different).
One guess. Firstly use GoogleSignInAccount with com.google.android.gms.auth.api.signin.
There a definition for scope, to determine the extent of the permissions the app is granted.
Using requestScopes(), the
public static final String PROFILE
.../ It lets your web app access over-the-air Android app installs.
For example:
GoogleSignInOptions gso =
new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail().
.requestScopes(new Scope("https://www.googleapis.com/auth/contacts.readonly"))
.build();
If full access can be gained a list of all apps used by the account holder can be found and compared to what's on the device.
Package Manager will retrieve a list of all apps currently installed on the device.
PackageInfo provides the details about the app.
INSTALL_REASON_USER will also filter out apps that have been actively installed by the user.
You might want to look at com.google.firebase.appindexing and Log User Actions. Different actions can be tracked.
The users account history is found at https://myactivity.google.com/myactivity.
A helpful link is the OAuth 2.0 Playground.
This github repo node-google-play, using node, is current and will call Google Play APIs. As did the archive that was used as an "unofficial" api, android-market-api, to query the market place.
App 1
The app claims to use the following permissions:
Version 2.1.8 can access:
$ In-app purchases
Other
receive data from Internet
view network connections
full network access
use accounts on the device
prevent device from sleeping
read Google service configuration
Noteworthy, the app doesn't set any permissions when there was a basic, install. I was unable to use any of the features, as I have no paid apps. So for the initial search - there were no permissions needed, which would indicate the app didn't have access to my account.
I checked the permissions - there were none set. So the only thing required was to accept the pop up, as displayed in your question.
App 2
The other app you refer to that does the same thing is more upfront about what is being accessed.
My Paid Apps
SECURITY/PRIVACY NOTICE
The first time you run this app, it will ask for full permission to your Google account. This is unfortunately
the only way to access the required information. No personal
information is stored, no information about your apps is shared with
the developer of this app, nor shared with any third parties.
Everything is kept on your phone only.
I've gone into detail over these apps in this blog post, which was for a university capstone project (no monetary gain). I'm inclined to think this is an exploit in the API and not status by design by Google, as there are no API calls to fetch purchases of apps other than the developer's own app. I hypothesize it's a zero day exploit, in which case there's no legitimate way to access this information.
In case of one of these applications (My Paid Apps), after checking the network traffic it is pretty obvious that it does use the Store's Account page to retrieve the list of paid applications.
Now, the mechanism it uses is the same mechanism that Google Chrome currently, and Pokemon GO supposedly at a point in time used.
In a nutshell, steps to do so are as follow:
Login:
What the mentioned program do for the first step is to log the user in and get access to the user's access token. To do so, it uses the android.accounts.AccountManager.getAuthToken() method. (See more: AccountManager)
However, as for the token scope, oauth2:https://www.google.com/accounts/OAuthLogin is requested.
It might be important to note that based on the OAth2 documentation from Google, this scope is not valid; however, it seems like a valid scope for Google OAuth v1.
Converting the newly retrieved access token to a ubertoken:
Now, what actually ubertoken supposed to do, is unknown and there is no official documentation about it. However, it was seen in the wild to be used by chrome browser to login users.
This is done by requesting the https://accounts.google.com/OAuthLogin?source=ChromiumBrowser&issueuberauth=1 page.
Converting ubertoken to website session:
Later on, using the newly created ubertoken it is possible to get a website session using the https://accounts.google.com/MergeSession API endpoint. After this step, the application is essentially capable of loading all personal pages that you can open using your browser while logged in; except some special pages including Payment settings.
Retrieving the list of paid applications:
Requesting and parsing the https://play.google.com/store/account page.
Following is the application's traffic as captured by 'Packet Capture':
As it is clearly visible in the picture, the end result is identical to what I get when I normally open the store's account page on my PC with Chrome Desktop:
Side note:
It seems none of these endpoints are documented as they are primarily used by Google's own programs and should be considered internal. Therefore I strongly recommend not using them in any program or code that you expect to run for a long time or in a production environment.
Also, there is bad news here for you too, it seems that the Google Play's account page only lists paid applications or special free apps (more especially OEM apps). I will try to find some time and dig deeper into the other application.
Interesting articles:
Pokemon tokens
Exploiting Google Chrome's OAuth2 Tokens
If you have root access, You can access /data/data/com.android.vending/databases/library.db
OnePlus3T:/data/data/com.android.vending/databases
-rw-rw---- 1 u0_a2 u0_a2 229376 2018-12-26 18:01 library.db
This database has all information, which app you have downloaded, which apps you have purchased, and even in which app you have done IAP.
Check ownership table, It has all information.
ownership (account STRING, library_id STRING, backend INTEGER, doc_id STRING, doc_type INTEGER, offer_type INTEGER, document_hash INTEGER, subs_valid_until_time INTEGER, app_certificate_hash STRING, app_refund_pre_delivery_endtime_ms INTEGER, app_refund_post_delivery_window_ms INTEGER, subs_auto_renewing INTEGER, subs_initiation_time INTEGER, subs_trial_until_time INTEGER, inapp_purchase_data STRING, inapp_signature STRING, preordered INTEGER, owned_via_license INTEGER, shared_by_me INTEGER, sharer_gaia_id TEXT, shareability INTEGER, purchase_time INTEGER, PRIMARY KEY (account, library_id, backend, doc_id, doc_type, offer_type))
Dealing with unofficial Google APIs is incredibly complicated territory. It's going to be possible to get this to work, but that's all I'll say. Proceed at your own risk.
The first thing you're going to need to do is get a Google Play auth token. This can be done several ways, but here's how they do it in Purchased Apps:
public static String getAuthToken(Activity activity, String userEmail) {
AccountManager accountManager = AccountManager.get(activity);
Account userAccount = new Account(userEmail, "com.google");
Bundle options = new Bundle();
options.putBoolean("suppressProgressScreen", true);
String token;
try {
Bundle result = accountManager
.getAuthToken(userAccount, "androidmarket", options, activity, null, null)
.getResult();
token = result.getString("authtoken");
} catch (OperationCanceledException e) {
Log.d(TAG, "Login canceled by user");
return null;
} catch (IOException | AuthenticatorException e) {
Log.e(TAG, "Login failed", e);
return null;
}
return token;
}
A few things to note here:
The above code must be run asynchronously. I recommend RxJava, but an AsyncTask will work.
You must supply a email for the account you want to use. I'll leave the details up to you but this is fairly easy using AccountManager.
After you have an auth token, you can now access any Google Play Store endpoint. The main one used by Purchased Apps is https://android.clients.google.com/fdfe/purchaseHistory. Another one you might be interested in is https://android.clients.google.com/fdfe/details?doc=(package name) (from APKfetch code). Here's a page with some more and some analysis. If you make a request to these APIs, you'll need to supply several headers:
Authorization - "GoogleLogin auth=(your auth token)"
User-Agent - "Android-Finsky/6.4.12.C-all%20%5B0%5D%202744941 (api=3,versionCode=80641200,sdk=" + VERSION.SDK_INT + ",isWideScreen=0)";
X-DFE-Device-Id - your device's Google Services Framework ID, obtained from AdvertisingIdClient.
X-DFE-Client-Id - "am-android-google"
Accept-Language - The device's language code, eg "en".
Now, you need to parse the response. Here's where things get tricky. These APIs returns a message encoded as a Protobuf, so it's essentially just binary data unless you have a schema (which of course, only Google has). One way to go about this in theory is to decompile the Google Play Store app and reuse their generated protobuf models with a tool like JADX.
Unfortunately, I've tried this and it doesn't really work. Protobuf model classes are just too complex for a standard decompiler. What you can use is a tool called PBTK. You'll ideally want to run this on the Google Play Store 6.1.12 APK, since that's the last version before they started using ProGuard. Do note that this program has two errors in its script that need to be fixed before running it: changing 'extracto' to 'extractor' in gui.py and removing the assertion statement on line 500 of jar_extract.py.
Now, that should output all of the response classes as .proto files. Create a folder under src/main called proto and drag the entire generated 'com' directory to it. You can delete everything that's not under com/google/android/finsky/protos. Follow instructions online to setup Gradle with the Protobuf Lite plugin.
When you want to parse a response, you can use the ResponseWrapper class, since they all appear to be contained under that.
That's about as far as I can take you. There's a good chance I got some part of this wrong; JADX is your best friend here, because the best way to figure out what an app is doing is by looking at its code. Hope this helps and happy developing!
you can get the package name of all installed apps on device and then get the information of every installed package that you find in the device from google play without any need to get to user account. there is some third party or unofficial apis to get google play apps details as json by getting the app package name. for example: https://42matters.com/
then use the received information for every package to find free ones.
i have two resources for you to consider, but first, in a word, no. there is no api from GOOGLE to let you do what you want, as these metrics arent stored in the phone, they are on the google play store servors, and google has no OFFICIAL api for the play store. you can however glean some info from these two sites:
https://www.quora.com/Is-there-an-API-for-the-Google-Play-Storeenter link description here
https://android.stackexchange.com/questions/162146/how-to-see-all-the-apps-i-have-downloaded-from-google-play-store
and this is enough to see how to accomplish this.
first, a list of what apps have been downloaded by an account is only referencable by the account. and this can be done through the play store. since your app will be installed on that users phone, this dosnt matter... you're in.
second, you will need a 3rd party API built for the GOOGLE PLAY STORE, there are some out there, check the first link.
using the api of your choice, you will send a get request, to the play store, and in return you should receive in most cases a json object to deserialize.
deserialize the object, and you will have your list. which list you get will depend on the endpoint you use, but that should be explained by/in the API itself.
good luck!
What we are dealing with
We have this app which we distribute to our clients in an offline fashion (i.e. not uploaded to Play store). The app flavour distributed to each client is almost identical with a bit of tweak here and there. All our clients share this app to their employees for usage. Basically this is an Enterprise App.
What's the problem
Recently one of our client started using a MDM (Mobility Device management) tool which blocks apps which are not downloaded from Google play. As obviously we got a request from our client to see if we can upload this app on Google play or not.
Important thing here is that we have over 100 clients and the package name of the app provided to each client is actually the same. So it's the same app with a bit of tweak here and there. If we go down the road of publishing the app to the play store, we might end up in a mayhem (we don't wanna upload 100 different apps to the play store - i.e. one for each client). We are doing some optimisation from our end so that multiple clients can use the same app (but we can't make all 100+ clients use the same app.).
What am I looking at ?
I started looking at Android For Work (AFW), Google private apps , Managed Google play and still digesting the stuffs. But to me it looked like just a secure way for enterprises to deploy/publish apps which can be downloaded only on specific devices and under a certain profile (which keeps things separate from user's personal apps and data in case they use the same phone for personal and work purpose).
What solution i am looking for ?
To privately deploy an app (host it with Google or privately host
but listed with Google play in both cases) and let my clients share
this app with their employee.
Each private app for each client should be on its own little
private island. I want to distribute the app with the same package
name to all my clients (From what I have read so far, this might not
be possible with Google play. But I am hoping somebody can point out
facts if I am missing something).
This is my solution:
Creating run-time dynamic app that get data and configs from back-end and render its views and data with its own Client Id.
You can create single app and upload to google play, but you should manage your clients by clientId that makes every app acts separated. This clientId is unique and generated per your clients. This solution have two sides. Android side and server side.
1 - Android side: Our app should have a baseUrl like this in Constants:
baseUrl = "http://yourCorporation.com/{clienId}/api/"
And then all the services of All clients use the same url. clientId is the key point. The difference of you client app is clientId. For generating url of api-call you should do something like this:
Constant.ClientId = scannedQRCode;
url = baseUrl.replace("{client_id}",Contant.ClientId) + apiUrl ;
You must create QR code per your clients that should scanned in app first run. It is good to send QR code after registration to his/her (client of your Clients) email. This QR code have clientId. Therefor every clients have their own services and really works as separated islands, even if you want to change server address, you can put all baseUrl in QR code but this is not suggested, because you have to create server per clients and this is headache.
You can even handle config and UI elements of you app with calling a config api that returns a customConfigDto as json like this:
public class CustomConfigDto {
String colorPrimary ;
String colroPrimaryDark ;
String colorAccent ;
int tabCounts;
//and more...
public String getColorPrimary() {
return colorPrimary;
}
public void setColorPrimary(String colorPrimary) {
this.colorPrimary = colorPrimary;
}
public String getColroPrimaryDark() {
return colroPrimaryDark;
}
public void setColroPrimaryDark(String colroPrimaryDark) {
this.colroPrimaryDark = colroPrimaryDark;
}
public String getColorAccent() {
return colorAccent;
}
public void setColorAccent(String colorAccent) {
this.colorAccent = colorAccent;
}
public int getTabCounts() {
return tabCounts;
}
public void setTabCounts(int tabCounts) {
this.tabCounts = tabCounts;
}
}
And render your views by this configurations. All of this works separated per app by their clientId.
I prefer QR code because it is very handy and classy and fit in your case, however you can enter this clientId with many other ways. This is one of best free and simple QR code generating service, and this is one of best QR-code scanner library for android.
2 - Server Side: You have to handle step1 in server-side and it is very easy. You can have entity calls Client that all other entities have it. Because you should keep all of your data in one place but separated by your clients. You can also map APIs like this in Spring:
#RequestMapping(value = "http://yourCorporation.com/{clienId}/api/customers", method = RequestMethod.GET)
Customers getCustomers(#PathVariable("clienId") Long clientId) {
return customerService.findCustomerByClientId(clientId);
}
Based on what you've said, this sounds more like you can solve this with configuration management than sending each client completely separate APKs.
Google has a private channel, but based on the documentation it seems much more oriented towards having a single membership list (i.e. once you're granted access you have access to the entire private channel) rather than highly customized access (i.e. certain people have access to certain items in the channel).
An alternative that I suggest: have all clients download the same APK. Give each of them a client-specific "activation code" for your app. When the app starts for the first time, it calls a web service and passes it its activation code; on the server side, you use the Activation Code to identify the client and then return data on the correct configuration to the client. Then you can distribute the same APK to everyone on your private channel and configure it remotely once it's installed.
A major advantage of this scheme is that you can have multiple configurations for an organization. Just give the client a choice of several activation codes, each of which will give them a certain configuration. For example, if you have an app that's used by both dock workers and janitors (and I'm just throwing out an example here), you could give the dock workers one activation code and janitors a second activation code and you can then easily give them different configurations.
Google Play now allows a developer to publish an app privately to up to 20 Managed Play organizations (or enterprises). To do so (instructions copied from the help center):
Sign in to the Google Play Console.
Go to Pricing & Distribution > User programs > Managed Google Play.
Check the Turn on advanced managed Google Play features box.
Check the Privately target this app to a list of organizations box.
Click Choose Organizations.
For each organization that you want to publish the app to, enter the Organization ID and a description (or name) and click Add. You can enter up to 20 organizations per app.
The good, long solution:
don't use the same package name for different apps. Create a multimodule project, set one module for the core, shared stuff, and add a module for each client where you can tweak what you need and configurate the package name dynamically based on build type. That way you can use the same package name for your CI server and everything else and have another package name when releasing the app.
The short workaround that may work:
Publish the app as a closed google play beta, and send invitations only to this client. That way he can distribute the app to his employees through play store and the other clients won't notice I can't assure it will work not knowing which MDM tool you are facing, but since beta channel apps don't require unknow origins permissions, you should be fine.
If you want the same package name, you'll have to do something like what EJoshuaS suggested: manage the different configurations inside of one app version. You won't be able to have more than one app with the same package deployed on Google Play.
If you're open to having different packages, you could just change the package name in the Android Manifest for each one and release as a different app. You would need to change the package everywhere you import the R file and you would need to make sure that all class references in your Manifest include the entire class path (<activity android:name="[full.package].MainActivity"> rather than <activity android:name=".MainActivity">). This gets pretty confusing and is terrible in terms of configuration management, so it's not really a great solution in general, but it might work for you.
I started looking at Android For Work (AFW), Google private apps , Managed Google play and still digesting the stuffs.
This would probably be a good fit for AFW.
But to me it looked like just a secure way for enterprises to deploy/publish apps which can be downloaded only on specific devices and under a certain profile
That's what an MDM does, yes, but there's more to it. With Android for Work you also have Managed Configurations which let you pass in a configuration for the app. This can be used to change backend urls, etc.
It for sure supports your second requirement, but I know too little to be certain about the first. While you can privately host and rollout an app on Google Play for Work, I don't know about distributing it privately to multiple clients.
The obvious benefit of using this Google API is that you don't have to build anything yourself. Also most MDMs support those Android for Work APIs, so that a domain admin can buy the app in bulk and distribute them to the employees. Have a look at the AppConfig Community which shows MDM Providers that incorporated those APIs and best practices.
Whatever you decide, you should definitely have a good look at Android for Work as what you are describing is exactly what it is intended for. The initial setup is a pain and there is way too little information about how it all works and plays together, but spending a few days trying to figure it out might be better than just building your own managed solution which you then will have to maintain too.
SITUATION
I have a set of functionalities in my app which changes based on the store it is installed from. E.g. I want to have a more restricted set of advertisements displayed for family audiences and children to be eligible for the Google Play for Education category. In other stores i still want to restrict but don't want to be as stringent as I will be in filtering out the ads.
General observation at my end is that if I opt-in for "Google Play for Education" category it takes a few more hours to get published because of the following (as stated on the developer console):
Checking this box submits this app for inclusion in the "educator
recommended" section of Google Play for Education. The final decision
on which apps to recommend is made by a 3rd party network of teachers.
If your app is selected, we will notify you by e-mail. If not, your
app will still be searchable in Google Play for Education.
Now before the app gets published in this category the network of teachers, I assume, download and test/verify if the guidelines are met and there are no violations.
PROBLEM
To differentiate between the store installed from I'm obviously using this:
PackageManager packageManager = context.getPackageManager();
String installer = packageManager.getInstallerPackageName(packageName);
if (installer == null) installer = ""; //to avoid NPE
if (installer.equals("com.android.vending")) {
//It is installed from Google Play store
//PROBLEM: THIS DOES NOT SEEM TO BE THE PACKAGE NAME RETURNED
//WHEN GOOGLE PLAY REVIEWERS/TESTERS ARE USING THE APP
}
else ...
....
....
//similarly handling other stores here
....
....
....
//After that also checking by installed app stores
....
....
What is happening: After being published things app properly identifies that it is downloaded from play store i.e. it gets com.android.vending as the installerPackageName. But, when it is being reviewed or tested by the network of teachers it appears to be getting a different installerPackageName. This is causing the app to think it has been downloaded from an app store other than Google Play Store. And because of this my app is rejected from the Education category. I need to know this installer package name to handle the scenario correctly.
How do i know this: I have a dedicated ad unit id to use when the detected app store is Google Play and all requests post successful publication (i.e. from the regular play store users) come to this google dedicated ad unit id. But, in the short span of time after submitting the app/update and before the app or and update is published, a few requests come to the non-google ad unit ids, causing the app to fail adherence to the guidelines to be eligible for "Google Play for Education" category. Because, the level of ad filtering in the non-google ad unit ids is slightly less. Hence the teachers evaluating/testing the app see some ads that they think are not as per guidelines and reject it.
Also, here is an article to support the fact that the app gets reviewed manually as well as by automated script before it is actually published to the store.
Current fix or limitation: I've disabled all other ad networks and have to use only admob. The setting of filters even at the strictest level in other ad networks doesn't seem to filter all ads that Google reviewers think are not suitable for children and family audiences. When using only admob the process is smooth and I always qualify.
What I'm looking for to overcome this problem: If i get to know the installerPackageName that is returned when the app is installed from where ever the reviewing network of teachers install the app from, I can handle that case exactly as i handle when i get com.android.vending and everything will be just fine.
I could not find any documentation or reference to obtain this information.
Also, if there is any other way i can identify it the app is in pending publication stage, I force all requests to go to the google ad unit id.
ASSUMPTION: There is a separate installer app for the reviewers and testers (automated/manual what ever it may be in the background) whose installerPackageName is NOT com.android.vending. If there is some Google guy around and can help confirm this (if allowed by Google), do comment. :-)
Other possibilities which i do not want to go with
Disable all other networks manually while the app is in pending publication phase and re-enable them once published. But, I don't want to do this because this would be like bluffing google and I don't want to go that way. I want my app logic to take care of it so that the same thing that is reviewed is let out in market.
I permanently stick with only admob. But this would be foolish as there are no such restrictions in other stores that I'm publishing my apps to and I will terribly lose on fill rate.
I there anyone who has had this issue before OR knows the installerPackageName for the review's download place OR knows how to determine if the app is currently in 'pending publication` state on playstore?
I can also possibly filter all by packagenames starting with com.android or com.google, but I want to keep that as last option. Also, would like to know if the installerPackage name is not set at all in case of those users. In that case I'll need to look at a completely different situation to handle the situation.
I find one thing that can help you in this case. It's analytics. Just create your custom event eg. INSTALLER_STRING in some of analytics systems and log that event when appropriate. Here is the example of event logging in Fabric Answers.
public static final String EVENT_OPEN_TOP_TRENDS = "EVENT_OPEN_TOP_TRENDS";
public static final String TOP_TRENDS_TYPE = "TOP_TRENDS_TYPE";
public static final String TYPE_TOP_TRENDS_IMAGES = "TYPE_TOP_TRENDS_IMAGES";
public static void logEvent(String eventId, String attributeName, String name) {
Answers.getInstance().logCustom(new CustomEvent(eventId).putCustomAttribute(attributeName, name));
}
logEvent(EVENT_OPEN_TOP_TRENDS, TOP_TRENDS_TYPE, TYPE_TOP_TRENDS_IMAGES);
Later on, you can see what are the sources your app was installer from on fabric website.
Check which results you will show using this log for all app you use do detect installer package name:
final PackageManager pm = getPackageManager();
//get a list of installed apps.
List<ApplicationInfo> packages = pm.getInstalledApplications(PackageManager.GET_META_DATA);
for (ApplicationInfo packageInfo : packages) {
String is = pm.getInstallerPackageName(packageInfo.packageName);//getPackageName());
Log.d(TAG, (packageInfo.packageName==null?"":packageInfo.packageName) + " : " + (is==null?"":is));
}
You will see the full list of installed apps & package sources, or log this data in your way your want.
EDIT
#Virus, i just want to give you a simple idea. if you want to know package installer name, you can just grab this data when you app is launched and send it to your own server using simple http GET request in order to detect the installer name. Republish you apo with this simple frabber. I think this the one solution.
I integrated inappPurchase code to my android application.its working fine but i need handle
purchase data because if user buy my products after he uninstalled,after some days he again installed in the senario no need to purchase again.For this purpose how to handle data
Most of the data that you place is removed when user Uninstalls the file, so basically create a file or folder with details of his accounts in an encrypted format either on the phone or on the SD card (preferably use Phone storage)
but again if user does a factory reset on his phone then all information will be lost
So
Either create a web service and pass all the account information , you can use the Phones IMEI number to act as a unique ID or use login info for the user so you can identify him or her even if he or she changes her phone
or use Google's GCM to target individual customers
EDIT
Ya restoring is there Android In-app billing RESTORE_TRANSACTION usage
but what if your not using in built, but are using paypal SDK or some other methods then we have such the above mentioned options
You should maintain all the purchase data on the server side for each device.
You have to use RestoreTransactions function for getting the purchase data of the particular user.
mBillingService.restoreTransactions();
And in ResponseHandler.java file you will get all details in
public static void purchaseResponse(final Context context,
final PurchaseState purchaseState, final String productId,
final String orderId, final long purchaseTime,
final String developerPayload, final String purchaseToken) {
}
Items that are managed per user account can be purchased only once per user account. When an item is managed per user account, Google Play permanently stores the transaction information for each item on a per-user basis. This enables you to query Google Play with the RESTORE_TRANSACTIONS request and restore the state of the items a specific user has purchased.
Refer to this link:
http://developer.android.com/guide/google/play/billing/billing_admin.html
And read the section 'Choosing a Purchase Type'.