53

I have an Android library that uploads data to a test server and production server. I'd like developers using this library to use the test server when developing, and production server when the app is downloaded from Android Market.

Is this possible for an app to tell where it came from (Market or non-Market?) I would imagine one could detect the presence of the signed JAR file.

sehugg
  • 3,615
  • 5
  • 43
  • 60
  • Do you want to know if the app is published, or from where the end user downloaded the app? Like, either the user loaded the app from the market, so market apps use the production server, or the app was published so all copies of that app become production apps. – Grant Jun 12 '09 at 14:07
  • Grant, the difference I'm looking for really is developer-time vs production-time, so I do want developer copies to remain on the test server. I just want any apps which were downloaded "in the wild" to use the production server. – sehugg Jun 12 '09 at 14:31
  • Create another application that doesn't do anything, then test for the presence of that to indicate a debug build? Install app on development phones. – OJW Oct 07 '10 at 17:13

5 Answers5

38

Yes, you could use the signature for that. If you use a debug key to sign your app during development and a release key when uploading your app to the market you can check for the signature that the app was signed with and based on that use test or production server. Here is a small code piece to read the signature of your app:

    try {
        PackageManager manager = context.getPackageManager(); 
        PackageInfo appInfo = manager.getPackageInfo(
            YOUR_PACKAGE_NAME, PackageManager.GET_SIGNATURES);

        // Now test if the first signature equals your debug key.
        boolean shouldUseTestServer = 
            appInfo.signatures[0].toCharsString().equals(YOUR_DEBUG_KEY);

    } catch (NameNotFoundException e) {
        // Expected exception that occurs if the package is not present.
    }

YOUR_PACKAGE_NAME must be something like 'com.wsl.CardioTrainer'. It must be the package name you used in your AndroidManifest.xml. Good Luck

mark

maximon
  • 396
  • 2
  • 4
  • 1
    Is it a good idea to hard code YOUR_RELEASE_KEY? Will reverse engineering reveal this? – Thushan Jul 16 '09 at 19:07
  • 4
    That might solve the problem but i would definitely NOT put my full private key into my code if i was you. Maybe you could get away with just using a 20 char subset of the key or something? – Declan Shanaghy Nov 06 '09 at 18:59
  • 5
    I think using some kind of hash on your key and hard coding that in, then hashing the key stored in the package info, then checking that would stop anyone from seeing the real key if it was reverse engineered. – Austyn Mahoney Jan 09 '10 at 00:22
  • 8
    Wouldn't you get around the security exposure if you tested for the debug key rather than the release key? – Rob Kent Mar 01 '10 at 11:03
  • You dont want to compare the signature to your debug key. Instead, you should compare the X500 principal of the signature to your debug key (or release key, or any other key). See http://stackoverflow.com/a/6203440/596599 – PacificSky May 08 '12 at 16:44
  • Regarding the signature: that is not your private key; it is the public key that *corresponds* to your private key. So using (and testing) the release key's signature (as opposed to the private key) should be OK. An easy way to obtain this value is just to log it from a signed copy of your APK. – Carl Dec 07 '12 at 03:38
  • Check out its installation source: http://stackoverflow.com/questions/3178043/is-there-a-way-to-detect-if-app-was-installed-with-market-or-not – Jared Burrows Jul 20 '14 at 05:34
  • We can store key in config file in assets folder – Hitesh Sahu Jun 18 '16 at 20:36
10

Starting with API 5, you can use PackageManager.getInstallerPackageName(String). From the documentation:

Retrieve the package name of the application that installed a package. This identifies which market the package came from.

To get the package of the Android Market, this post may help.

Community
  • 1
  • 1
Phil
  • 35,852
  • 23
  • 123
  • 164
3

From what I can tell there is nothing that the Market Application does to "flag" an application to say that it was downloaded from the market.

I have seen this issue approached in a different manner by another Android library. The AdMob Android SDK is free to download and use as described on their wiki. This library serves ads, so they have the same desire to be able to determine if the application that is currently running is being tested by the developer or if it is being used "in the wild". Their approach was to require that the developer set a "testing" attribute in the XML or to call their libraries "setTesting(boolean)" function to let the library know which ads to serve. This is obviously more of a manual approach that relies on the developer to change one line of code or XML before publishing.

snctln
  • 12,175
  • 6
  • 45
  • 42
  • 1
    Yeah, that's one approach .. the problem is that it's hard to remember to change it back when you publish :) I was looking for a way that would be automatic. Oh well. – sehugg Jun 13 '09 at 04:09
  • 1
    You could customize the `build.xml` Ant build script to swap out variables between release vs. debug building. I've done it in such a way that a configuration class (for Facebook and Twitter keys) and a resource file (for Google Maps) are swapped automatically. – Paul Lammertsma Nov 20 '11 at 19:48
1

You could default your configuration to the production environment and use a custom Instrumentation that sets the configuration to testing environment. Intrumentation should be removed before publishing to the android market.

Josef Pfleger
  • 74,165
  • 16
  • 97
  • 99
0

Perhaps you could add a setting to your app for "developer mode".

Another possibility, have it look for a special file or configuration file on the SD card, and key off of that.

davenpcj
  • 12,508
  • 5
  • 40
  • 37