拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Android 小知识:用 Cursor 调试 emulator 里的 intent-filter 与 sp 配置

Android 小知识:用 Cursor 调试 emulator 里的 intent-filter 与 sp 配置

1. 为什么你的 intent-filter 在 emulator 里没反应

先说一个我踩过的坑:在 Cursor 里改完AndroidManifest.xml,点 Run 之后 emulator 里点图标还是进旧页面,adb shell am start报Activity not found。查了半天代码,最后发现是 intent-filter 的exported没写、或者category拼错一个字母。这类问题在真机上可能被系统"兜底"掩盖,但在 emulator 上会直接暴露。

这篇聚焦两件事:intent-filter 声明不生效导致跳转失败,以及SharedPreferences(下面简称 sp)读写不生效导致数据不持久化。这两个问题在 Cursor 里调试 emulator 时特别容易撞上,因为 Cursor 的 AI 补全会帮你生成看起来没问题的 manifest 片段,但 Android 12 之后对exported的强制要求、以及 sp 的apply()异步特性,AI 不一定每次都提醒你。

适合谁看:正在用 Cursor 写 Android、跑 emulator 调试、被"配置写了但没生效"卡住的开发者。你需要的基础是会用adb、知道AndroidManifest.xml和Activity大概是什么。

核心检索词先摆出来:Android intent-filter 不生效、SharedPreferences 读写不生效、Cursor 调试 emulator。这三个词贯穿全文,后面每一步操作都围绕它们展开。

我实测下来,90% 的"不生效"不是代码逻辑错,而是三类盲区:manifest 合并后属性被覆盖、emulator 缓存了旧的安装包、sp 的提交时机和读取时机错位。下面按"先定位、再配置、后验证"的顺序拆开讲,每一步都给可复制的片段和命令。

先明确一个概念:intent-filter 是 Activity 的"名片",告诉系统"我能响应哪些 Intent"。系统在startActivity时,会拿 Intent 的 action、category、data 去匹配所有已注册 Activity 的 intent-filter,匹配上才启动。emulator 里如果匹配失败,日志会打ActivityNotFoundException或Unable to find explicit activity class。而 sp 是键值对存储,写在/data/data/<包名>/shared_prefs/下的 XML 文件里,apply()是异步落盘,commit()是同步。读的时候如果getSharedPreferences的名字和写的时候不一致,就会读到空。

2. 在 Cursor 里接上 TaoToken 做配置排查

Cursor 本身是编辑器,它不会帮你跑 emulator,但它的 AI 对话和代码补全可以帮你快速定位 manifest 和 sp 的问题。我习惯把 TaoToken 的模型对话接进 Cursor 的工作流,遇到报错直接把日志贴进去问,比翻文档快。

TaoToken 是一个模型 API 聚合入口,官网在 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 端点是 https://taotoken.net/api 。它的作用是让你在 Cursor 里用统一的 Key 调用不同模型,排查 Android 配置问题时不用来回切工具。

前置准备分三步。第一步,去 https://taotoken.net/api-keys 生成一个 API Key,复制下来,这个 Key 后面要填进 Cursor 的配置里。第二步,确认你的 Cursor 版本支持自定义模型端点(Settings 里有 Models 或 OpenAI API Key 的入口)。第三步,准备好你的 emulator,用adb devices确认设备在线,输出类似emulator-5554 device就对了。

这里要提醒一句:TaoToken 是模型调用入口,不是 Android 构建工具,它不替代 Gradle、不替代 emulator。它的价值在于你排查 intent-filter 或 sp 问题时,能快速让模型帮你分析日志、生成对照配置。

配置 Cursor 的模型端点时,Base URL 填https://taotoken.net/api,API Key 填刚才生成的,Model ID 填你需要的模型名。如果你用的是 Claude Code 类的编码场景,可以参考 https://taotoken.net/coding-plan 里的说明;如果只是想验证模型能不能通,用 https://taotoken.net/chat 先测一下。

我试过把 emulator 的 logcat 输出直接贴给模型,让它判断 intent-filter 匹配失败的原因,比自己在几百行日志里找ActivityNotFoundException快很多。但注意,模型给的建议要自己验证,尤其是 manifest 属性,Android 版本差异很大。

3. 可复制的 intent-filter 与 sp 配置片段

这一节给完整可复制的配置。先看 intent-filter。假设你要让一个DetailActivity响应自定义 scheme 跳转,同时保留 Launcher 入口,AndroidManifest.xml里这样写:

<activity android:name=".DetailActivity" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <intent-filter android:autoVerify="false"> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="myapp" android:host="detail" android:pathPrefix="/item" /> </intent-filter> </activity>

关键点:android:exported="true"必须显式写,Android 12(API 31)之后,带 intent-filter 的组件不写 exported 会直接编译失败或安装失败。category.DEFAULT是隐式 Intent 匹配的必需项,漏了就用am start起不来。data的 scheme、host、pathPrefix 三者要和你am start传的 URI 完全对应。

再看 sp 的读写。写的时候:

val sp = getSharedPreferences("app_config", Context.MODE_PRIVATE) sp.edit().putString("user_token", "abc123").apply()

读的时候:

val sp = getSharedPreferences("app_config", Context.MODE_PRIVATE) val token = sp.getString("user_token", "") Log.d("SP_DEBUG", "token=$token")

注意"app_config"这个名字,读写必须完全一致,大小写敏感。apply()是异步写内存再异步落盘,commit()是同步落盘并返回 boolean。调试阶段建议先用commit(),能立刻拿到写入结果:

val ok = sp.edit().putString("user_token", "abc123").commit() Log.d("SP_DEBUG", "commit result=$ok")

如果你在 Cursor 里用 AI 生成配置,建议把上面两段作为模板贴进对话,让模型基于你的包名和 Activity 名改写,而不是让它从零生成,减少拼写错误。

4. 在 emulator 上验证跳转与数据持久化

配置写完,怎么验证?分两条线。

验证 intent-filter 跳转:先装包,./gradlew installDebug,然后确认 Activity 已注册:

adb shell dumpsys package com.example.myapp | grep -A 5 "DetailActivity"

输出里应该能看到你的 intent-filter 的 action 和 data。然后用am start模拟跳转:

adb shell am start -a android.intent.action.VIEW -d "myapp://detail/item/42" com.example.myapp

如果成功,emulator 会拉起DetailActivity,logcat 里能看到START u0 {act=android.intent.action.VIEW dat=myapp://detail/item/42 ...}。如果失败,报Error: Activity not started, unable to resolve Intent,说明 intent-filter 没匹配上,回去检查 data 的 scheme/host/pathPrefix。

验证 sp 持久化:写入后,直接看文件:

adb shell run-as com.example.myapp cat /data/data/com.example.myapp/shared_prefs/app_config.xml

正常输出类似:

<?xml version='1.0' encoding='utf-8' standalone='yes' ?> <map> <string name="user_token">abc123</string> </map>

如果文件不存在或 map 为空,说明写的时候 sp 名字错了,或者apply()还没落盘就被你杀了进程。用commit()再试一次。验证持久化还要做一步:adb shell am force-stop com.example.myapp杀掉进程,再重新启动 App,读一次 sp,看值还在不在。这一步能排除"只写了内存没落盘"的假象。

emulator 有个坑:如果你用-wipe-data启动,/data会被清空,sp 全丢。调试持久化时别带这个参数。

5. 常见报错排查对照

这一节列真实会撞上的报错,对照着查。

报错一:android:exported needs to be explicitly specified。这是 Android 12+ 的强制要求,带 intent-filter 的 activity、service、receiver 必须写android:exported。解决:在对应组件上加android:exported="true"(需要被外部调用)或"false"(仅内部)。

报错二:ActivityNotFoundException: Unable to find explicit activity class。两种可能:一是 Activity 没在 manifest 注册;二是am start的组件名写错。先用adb shell dumpsys package <包名> | grep <Activity名>确认注册,再检查am start -n 包名/完整类名的写法。

报错三:local proxy failed或连接模型端点超时。这通常出现在 Cursor 调模型时,检查 Base URL 是不是https://taotoken.net/api,Key 有没有多余空格。如果报 401,说明 Key 无效或过期,去 https://taotoken.net/api-keys 重新生成。接入细节看 https://taotoken.net/doc 。

报错四:reading choices相关解析错误。这是模型返回体解析失败,多半是 Model ID 填错,或者请求格式和端点不匹配。确认你填的 Model ID 在 TaoToken 支持的列表里,请求走 OpenAI 兼容格式。

报错五:sp 读出来是 null 或默认值。检查三件事:getSharedPreferences的名字读写是否一致;写入是否用了commit()并确认返回 true;读取是否在写入之前执行(时序问题)。用run-as直接看 XML 文件是最快的定位方式。

报错六:OAuth 或鉴权失败。如果你在 Cursor 里配的是需要 OAuth 的模型,确认 token 没过期。TaoToken 的 Key 鉴权走 Header,格式是Authorization: Bearer <你的Key>,别漏了Bearer。

排查顺序建议:先看 logcat 的E级别日志,再用dumpsys确认组件注册,最后用run-as看 sp 文件。三步走完,基本能定位。

6. 把调试链路固定下来

最后给一个我常用的固定动作。每次改完 manifest 或 sp 相关代码,按这个顺序走一遍:./gradlew installDebug重装,adb shell am force-stop <包名>杀进程,adb logcat -c清日志,然后触发跳转或读写,adb logcat | grep -E "SP_DEBUG|ActivityTaskManager"看输出。这套动作能排除 emulator 缓存旧包导致的"改了没生效"。

Cursor 这边,把常用的排查 prompt 存成 snippet,比如"分析这段 logcat,判断 intent-filter 是否匹配失败",遇到问题直接调用。模型端点用 TaoToken 统一管理,Key 和 Base URL 固定下来,换模型只改 Model ID。需要长期跑编码任务的,可以看 https://taotoken.net/coding-plan ;只是临时验证模型通不通的,用 https://taotoken.net/chat 就够。

调试 Android 配置问题,最怕的是"以为改了其实没装上新包"。养成installDebug+force-stop+ 清 logcat 的习惯,比反复读代码有效得多。

返回列表