PAYATHON 2026

如何打开 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”这几种情况。

备注:内容仅供参考。