You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Instant App:如何基于基础功能导航抽屉实现Feature的URL Intent跳转

嘿,这个场景我帮不少开发者踩过坑,核心要抓住的一点是:不能让各个Feature直接启动自己的独立Activity,而是要让Base Feature里带导航抽屉的容器Activity来统一处理所有URL Intent,然后把Feature的页面作为内容嵌入进去。这样导航抽屉就能一直保留在界面上了。下面给你一步步拆解实现细节:

核心思路

Base Feature作为所有模块的共享基础,要承担「导航抽屉宿主+URL入口处理器」的双重角色。所有Feature的页面都以Fragment(而非独立Activity)的形式存在,当用户点击抽屉项或外部触发URL Intent时,由Base的容器Activity接收并加载对应的Feature Fragment,整个过程中导航抽屉始终作为容器的一部分存在。

具体实现步骤

1. 搭建Base Feature的导航抽屉容器Activity

首先在Base里创建一个带导航抽屉的主Activity,比如BaseDrawerActivity,它是整个App/Instant App的核心入口,负责承载所有Feature的内容。

示例代码(Kotlin)

class BaseDrawerActivity : AppCompatActivity() {
    private lateinit var drawerLayout: DrawerLayout
    private lateinit var navView: NavigationView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_base_drawer)

        // 初始化导航抽屉组件
        drawerLayout = findViewById(R.id.drawer_layout)
        navView = findViewById(R.id.nav_view)

        // 处理抽屉菜单项点击,触发对应Feature的URL Intent
        navView.setNavigationItemSelectedListener { menuItem ->
            when (menuItem.itemId) {
                R.id.nav_feature1 -> launchFeature("yourapp://feature1")
                R.id.nav_feature2 -> launchFeature("yourapp://feature2")
            }
            drawerLayout.closeDrawer(GravityCompat.START)
            true
        }

        // 处理启动时的URL Intent,加载对应Feature页面
        intent?.let { handleIntent(it) }
    }

    // 处理新的Intent(比如从后台切回时的深层链接)
    override fun onNewIntent(intent: Intent?) {
        super.onNewIntent(intent)
        intent?.let { handleIntent(it) }
    }

    private fun launchFeature(url: String) {
        val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
        startActivity(intent)
    }

    // 解析URL,加载对应的Feature Fragment
    private fun handleIntent(intent: Intent) {
        intent.data?.let { uri ->
            when (uri.host) {
                "feature1" -> loadFeatureFragment(Feature1Fragment())
                "feature2" -> loadFeatureFragment(Feature2Fragment())
            }
        }
    }

    private fun loadFeatureFragment(fragment: Fragment) {
        supportFragmentManager.beginTransaction()
            .replace(R.id.content_container, fragment)
            .commit()
    }
}

对应的布局文件(activity_base_drawer.xml)

<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <!-- 内容容器:所有Feature的Fragment都会在这里替换显示 -->
    <FrameLayout
        android:id="@+id/content_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <!-- 导航抽屉菜单 -->
    <com.google.android.material.navigation.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:menu="@menu/drawer_menu" />

</androidx.drawerlayout.widget.DrawerLayout>

2. 配置Feature模块的页面为可嵌入的Fragment

每个Feature模块不要创建独立的根Activity,而是提供Fragment作为内容页面,这样Base的容器Activity可以直接加载它们。

比如Feature1模块的Feature1Fragment:

class Feature1Fragment : Fragment() {
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_feature1, container, false)
    }

    // 如果需要接收URL参数,可以添加静态创建方法
    companion object {
        fun newInstance(param: String?): Feature1Fragment {
            val fragment = Feature1Fragment()
            param?.let {
                val args = Bundle()
                args.putString("param_key", it)
                fragment.arguments = args
            }
            return fragment
        }
    }
}

3. 配置URL Intent过滤规则

在Base Feature的AndroidManifest.xml中,给BaseDrawerActivity添加Intent Filter,让它成为所有Feature URL的处理入口。不要在Feature模块的Manifest中配置独立的Activity Intent Filter,否则会直接启动Feature的Activity,跳过Base的导航抽屉。

<activity
    android:name=".BaseDrawerActivity"
    android:exported="true">
    <!-- 作为App/Instant App的启动入口 -->
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>

    <!-- 处理Feature1的URL -->
    <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:scheme="yourapp"
            android:host="feature1" />
    </intent-filter>

    <!-- 处理Feature2的URL -->
    <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:scheme="yourapp"
            android:host="feature2" />
    </intent-filter>
</activity>

4. 配置Instant App和完整App模块的依赖

在Instant App模块的build.gradle中,确保依赖Base Feature和所有Feature模块:

dependencies {
    implementation project(':base')
    implementation project(':feature1')
    implementation project(':feature2')
}

完整App模块的配置类似,保证所有模块都被正确包含。

5. 处理URL参数传递(可选)

如果需要给Feature传递参数,可以通过URL的Query参数实现,在handleIntent方法中解析:

private fun handleIntent(intent: Intent) {
    intent.data?.let { uri ->
        val param = uri.getQueryParameter("item_id")
        when (uri.host) {
            "feature1" -> {
                val fragment = Feature1Fragment.newInstance(param)
                loadFeatureFragment(fragment)
            }
            // 处理其他Feature
        }
    }
}
关键注意事项
  • 所有URL Intent必须由Base的容器Activity统一处理,禁止Feature模块的Activity直接接收Intent。
  • 用Fragment作为Feature的内容载体,确保可以无缝嵌套在Base的导航抽屉布局中。
  • 保证Base Feature是所有模块(Instant App和完整App)的依赖项,确保导航抽屉的代码共享。

内容的提问来源于stack exchange,提问作者user3833749

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:18:07