前言
在国内基本上每个手机厂商都会有自己的手机应用市场,建立自己的生态,相应的也会在出厂手机的时候内置安装某些app。并且在出厂的时候,如果你没有装过SIM卡激活,是不能通过USB安装应用,这也间接的阻止了中间商在中间预装某些app获利。 App在这些市场上架,相应的会有应用市场的的评论,就像淘宝卖东西一样,用户在买某一件东西的时候,会在下面看看其他买家的评论,看看这个东西好不好用,差评怎么样,好评怎么样。所以App在应用市场也一样,用户在下载这个app的时候会在评论区看看这个app好不好用,受不受欢迎,值不值得下载,所以很多公司App都会有去应用市场评论的功能。
需求
- 增加引导用户去应用市场评价,目标是持续增加应用市场的好评数。
- 面向对象,要筛选出大概率给好评的用户,这里可以从面向行为入手,如某个用户在买了某件商品之后进行了评价,评价的行为都很好,就弹窗引导用户去应用市场评价。
- 某些应用市场的评论过少,或者差评过多,支持运营人员可配置跳转到某个应用市场去评论。
需求分析
对于前端来说,这其实是一个很简单的需求.
- 需要接口返回字段判断是否显示跳转应用市场去评论的弹窗
- 后台可配置应用市场列表,前端根据查找手机已经安装的应用市场跟列表比对,配对上的然后弹窗提供给用户选择去那个应用市场.
- 方式2是可配置多个,其实作为运营的话,我感觉只要配置一个就好了,如果手机安装了就跳转过去,否则跳转到默认的市场。
实现
- 后台配置单个的应用市场只需要根据后台配置的应用市场包名跟页面进行弹窗,跳转就好了。这里需要应用市场包名跟页面名字,前端可以拿到apk进行分析一下,给到后端。
/**
* 根据app包名跳转指定包名,指定页面的应用市场
* @param mContext
* @param packageName
* @param marketPageName
*/
public static void gotoEvaluateMarket(Context mContext,String packageName,String marketPageName) {
if("com.sec.android.app.samsungapps".equals(packageName)) {
goToSamsungappsMarket(mContext,packageName,marketPageName);// 针对三星市场做特殊处理,不然进不到详情页
return;
}
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("market://details?id="+mContext.getPackageName()));
if(!TextUtils.isEmpty(packageName) && !TextUtils.isEmpty(marketPageName)) {
intent.setClassName(packageName, marketPageName);
}
try {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(intent);
} catch (Exception e) {
//1.这个地方可能会因为手机上没有任何应用市场异常。
//2.可能是设置的应用市场的pageName页面没有在清单里面设置Action,报权限异常:
//java.lang.SecurityException: Permission Denial:
// starting Intent { act=android.intent.action.VIEW dat=market://details?id=com.xx.xx cmp=com.baidu.appsearch/.login.BindWidgetActivity }
// from ProcessRecord{a574e4d 24266:com.xx.xx/u0a146} (pid=24266, uid=10146) not exported from uid 10126
if(e instanceof SecurityException) {
gotoEvaluateMarket(mContext,"","");
} else {
Toast.makeText(mContext, "您的手机没有安装安卓应用市场", Toast.LENGTH_SHORT).show();
}
}
}
/**
* 跳转三星应用市场详情页
* @param mContext
* @param packageName
* @param marketPageName
*/
public static void goToSamsungappsMarket(Context mContext,String packageName,String marketPageName) {
Uri uri = Uri.parse("http://www.samsungapps.com/appquery/appDetail.as?appId=" + mContext.getPackageName());
Intent intent = new Intent();
intent.setClassName(packageName, marketPageName);
intent.setData(uri);
try {
mContext.startActivity(intent);
} catch (ActivityNotFoundException e) {
e.printStackTrace();
Toast.makeText(mContext, "您的手机没有安装安卓应用市场", Toast.LENGTH_SHORT).show();
}
}
- 当需求是后端可以配置多个应用市场,前端匹配到弹出列表给用户选择的时候,这就需要获取当前手机上安装的应用市场包名了。
/**
* 获取手机上安装的lancher应用
* @param context
*/
public static ArrayMap<String,String> getInstalledLancherAPK(Context context) {
ArrayMap<String,String> pkgs = new ArrayMap<>();
Intent intent = new Intent(Intent.ACTION_MAIN, null);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
List<ResolveInfo> apps = context.getPackageManager().queryIntentActivities(intent, 0);
if (apps == null || apps.size() == 0){
return pkgs;
}
//for循环遍历ResolveInfo对象获取包名和类名
for (int i = 0; i < apps.size(); i++) {
ResolveInfo info = apps.get(i);
String packageName = info.activityInfo.packageName;
String cls = info.activityInfo.name;
CharSequence name = info.activityInfo.loadLabel(context.getPackageManager());
if (!TextUtils.isEmpty(packageName)) {
Log.e("admin--a", name + "----" + packageName + "----" + cls);
pkgs.put(packageName,cls);
}
}
return pkgs;
}
/**
* 获取当前手机上安装的应用商店包名跟指定页面
*
* @param context
* @return
*/
public static ArrayMap<String,String> getInstalledMarketPackageName(Context context) {
ArrayMap<String,String> pkgs = new ArrayMap<>();
Intent intent = new Intent();
intent.setAction("android.intent.action.VIEW");
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setData(Uri.parse("market://details?id="));
PackageManager pm = context.getPackageManager();
// 通过queryIntentActivities获取ResolveInfo对象
List<ResolveInfo> infos = pm.queryIntentActivities(intent, 0);
if (infos == null || infos.size() == 0) {
return pkgs;
}
int size = infos.size();
for (int i = 0; i < size; i++) {
String pkgName = "";
CharSequence name = "";
String cls = "";
try {
ActivityInfo activityInfo = infos.get(i).activityInfo;
pkgName = activityInfo.packageName;
cls = activityInfo.name;
name = activityInfo.loadLabel(context.getPackageManager());
} catch (Exception e) {
e.printStackTrace();
}
if (!TextUtils.isEmpty(pkgName)) {
Log.e("admin--b", name + "----" + pkgName + "----" + cls);
pkgs.put(pkgName,cls);
}
}
return pkgs;
}
//打印数据
//admin--b: 应用商店----com.xiaomi.market----com.xiaomi.market.ui.JoinActivity
//admin--b: 豌豆荚----com.wandoujia.phoenix2----com.pp.assistant.activity.PPMainActivity
//admin--b: 应用商店----com.bbk.appstore----com.vivo.router.ui.jump.JumpActivity
//admin--b: UC浏览器----com.UCMobile----com.UCMobile.main.UCMobile
//admin--b: 百度手机助手----com.baidu.appsearch----com.baidu.appsearch.UrlHandlerActivity
//admin--b: 360手机助手----com.qihoo.appstore----com.qihoo.appstore.home.LauncherActivity
//admin--b: 应用宝----com.tencent.android.qqdownloader----com.tencent.pangu.link.SplashActivity
对不同手机一些调用方法调研
- 方法一
public static void search(Context mContext) {
try {
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse("market://search?q="+mContext.getPackageName()));
mContext.startActivity(i);
} catch (Exception e) {
Toast.makeText(mContext, "您的手机没有安装Android应用市场", Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
}
改方式不能像网上说的那样,会列出手机上所以安装的应用市场,从uri看出,这个方式最多是打开配置了search的页面。 所以在小米手机上的效果如下:
在google 手机上效果如下:
同时使用上面实现的方式跳转 google手机上不会直接跳转,而是选中你要跳转的,弹窗让你选择,效果如下:
- 方式二:
public static void gotoEvaluateMarket(Context mContext, String marketPkg) {
try {
Uri uri = Uri.parse("market://details?id=" + mContext.getPackageName());
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
if (!TextUtils.isEmpty(marketPkg)) {
intent.setPackage(marketPkg);
}
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(intent);
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(mContext, "您的手机没有安装安卓应用市场", Toast.LENGTH_SHORT).show();
}
}
此方式很多市场都跳转不过去。
包名跟页面整理
# 小米应用商店
packageName = "com.xiaomi.market";
marketPageName = "com.xiaomi.market.ui.AppDetailActivity";
//或
marketPageName = "com.xiaomi.market.ui.JoinActivity";
# 魅族应用商店
packageName = "com.meizu.mstore";
marketPageName = "com.meizu.flyme.appcenter.activitys.AppMainActivity";
# VIVO应用商店
packageName = "com.bbk.appstore";
marketPageName = "com.vivo.router.ui.jump.JumpActivity";
# 应用宝
packageName = "com.tencent.android.qqdownloader";
marketPageName = "com.tencent.pangu.link.LinkProxyActivity";
# 百度手机助手
packageName = "com.baidu.appsearch";
marketPageName = "com.baidu.appsearch.UrlHandlerActivity";
# 360手机助手
packageName = "com.qihoo.appstore";
marketPageName = "com.qihoo.appstore.home.LauncherActivity";
//或
marketPageName = "com.qihoo.appstore.distribute.SearchDistributionActivity";
# 豌豆荚
packageName = "com.wandoujia.phoenix2";
marketPageName = "com.pp.assistant.activity.PPMainActivity";
# 华为应用商店
packageName = "com.huawei.appmarket";
marketPageName = "com.huawei.appmarket.service.externalapi.view.ThirdApiActivity";
# OPPO应用商店
packageName = "com.oppo.market";
marketPageName = "a.a.a.aoz";
# UC浏览器
packageName = "com.UCMobile";
marketPageName = "com.UCMobile.main.UCMobile";
# 安智市场
packageName = "com.anzhi.market";
marketPageName = "com.anzhi.market.ui.AppDetailsActivity";
# 三星市场
//三星市场使用上面的方法不能跳到详情页面,只能打开三星应用市场。
packageName = "com.sec.android.app.samsungapps";
marketPageName = "com.sec.android.app.samsungapps.Main";
# 联想应用市场
packageName = "com.lenovo.leos.appstore";
marketPageName = "com.lenovo.leos.appstore.activities.AppDetailActivity";