Supporting Amazon and Android market (Google Play) links inside application

六月ゝ 毕业季﹏ 提交于 2019-11-27 11:42:07

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.

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.

Sagar Waghmare

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

Carlo Medas

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).

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.

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.

Carl

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!