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_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_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/apiAPI 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:exportedtrue intent-filter action android:nameandroid.intent.action.MAIN / category android:nameandroid.intent.category.LAUNCHER / /intent-filter intent-filter android:autoVerifyfalse action android:nameandroid.intent.action.VIEW / category android:nameandroid.intent.category.DEFAULT / category android:nameandroid.intent.category.BROWSABLE / data android:schememyapp android:hostdetail android:pathPrefix/item / /intent-filter /activity关键点android:exportedtrue必须显式写Android 12API 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 会拉起DetailActivitylogcat 里能看到START u0 {actandroid.intent.action.VIEW datmyapp://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 version1.0 encodingutf-8 standaloneyes ? map string nameuser_tokenabc123/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:exportedtrue需要被外部调用或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/apiKey 有没有多余空格。如果报 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 配置问题最怕的是以为改了其实没装上新包。养成installDebugforce-stop 清 logcat 的习惯比反复读代码有效得多。
返回列表