支持应用内的亚马逊和安卓市场(Google Play)链接

26

今天我的一个应用被亚马逊应用商店拒绝了。原因是在我的应用程序内,我链接到了 Android 市场上的付费版本。虽然令人失望,但没关系,我猜每个人都想分一杯羹...

现在我必须修改应用程序,将 Android 市场的链接更改为亚马逊应用商店的链接。这不算什么大问题,但是如果我这样做,当我想上传新版本回到 Android 市场时,就会产生差异。毕竟,如果用户从 Android 市场购买应用程序,将他们引导到亚马逊应用商店相当愚蠢。

现在我们都知道支持和管理相同应用程序的多个版本很麻烦。因此,我的问题是如何同时连接这两个市场?是否有一种方法可以告诉我从哪里下载了应用程序,以便我可以在应用程序中编写这两个链接,并自动指向其中之一?其次,给用户选择下载来源(比如弹出对话框并询问用户要从哪里下载)符合亚马逊服务条款吗?

谢谢大家。

编辑:直接来自亚马逊客户服务的回复“关于连接两个市场”(我希望批准过程和这些家伙一样快):

目前,我们需要任何链接只指向亚马逊应用商店的市场链接。允许链接到您的网站,但不允许链接到其他市场。

当从应用程序内部指向其他应用程序时,包括升级销售,必须通过亚马逊应用商店完成购买。


3
值得一提的是,最近在“android-developers”谷歌小组上讨论过这个问题:http://groups.google.com/group/android-developers/browse_frm/thread/d7c44877f388c0ed# - CommonsWare
哇,有点失望,但是很好知道。谢谢。 - user432209
3
又一个市场发布了... 又一个需要关注的市场... 同一个应用的又一个版本需要维护... 我不喜欢它的发展方式... - WarrenFaith
7个回答

12

好消息!显然, 亚马逊商店的最新版本终于将 PackageManager.getInstallerPackageName() 设置为 "com.amazon.venezia",以与 Google Play 的 "com.android.vending" 相对应。这将是确定您的应用程序是否是侧载、从亚马逊安装或从 Google 安装的最简单方法。


亚马逊是如何存储集合包名称的?您需要手动输入包名称吗?您能解释一下吗? - Emil

8

以下是你可以做的:

  1. 完成应用程序的准备和签名。
  2. 在测试设备上安装应用程序。
  3. 使用 PackageManager.getPackageInfo 方法。

如何操作:

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);
    }
}

基本上,您从测试设备上安装的应用程序中获取的hashCode()将与市场上的hashCode()相同。来自应用商店的哈希码将不同,因为根据https://developer.amazon.com/help/faq.html,应用商店使用特定于您的开发者帐户的签名对应用程序进行签名,因此将返回与实际签名不同的值。
注意:成功打开市场是可行的,但我尚未在应用商店上部署此方法,因此我尚未完全测试它。我有信心它会起作用,但不能保证,因此如果您使用我建议的方法失败,请不要追究我的责任。

6

它总是亚马逊吗?我认为任何安卓手机都可以从亚马逊商店下载应用程序? - Emil

5

正如你所说,你可以使用布尔值,然后被迫构建两次应用程序,因此我认为这不是最好的方法。

最好的方法是检查 Android 市场是否已安装并相应地采取行动: 在这里

另一种更复杂的方法是查询您的应用程序安装程序的名称,使用 PackageManager.getInstallerPackageName。这需要额外的工作,因为即使您在安装了 Android 市场的 Android 设备上安装了应用程序,该应用程序也可能通过平行市场安装,并且您必须检查它是否以调试/开发方式安装(在这种情况下,安装程序包名称为空)。


真的很酷!我一直在寻找这样的领域,但是找不到! - Peterdk

4

这样做真是太麻烦了。如果只是想打开市场网址,只需检查带有Android市场url的意图是否有任何可以处理它的活动。如果没有,使用另一个意图打开亚马逊应用商店。

 /**
     * 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;
    }

另一种方法是使用ant进行构建。通过这种方式,您可以动态生成一个带有常量设置为表示应用市场的值的java类,并轻松输出不同的构建版本。但是,这需要一些学习,但一旦掌握了,就非常容易。

2
我的Amazon Fire HD 7(2013)确实可以处理市场:GP商店的意图。它通过弹出对话框来处理它们,询问用户是否想要转到Amazon应用商店上相同应用的页面(即使该页面不存在)。如果用户选择继续,她将被带到该应用的Appstore页面,或者如果该应用尚未存在于Appstore上,则会被带到主Appstore页面。因此,虽然以上内容可能在2012年有效,但您将无法仅通过测试是否有应用程序来处理该意图,以便知道是否应使用Market还是Amazon URL。 - Carl

0

我也曾为此苦恼,但决定在我创建新版本时花时间创建第二组.apks,因为我在亚马逊免费应用程序上看到的即时成功值得。我现在使用亚马逊布尔标志,并创建一个通用版本,然后为亚马逊市场创建一个递增的版本。据我所知,没有其他市场要求内部链接。

我最终打算编写一个市场选择器,以一种流畅的方式自动确定该做什么,但有很多变量 - 不仅是一个应用程序的市场地址,还有不同市场如何识别公司名称以查找所有应用程序。一些市场应用程序劫持了主要的Android市场协议(例如Appslib和SlideMe,如果我记得正确),但没有以相同的方式存储公司名称。然后,您需要决定升级链接放在哪里 - 放在同一个市场还是放在一个通用市场上(我只向我使用的大多数市场提交了我的免费应用程序)。

我正在等待我的付费应用程序获得批准,但我非常确定,在亚马逊市场上提供它将是值得的,考虑到我已经为我的免费应用程序获得了多少下载量。


4
在追求更多市场(Nook、BlackBerry等)后,越来越明显地发现分别构建应用程序是唯一有效的解决方案。动态检查安装的市场非常棘手,并且会导致使用多个商店(例如Google Play和Amazon Appstore)的用户得出错误的结果。此外,对于更复杂的应用程序,涉及到的问题不仅仅是链接。 - ProjectJourneyman
你的回答确实有些过时了,但我的问题是如果用户在亚马逊上安装,包名应该包含“amazon”,不是吗?这有什么问题吗?即使手机可以有多个商店。 - Emil
如果您选择进行亚马逊构建,可以使软件包名称包含“amazon”,但许多应用程序在所有应用商店中使用相同的软件包名称。然后,您可以检查软件包名称以决定如何链接。我选择使用构建变体资源来确定我所处的构建,并有一个库来处理每个商店的链接机制:https://github.com/TimMackenzie/AndroidMarketManager - ProjectJourneyman

0

只需将项目的大部分重构成一个项目库,然后创建多个项目(例如,每个应用商店一个)只包含独立的图标和字符串资源,在清单中声明它们自己的包ID,以及继承你在库中定义的主活动的主活动。

这样一来,所有独特的URL可以通过覆盖在每个特定应用项目的活动中定义的虚拟或抽象方法在您的库的主活动中提供。显示这些URL的库代码可以通过对这些方法的多态调用获取它们。

这样,每个专门的项目都会非常小,并且维护主要是针对库进行,如下所述:

共享代码基础的多个应用程序


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接