如何打开 Android 应用,未安装则跳转 Google Play(无 JavaScript)?
可以在 Android 应用中用原生 Intent 实现:先尝试启动目标应用,找不到启动入口时打开它的 Google Play 详情页;如果设备没有可用的 Google Play 客户端,再打开网页链接。整个流程都在客户端完成,无需 JavaScript 或服务器重定向。
你需要知道目标应用的包名,目标应用也需要有允许外部启动的入口。
为什么使用 Intent
PackageManager.getLaunchIntentForPackage() 可以根据包名获取目标应用的启动 Intent,适合用来实现“打开另一个应用”的按钮。它只负责获取应用入口,跳转商店的回退逻辑需要自行编写。Android API 文档
Google Play 详情页的地址格式为:
https://play.google.com/store/apps/details?id=目标应用包名
使用 ACTION_VIEW 打开这个地址,并设置 setPackage("com.android.vending"),就可以指定由 Google Play 客户端处理。Google Play 链接说明
1. 声明目标应用的包可见性
如果应用运行在 Android 11 或更高版本,且 targetSdkVersion 为 30 或更高,查询其他应用时会受到包可见性限制。如果没有声明,可能出现目标应用已经安装,却查不到启动入口的情况。
在发起跳转的应用的 AndroidManifest.xml 中添加 <queries>,与 <application> 同级:
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<queries>
<package android:name="com.example.target" />
</queries>
<!-- 保留现有的 application 配置 -->
</manifest>
将 com.example.target 替换为目标应用实际安装包的 applicationId。已知目标包名时,使用这种定向声明即可,无需申请 QUERY_ALL_PACKAGES。包可见性声明文档
2. 编写启动和商店回退逻辑
下面的 Kotlin 函数以 Activity 为接收者,可以在界面按钮的点击事件中调用:
import android.app.Activity
import android.content.ActivityNotFoundException
import android.content.Intent
import android.net.Uri
import android.widget.Toast
fun Activity.openAppOrStore(targetPackage: String) {
fun tryOpen(intent: Intent): Boolean {
return try {
startActivity(intent)
true
} catch (_: ActivityNotFoundException) {
false
} catch (_: SecurityException) {
false
}
}
// 优先启动目标应用。
val launchIntent =
packageManager.getLaunchIntentForPackage(targetPackage)
if (launchIntent != null && tryOpen(launchIntent)) {
return
}
val storeUri = Uri.parse(
"https://play.google.com/store/apps/details"
).buildUpon()
.appendQueryParameter("id", targetPackage)
.build()
// 指定由 Google Play 客户端打开详情页。
val playIntent = Intent(Intent.ACTION_VIEW, storeUri).apply {
setPackage("com.android.vending")
}
if (tryOpen(playIntent)) {
return
}
// 不限定处理应用,允许浏览器等可用应用打开链接。
val webIntent = Intent(Intent.ACTION_VIEW, storeUri)
if (!tryOpen(webIntent)) {
Toast.makeText(
this,
"无法打开应用或 Google Play,请检查设备上的可用应用。",
Toast.LENGTH_LONG
).show()
}
}
在 Activity 中绑定按钮:
button.setOnClickListener {
openAppOrStore("com.example.target")
}
回退到网页链接时,需要新建一个不带 com.android.vending 限制的 Intent。如果保留这个限制,设备缺少 Google Play 时就无法将链接交给浏览器处理。
3. 注意启动失败与“未安装”的区别
仅凭 getLaunchIntentForPackage() 返回 null,无法确定应用未安装。目标包不可见、包名不正确,或应用没有符合条件的启动入口,都可能导致这个结果。启动入口 API 说明
上面的代码会在无法启动目标应用时打开商店,包括启动时抛出 ActivityNotFoundException 或 SecurityException 的情况。如果目标应用已经安装,却总是跳转商店,可以先检查:
<queries>中的包名是否与实际安装包一致,尤其是带有包名后缀的调试版本。- 目标应用的入口 Activity 是否启用、是否允许外部启动,以及是否需要调用方持有额外权限。
这段代码打开的是目标应用的默认入口。如果目标应用已有正常的启动入口,通常不需要为实现这个按钮而修改目标应用。
打开 Google Play 详情页也不代表一定能安装,目标应用仍需对当前用户、地区和设备可用。建议至少测试“已安装”“未安装且有 Google Play”和“没有 Google Play”这几种情况。
备注:内容仅供参考。
