26

So one of my applications was rejected from the Amazon app store today. The reason was because inside my app, I linked to the paid version of the app on the Android market. Disappointing, but whatever, I guess everyone wants their cut...

So now I'm left having to modify the application to change the Android market link to an Amazon app store link. Not really a big deal except for now if I do that I'm left with a discrepancy when I want to upload a newer version back to the Android market. After all, it would be rather dumb to link someone to the Amazon app store if they purchase the app from the Android market.

Now we all know that it is a pain supporting/managing multiple versions of the same app. Consequently my question becomes how can I link to both at the same time? Is there a way to tell where an app was downloaded from so I can code both links into the app and thus point the user automatically to one or the other? Secondly, is it against the Amazon TOS to give the user a choice (say I pop up a dialog instead and ask the user where to download from)?

Thanks all.

Edit: Direct from Amazon customer service "Re: Link to both markets" (I wish the approval process was as fast as these guys):

For the time being, we need any linking to point back to the Amazon Appstore only for market links. Linking to your website is allowed, just not other markets.

When pointing to other apps from within your app, including up-sells, completion of purchase must be from the Amazon Appstore.

Reed
  • 14,703
  • 8
  • 66
  • 110
user432209
  • 20,007
  • 10
  • 56
  • 75
  • 3
    @user432209: FWIW, this was discussed very recently on the `android-developers` Google Group: http://groups.google.com/group/android-developers/browse_frm/thread/d7c44877f388c0ed# – CommonsWare Mar 29 '11 at 23:42
  • Wow, disappointing, but great to know. Thanks. – user432209 Mar 29 '11 at 23:45
  • 3
    Yet another market launched... yet another market which needs to be cared for... yet another version of the same app needs to be maintained... I don't like the way it goes... – WarrenFaith Mar 30 '11 at 00:14

7 Answers7

12

Good news! Apparently the latest version of the Amazon store finally sets PackageManager.getInstallerPackageName() to "com.amazon.venezia" to contrast with Google Play's "com.android.vending". This will be the easiest way to determine if your app is sideloaded, installed from Amazon, or installed from Google.

mttmllns
  • 1,740
  • 1
  • 15
  • 13
  • how does amazon store sets packagename? you give the packagename manually yourself. can you explain this? – Emil Dec 06 '17 at 16:40
8

Here's what you can do:

  1. Complete the preparation and signing of your application.
  2. Install it on your test device
  3. Use PackageManager.getPackageInfo

How to do this:

public static boolean isMarket(Context context){
    boolean isMarketSig = false;
    int currentSig = 1;
    try {
        Signature[] sigs = context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES).signatures;
        for (Signature sig : sigs)
        {
            currentSig = sig.hashCode();


    Log.i("MyApp", "Signature hashcode : " + sig.hashCode());
// This Log is for first time testing so you can find out what the int value of your signature is.
            }
            } catch (Exception e){
                e.printStackTrace();


}
//-1545485543 was the int I got from the log line above, so I compare the current signature hashCode value with that value to determine if it's market or not.
        if (currentSig==-1545485543){
            isMarketSig = true;
    } else {
        isMarketSig = false;
    }

    return isMarketSig;
}
public static void openStore(Context context){
    if (isMarket(context)){
        Intent goToMarket = new Intent(Intent.ACTION_VIEW,Uri.parse("market://d" +
        "etails?id=com.jakar.myapp"));
        goToMarket.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(goToMarket);  
    } else {
        Intent goToAppstore = new Intent(Intent.ACTION_VIEW,Uri.parse("http://www.amazon.com/gp/mas/dl/andro" +
        "id?p=com.jakar.myapp"));
        goToAppstore.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(goToAppstore);
    }
}

Basically, the hashCode() that you get from the app installed on your testing device will be the same one from the market. The hash code from the app store will be different because according to https://developer.amazon.com/help/faq.html, the app store signs the application with a signature specific to your developer account, so that will return a different value that what you actually signed it with.

Note: It works to open the market successfully, but I haven't yet deployed this method on the App Store, so I haven't completely tested it. I am confident it will work, but can make no guarantees, so if you use what I've suggested and it fails, please don't hold me accountable.

Reed
  • 14,703
  • 8
  • 66
  • 110
6

You can do the following things:

  1. Check if the device based on its Manufacturer. For ex: https://developer.amazon.com/sdk/fire/specifications.html

  2. For writing reviews and opening the Amazon App Store use the following intent

    amzn://apps/android?p=package_name
    

    where p=Link to the detail page for a specific package name.

Ref: Amazon developer link.

https://developer.amazon.com/sdk/in-app-purchasing/sample-code/deeplink.html

j0k
  • 22,600
  • 28
  • 79
  • 90
Sagar Waghmare
  • 4,702
  • 1
  • 19
  • 20
  • Is it always Amazon? I thought that any android phone can download app from amazon store? – Emil Oct 15 '17 at 19:53
5

As you said, you could use a boolean and then be forced to build your apps twice, so I bevelive it's not the best way.

The best way is to check if android market is installed and act accordingly: here.

Another even more complex way is to query the name of the installer of your app, using PackageManager.getInstallerPackageName. This needs extra work since the app can be installed by parallel markets even if you are on android device with android market installed, and also you must check if it's installed as debug/development (installer package name is null in this case).

Community
  • 1
  • 1
Carlo Medas
  • 803
  • 9
  • 15
4

What a hard way to do this. If you just want to open the market url, just check if the intent with the url for android market has any activity that knows how to handle it. If not, open up the amazon appstore with another intent.

 /**
     * Returns intent that  opens app in Google Play or Amazon Appstore
     * @param context
     * @param packageName
     * @return null if no market available, otherwise intent
     */
    public static Intent showApp(Activity activity, String packageName)
    {
        Intent i = new Intent(Intent.ACTION_VIEW);
        String url = "market://details?id=" + packageName;
        i.setData(Uri.parse(url));

        if (isIntentAvailable(activity, i))
        {               
            return i;
        }

        i.setData(Uri.parse("http://www.amazon.com/gp/mas/dl/android?p=" + packageName));
        if (isIntentAvailable(activity, i))
        {
            return i;
        }
        return null;

    }

    public static boolean isIntentAvailable(Context context, Intent intent) {
        final PackageManager packageManager = context.getPackageManager();      
        List<ResolveInfo> list =
                packageManager.queryIntentActivities(intent,
                        PackageManager.MATCH_DEFAULT_ONLY);
        return list.size() > 0;
    }

Another way is to build using ant. This way you can generate dynamically a java class with constants set to a value that represent the app market, and output different builds with ease. This however takes some learning but when you have it running, it's very easy.

Peterdk
  • 15,625
  • 20
  • 101
  • 140
  • 2
    My Amazon Fire HD 7 (2013) *does* handle the market: intents for the GP store. It handles them by popping up a dialog asking the user if she wants to go to the page on the Amazon Appstore for the same app (even if that page does not exist). If the user selects Continue, she is taken to the Appstore page for that app, or, if the app does not exist on the Appstore yet, is taken to the main Appstore page. So, while the above may have worked in 2012, you will *not* be able to just test to see if there is an app to handle that intent in order to know if you should use a Market or an Amazon URL. – Carl Aug 10 '14 at 04:29
0

Just refactor most of your project into a Project Library, and then create multiple projects (e.g., for each app store) that have only unique icon and string resources, their own package ID declared in the manifest, and then a main activity that extends the main activity that you have defined in your library.

That way, all the unique URLs can be provided by overriding, in each particular app project's activity, the virtual or abstract methods defined in your library's main activity. The library code that that displays these URLs can obtain them via a polymorphic call to each of those methods.

That way, each such specialized project will be very small, and maintenance will be mainly to your library, as described here:

Multiple Apps with a shared code base

Community
  • 1
  • 1
Carl
  • 15,445
  • 5
  • 55
  • 53
0

I was also struggling with this, but decided that the instant success I'm seeing with my free app on Amazon warrants the time to create a second set of .apks when I make a new build. I went with the Amazon boolean flag for now, and create one common version, then a version incremented by one for the Amazon market. No other markets demand internal linking, AFAIK.

I eventually intend to code up a market chooser with a slick way to automatically figure out what to do, but there are a lot of variables - not just the market address of one app, but how different markets recognize the company name to find all apps. Some market apps hijack the main Android market protocol (e.g. Appslib and SlideMe if I remember correctly) but don't store the company name the same way. Then you need to decide where upsell links go - to the same market or to a common one (I only submitted my free app to most of the markets I use).

I am waiting for my paid app to be approved, but I am pretty sure it will be worth it to have it available on the Amazon market given how many downloads I've gotten for my free app.

ProjectJourneyman
  • 3,566
  • 1
  • 27
  • 37
  • 4
    After pursuing more markets (Nook, BlackBerry, etc.) it has become even more apparent that separate builds are the only valid solution. Dynamically checking the installed markets is very problematic, and will lead to incorrect results for users of multiple stores (e.g. Google Play and Amazon Appstore). In addition, there are more issues than just linking involved for more complex apps. – ProjectJourneyman Apr 23 '12 at 18:03
  • your answer is pretty old indeed but my questions is if user installs over amazon, packagename shoulod contain "amazon", not? what is the problem with that? even if phone can have multiple stores. – Emil Oct 15 '17 at 19:59
  • You can make the package name include "amazon" if you choose for your amazon build, but many apps use the same package name for all app stores. You could then check your package name to decide how to link. I chose to use build variant resources to determine which build I am in, and have a library to handle the linking mechanics for each store: https://github.com/TimMackenzie/AndroidMarketManager – ProjectJourneyman Dec 06 '17 at 14:57