首页 / 资讯中心 / 文章详情

Android 扫描识别车牌与身份证:TaoToken 统一 Key 接入配置与验证

Android 扫描识别车牌与身份证:TaoToken 统一 Key 接入配置与验证 ★ FEATURED ARTICLE
1. Android 扫描识别车牌与身份证从相机回调到统一 Key 接入Android 端做车牌和身份证扫描识别最麻烦的往往不是相机取景而是识别能力怎么接、Key 怎么管、多个识别接口怎么统一。我最近在做一个案件信息录入类的 App需要在同一个页面里既拍身份证又拍车牌一开始每个识别能力单独申请一套凭证代码里散落着好几处初始化逻辑改一个环境要翻半天。后来把识别请求统一走 TaoToken 的 API 通道用一套 Key 管理所有调用配置集中到config.toml和settings.json里Android 侧只负责把拍到的图片转成 Base64 或文件流发出去识别结果解析逻辑基本不用动。这篇就按这个思路写先讲清楚 Android 扫描识别车牌、身份证这个场景里常见的接入痛点再把 TaoToken 的前置准备、可复制的配置文件骨架、CC Switch 和 Cline 的配置片段给出来最后用一次真实的扫描识别请求做验证并列出我踩过的几个坑。适合已经在写 Android 相机回调、但被多套 Key 和识别接口配置搞烦的开发者。TaoToken 在这里的角色是一个统一的 API 通道把车牌识别、身份证识别这类能力收敛到同一个入口你只需要维护一份 Key 和一份配置。官网地址是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 入口是 https://taotoken.net/api 注意 API 地址不带 UTM 参数。2. TaoToken 前置准备Key、模型与通道确认在写 Android 代码之前先把服务端这侧的东西准备好不然后面调试会分不清是 App 的问题还是 Key 的问题。第一步是拿到 API Key。进入控制台的 API Keys 页面创建一个新的 Key建议按项目命名比如android-ocr-demo方便后面区分。创建后立刻复制保存页面刷新后就看不到完整值了。控制台入口https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite API Keys 页面https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 。第二步是确认你要用的识别能力对应的模型名。TaoToken 的模型列表里会区分通用对话模型和视觉/识别类模型车牌和身份证属于图像理解范畴选支持图片输入的模型。你可以在模型对话页面先手动传一张车牌图试试确认返回结构长什么样再去写 Android 代码。模型对话入口https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentchatutm_campaignrewrite 。第三步是确认请求格式。TaoToken 的 API 兼容常见的多模态消息结构图片可以用 Base64 内联也可以用可访问的 URL。Android 端拍完照拿到的是本地文件最省事的做法是读成字节数组再 Base64 编码拼进image_url字段。这里要注意 Base64 会让请求体变大身份证正面照压缩到 200KB 以内比较稳。如果你打算长期在 Android 项目里做识别和编码辅助可以看一下 Coding Plan它更适合持续性的开发调用场景https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 遇到字段不确定的时候以文档为准。3. 可复制配置config.toml 与 settings.json 骨架Android 项目本身不直接读 toml但很多配套工具链比如 CC Switch、Cline用 toml 和 json 管理通道配置。我习惯把识别通道的配置抽出来Android 侧只读一个BuildConfig里的 baseUrl 和 key其余交给工具链。先给config.toml骨架放在项目根目录或者工具配置目录下# config.toml # TaoToken 统一通道配置Android 识别项目示例 [provider] name taotoken base_url https://taotoken.net/api api_key sk-你的Key填这里 timeout_seconds 60 [models] # 车牌识别用的视觉模型 plate gpt-4o # 身份证识别用的视觉模型 idcard gpt-4o [request] # 图片压缩质量0-100 image_quality 40 # 单次请求最大图片字节数 max_image_bytes 512000 # 是否开启方向检测 detect_direction true [logging] level info save_raw_response false再给settings.json骨架这个更适合放在 Android 的 assets 或者工具链的配置目录{ taotoken: { baseUrl: https://taotoken.net/api, apiKey: sk-你的Key填这里, endpoints: { chat: /v1/chat/completions, models: /v1/models }, ocr: { plateModel: gpt-4o, idCardModel: gpt-4o, imageQuality: 40, maxImageBytes: 512000 }, retry: { maxAttempts: 3, backoffMs: 800 } } }Android 侧读取的时候把baseUrl和apiKey通过build.gradle的buildConfigField注入避免硬编码在 Java 里。这样切换环境只改一处。CC Switch 的配置片段加到它的 provider 列表里[[providers]] name taotoken-ocr base_url https://taotoken.net/api api_key sk-你的Key填这里 models [gpt-4o]Cline 的配置片段在它的设置里填{ cline.apiProvider: openai-compatible, cline.openAiBaseUrl: https://taotoken.net/api, cline.openAiApiKey: sk-你的Key填这里, cline.openAiModelId: gpt-4o }这几份配置的核心就一句话baseUrl 统一指向https://taotoken.net/apiKey 只维护一份模型名按识别类型区分。4. Android 侧扫描识别请求从相机回调到 API 调用配置好了接下来是 Android 里真正发请求的部分。我沿用原来相机回调的结构但把识别方法换成走 TaoToken 的 HTTP 请求。先看相机回调这部分和你原来的写法基本一致只是把识别方法名换掉Override protected void onActivityResult(int requestCode, int resultCode, Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode REQUEST_CODE_CAMERA resultCode Activity.RESULT_OK) { if (data ! null) { String contentType data.getStringExtra(CameraActivity.KEY_CONTENT_TYPE); String filePath FileUtils.getSaveFile(getApplicationContext()).getAbsolutePath(); if (!TextUtils.isEmpty(contentType)) { if (CameraActivity.CONTENT_TYPE_ID_CARD_FRONT.equals(contentType)) { recognizeByTaoToken(idcard, filePath); } if (CameraActivity.CONTENT_TYPE_GENERAL.equals(contentType)) { recognizeByTaoToken(plate, filePath); } } } } }核心的识别方法把图片转 Base64 后拼多模态消息private void recognizeByTaoToken(String type, String filePath) { new Thread(() - { try { File file new File(filePath); byte[] bytes new byte[(int) file.length()]; FileInputStream fis new FileInputStream(file); fis.read(bytes); fis.close(); String base64 Base64.encodeToString(bytes, Base64.NO_WRAP); String prompt plate.equals(type) ? 识别这张图片中的车牌号码和车牌颜色返回JSON{\number\:\\,\color\:\\} : 识别这张身份证正面返回JSON{\name\:\\,\gender\:\\,\ethnic\:\\,\idNumber\:\\,\address\:\\}; JSONObject imageUrl new JSONObject(); imageUrl.put(url, data:image/jpeg;base64, base64); JSONObject textPart new JSONObject(); textPart.put(type, text); textPart.put(text, prompt); JSONObject imagePart new JSONObject(); imagePart.put(type, image_url); imagePart.put(image_url, imageUrl); JSONArray content new JSONArray(); content.put(textPart); content.put(imagePart); JSONObject message new JSONObject(); message.put(role, user); message.put(content, content); JSONArray messages new JSONArray(); messages.put(message); JSONObject body new JSONObject(); body.put(model, gpt-4o); body.put(messages, messages); body.put(max_tokens, 512); URL url new URL(BuildConfig.TAOTOKEN_BASE_URL /v1/chat/completions); HttpURLConnection conn (HttpURLConnection) url.openConnection(); conn.setRequestMethod(POST); conn.setRequestProperty(Content-Type, application/json); conn.setRequestProperty(Authorization, Bearer BuildConfig.TAOTOKEN_API_KEY); conn.setDoOutput(true); conn.setConnectTimeout(15000); conn.setReadTimeout(60000); OutputStream os conn.getOutputStream(); os.write(body.toString().getBytes(UTF-8)); os.flush(); os.close(); int code conn.getResponseCode(); InputStream is code 200 ? conn.getInputStream() : conn.getErrorStream(); BufferedReader reader new BufferedReader(new InputStreamReader(is, UTF-8)); StringBuilder sb new StringBuilder(); String line; while ((line reader.readLine()) ! null) { sb.append(line); } reader.close(); conn.disconnect(); final String result sb.toString(); runOnUiThread(() - mContent.setText(result)); } catch (Exception e) { Log.e(TaoTokenOCR, request failed, e); } }).start(); }BuildConfig.TAOTOKEN_BASE_URL和BuildConfig.TAOTOKEN_API_KEY在build.gradle里注入android { defaultConfig { buildConfigField String, TAOTOKEN_BASE_URL, \https://taotoken.net/api\ buildConfigField String, TAOTOKEN_API_KEY, \sk-你的Key填这里\ } }这样 Java 代码里不出现明文 Key切换环境也只改 gradle 一处。5. 验证请求与预期返回配置和代码都就位后做一次最小验证。我建议先用 curl 在电脑上跑一遍确认 Key 和模型没问题再去跑 Android。curl -X POST https://taotoken.net/api/v1/chat/completions \ -H Content-Type: application/json \ -H Authorization: Bearer sk-你的Key \ -d { model: gpt-4o, messages: [ { role: user, content: [ {type: text, text: 识别这张图片中的车牌号码和车牌颜色返回JSON}, {type: image_url, image_url: {url: data:image/jpeg;base64,/9j/4AAQ...}} ] } ], max_tokens: 512 }预期返回结构大致是这样{ id: chatcmpl-xxx, object: chat.completion, choices: [ { index: 0, message: { role: assistant, content: {\number\:\京A12345\,\color\:\蓝色\} }, finish_reason: stop } ], usage: { prompt_tokens: 820, completion_tokens: 24, total_tokens: 844 } }拿到这个返回说明通道是通的。Android 侧把choices[0].message.content解析出来再按你原来的 JSON 解析逻辑取number和color就行。身份证识别同理只是 prompt 换成身份证字段返回的 content 里是姓名、性别、民族、身份证号、住址。实测下来一张压缩到 150KB 左右的车牌图从发出请求到拿到结果大概 2 到 4 秒取决于网络。身份证正面因为字段多稍微慢一点但也在可接受范围。6. 本篇常见错排查第一个坑是 Base64 前缀漏了。image_url的 url 字段必须是data:image/jpeg;base64,开头少了这个前缀服务端会当成普通 URL 去请求直接报错。我一开始就是只传了 Base64 字符串排查了半天。第二个坑是图片太大。Android 相机默认拍出来的图可能好几 MB直接 Base64 编码后请求体会超过限制返回 413 或者超时。解决办法是在拍照后先压缩或者用BitmapFactory采样后再编码。我一般把长边压到 1280 像素质量 40出来的图 100 到 200KB。第三个坑是 Key 权限。如果你在控制台创建 Key 的时候限制了模型范围而请求里用的模型不在范围内会返回 403。去 API Keys 页面确认一下这个 Key 允许的模型列表。第四个坑是并发。Android 里如果在主线程发请求会直接崩必须放到子线程。上面代码里用了new Thread如果你用 OkHttp 或者 Retrofit记得回调里切回主线程更新 UI。第五个坑是返回内容不是纯 JSON。模型有时候会在 JSON 外面包一层说明文字比如「识别结果如下{...}」。解析前先做一次字符串截取找到第一个{和最后一个}之间的内容再解析能省很多事。排障相关的入口放在这里API Keys 页面 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 接入文档 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。如果你在 Android 里做长期编码和识别混合的场景Coding Plan 会更合适https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 。想先手动验证模型对车牌和身份证的识别效果直接去模型对话页面传图试https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentchatutm_campaignrewrite 。最后补一个实用技巧把车牌和身份证的 prompt 模板抽成常量放在settings.json里Android 侧读配置拼 prompt这样以后换识别字段或者调整返回格式不用改 Java 代码改配置就行。
阅读完成 · 觉得有帮助?
咨询建站