Android适配 - 跳转应用商店查看应用详情

Android 跳转手机已安装的应用市场,APP大多数都会引导用户去应用市场进行评分或者评论,正常的跳转协议已经可以满足大部分手机应用市场,但是在三星、索尼、红米上也会出现一些不一样的效果,本文记录如何适配跳转。

正常跳转

    /**
     * 跳转应用商店.
     *
     * @param context   {@link Context}
     * @param appPkg    包名
     * @param marketPkg 应用商店包名
     * @return {@code true} 跳转成功 <br> {@code false} 跳转失败
     */
    public static boolean toMarket(Context context, String appPkg, String marketPkg) {
        Uri uri = Uri.parse("market://details?id=" + appPkg);
        Intent intent = new Intent(Intent.ACTION_VIEW, uri);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        if (marketPkg != null) {// 如果没给市场的包名,则系统会弹出市场的列表让你进行选择。
            intent.setPackage(marketPkg);
        }
        try {
            context.startActivity(intent);
            return true;
        } catch (Exception ex) {
            ex.printStackTrace();
            return false;
        }
    }

正常跳转如果手机安装了多个应用市场,例如:应用宝、360手机助手,则会弹出系统选择框给用户进行选择,用户也可以勾选是否默认选择(某些机型是:始终/仅此一次)

HUAWEI Xiaomi

三星手机表现异常

上述正常方法未能打开三星的官方应用商店,也就是如果要跳转三星应用商店则需要单独适配。正确打开方式如下:

    /**
     * 跳转三星应用商店
     * @param context {@link Context}
     * @param packageName 包名
     * @return {@code true} 跳转成功 <br> {@code false} 跳转失败
     */
    public static boolean goToSamsungMarket(Context context, String packageName) {
        Uri uri = Uri.parse("http://www.samsungapps.com/appquery/appDetail.as?appId=" + packageName);
//        Uri uri = Uri.parse("http://apps.samsung.com/appquery/appDetail.as?appId=" + packageName);
        Intent intent = new Intent(Intent.ACTION_VIEW, uri);
        intent.setPackage("com.sec.android.app.samsungapps");
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        try {
            context.startActivity(intent);
            return true;
        } catch (ActivityNotFoundException e) {
            e.printStackTrace();
            return false;
        }
    }

索尼手机表现异常

上述正常方法未能打开索尼的官方应用商店-索尼精选,也有人指出索尼并无单独的应用商店,采用的是Google的Google Play,国内才推出索尼精选。正确的打开方式如下:

    /**
     * 跳转索尼精选
     * @param context {@link Context}
     * @param appId 索尼精选中分配得appId
     * @return {@code true} 跳转成功 <br> {@code false} 跳转失败
     */
    public static boolean goToSonyMarket(Context context, String appId) {
        Uri uri = Uri.parse("http://m.sonyselect.cn/" + appId);
        Intent intent = new Intent(Intent.ACTION_VIEW, uri);
//        Intent intent = new Intent();
//        intent.setAction("com.sonymobile.playnowchina.android.action.NOTIFICATION_APP_DETAIL_PAGE");
//        intent.setAction("com.sonymobile.playnowchina.android.action.APP_DETAIL_PAGE");
//        intent.putExtra("app_id", 9115);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        try {
            context.startActivity(intent);
            return true;
        } catch (Exception ex) {
            ex.printStackTrace();
            return false;
        }
    }

跳转索尼精选,附带APPID,但是这个值是索尼精选分配的,也就是上传了索尼精选后的id,例如微信的id是9115。

红米note2表现异常(未测试)

上述正常方式跳转应用市场,无论手机是否安装其他应用市场,均跳转至小米商店。(本人测试手机红米4X,属于正常跳转)

合适的跳转方式

由于上述情况多变,但是大多数情况下,正常写法已经满足要求。如果想仅仅跳转应用宝或者小米商店,而不进行系统弹窗选择,可以直接指定包名,这样就可以直接跳转。

    /**
     * 直接跳转至应用宝
     *
     * @param context {@link Context}
     * @param appPkg  包名
     * @return {@code true} 跳转成功 <br> {@code false} 跳转失败
     */
    public static boolean toQQDownload(Context context, String appPkg) {
        return toMarket(context, appPkg, "com.tencent.android.qqdownloader");
    }

    /**
     * 直接跳转至360手机助手
     *
     * @param context {@link Context}
     * @param appPkg  包名
     * @return {@code true} 跳转成功 <br> {@code false} 跳转失败
     */
    public static boolean to360Download(Context context, String appPkg) {
        return toMarket(context, appPkg, "com.qihoo.appstore");
    }

    /**
     * 直接跳转至豌豆荚
     *
     * @param context {@link Context}
     * @param appPkg  包名
     * @return {@code true} 跳转成功 <br> {@code false} 跳转失败
     */
    public static boolean toWandoujia(Context context, String appPkg) {
        return toMarket(context, appPkg, "com.wandoujia.phoenix2");
    }

    /**
     * 直接跳转至小米应用商店
     *
     * @param context {@link Context}
     * @param appPkg  包名
     * @return {@code true} 跳转成功 <br> {@code false} 跳转失败
     */
    public static boolean toXiaoMi(Context context, String appPkg) {
        return toMarket(context, appPkg, "com.xiaomi.market");
    }

    /**
     * 直接跳转至魅族应用商店
     *
     * @param context {@link Context}
     * @param appPkg  包名
     * @return {@code true} 跳转成功 <br> {@code false} 跳转失败
     */
    public static boolean toMeizu(Context context, String appPkg) {
        return toMarket(context, appPkg, "com.meizu.mstore");
    }

鉴于说上述机型差异,如果想自定义弹窗,那必须检测手机安装的应用商店有哪些,检测方式如下:(未详细测试)

    /**
     * 检查已安装的应用商店
     * 但是小米商店目前检测不出,先定义为bug
     *
     * @param context {@link Context}
     * @return 返回包名列表
     */
    public static List<String> checkMarket(Context context) {
        List<String> packageNames = new ArrayList<>();
        Intent intent = new Intent();
        intent.setAction("android.intent.action.MAIN");
        intent.addCategory("android.intent.category.APP_MARKET");
        PackageManager pm = context.getPackageManager();
        List<ResolveInfo> infos = pm.queryIntentActivities(intent, 0);
        int size = infos.size();
        for (int i = 0; i < size; i++) {
            ActivityInfo activityInfo = infos.get(i).activityInfo;
            String packageName = activityInfo.packageName;
            Log.d(TAG, "packageName : " + packageName);
            packageNames.add(packageName);
        }
        return packageNames;
    }

如何分析适配机型

按照正常的写法,三星和索尼都无法跳转。下面将分析方法记录起来,便于以后还有其他机型要适配时也知道如何进行适配。

Intent跳转方式分为显式和隐式,正常跳转属于隐式跳转,正常写法未跳转的需要去寻找其应用商店APP的跳转协议。

1.下载对应的应用商店APK,然后进行反编译。

2.主要查看AndroidManifest.xml文件,分析跳转协议。

3.使用jd-gui查看源码,分析是否会附带额外参数。

三星应用商店:
AndroidManifest.xml

<activity android:configChanges="keyboard|keyboardHidden|orientation|screenSize" android:exported="true" android:name="com.sec.android.app.samsungapps.Main" android:screenOrientation="unspecified" android:theme="@style/SamsungAppsTranslucentNoTitleBarTheme">

            <intent-filter>
                <action android:name="android.intent.action.VIEW"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <category android:name="android.intent.category.BROWSABLE"/>
                <data android:host="www.samsungapps.com" android:pathPrefix="/appquery/appDetail.as" android:scheme="http"/>
            </intent-filter>

            <intent-filter>
                <action android:name="android.intent.action.VIEW"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <category android:name="android.intent.category.BROWSABLE"/>
                <data android:host="apps.samsung.com" android:pathPrefix="/appquery/appDetail.as" android:scheme="http"/>
            </intent-filter>
</activity>

ContentDetailActivity.java

结合AndroidManifest.xml以及源码,可以分析出三星的跳转协议,经测试两中host都可以成功跳转,测试机型:三星C5,Android 7.1.1。

索尼精选

        <activity android:alwaysRetainTaskState="true" android:clearTaskOnLaunch="false" android:configChanges="fontScale|keyboard|keyboardHidden|locale|screenLayout|uiMode" android:name="com.sonyericsson.playnowchina.android.phone.AppDetailActivity" android:screenOrientation="portrait">
            <intent-filter>
                <category android:name="android.intent.category.BROWSABLE"/>
                <action android:name="android.intent.action.VIEW"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <data android:host="m.sonyselect.cn" android:scheme="http"/>
            </intent-filter>
            <intent-filter>
                <action android:name="com.sonymobile.playnowchina.android.action.NOTIFICATION_APP_DETAIL_PAGE"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
            <intent-filter>
                <action android:name="com.sonymobile.playnowchina.android.action.APP_DETAIL_PAGE"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </activity>

AppDetailActivity.java

结合AndroidManifest.xml和源码,很容易得出Action+app_id这个额外参数,但是这样的跳转无论app_id传的是包名还是上架索尼精选后的id,跳转后都Toast显示网络异常。最后按照<data> 得出结果。

测试机型

机型 版本 效果
索尼xm50t 4.3 需要单独适配索尼精选
三星C5 7.1.1 需要单独适配三星应用商店
红米4X 7.1.2,MIUI 9 正常
华为Mate8 7.0,EMUI 5.0.1 正常
魅族note3 7.0,flyme 6.2.0.1 正常
OPPOA37m 5.1,ColorOs 3.0 正常

源码

https://github.com/scauzhangpeng/Sample/blob/master/util/src/main/java/com/xyz/util/MarketUtil.java

结论:

本篇记录如何进行适配应用商店的方法,索尼精选这类在开发过程中也可以不进行适配,视情况而定。

猜你喜欢

转载自blog.csdn.net/scau_zhangpeng/article/details/79098613