Android开发新手求助:整合Azure认知服务多API及名人模型问题
解决Azure认知服务名人模型整合的问题
Hi there! Let's break down the issues in your code and fix them step by step — I've spotted a few key problems that are causing your post-execution errors.
核心问题分析
1. 输入流重复使用导致API调用失败
ByteArrayInputStream在被第一次读取后,内部指针会移动到流的末尾。你在调用describe()后,又把同一个流传给analyzeImageInDomain(),这时候流里已经没有数据可以读取了,直接导致第二次API调用失败。
2. 返回数据格式错误,解析失败
你把两个独立的JSON结果塞进HashMap再转成字符串,这个混合后的字符串既不是合法的AnalysisResult格式,也不是AnalysisInDomainResult格式。在onPostExecute里用Gson去解析这种混乱的字符串,必然会抛出解析异常。
3. 异常传递与类型处理问题
- 你的
onPostExecute里用到了e变量,但没有看到在doInBackground中正确捕获并保存异常; - 名人检测结果中的
confidence是数值类型,你用getAsString()读取会触发类型转换错误。
修改后的完整代码示例
第一步:创建结果封装类
先定义一个简单的POJO类,用来同时封装普通图像描述和名人检测结果:
public class CombinedVisionResult { public AnalysisResult descriptionResult; public AnalysisInDomainResult celebrityResult; }
第二步:修正process方法
private CombinedVisionResult process() throws VisionServiceException, IOException { String model = "celebrities"; // 先把Bitmap转成byte数组,方便多次生成新的输入流 ByteArrayOutputStream output = new ByteArrayOutputStream(); bitmapPicture.compress(Bitmap.CompressFormat.JPEG, 100, output); byte[] imageBytes = output.toByteArray(); // 调用普通描述API:用新的输入流 ByteArrayInputStream describeStream = new ByteArrayInputStream(imageBytes); AnalysisResult descResult = this.client.describe(describeStream, 1); // 调用名人检测API:重新生成输入流 ByteArrayInputStream celebStream = new ByteArrayInputStream(imageBytes); AnalysisInDomainResult celebResult = this.client.analyzeImageInDomain(celebStream, model); // 封装结果返回 CombinedVisionResult combinedResult = new CombinedVisionResult(); combinedResult.descriptionResult = descResult; combinedResult.celebrityResult = celebResult; return combinedResult; }
第三步:修正AsyncTask的执行逻辑
调整AsyncTask的泛型参数,直接返回封装后的结果,并正确处理异常:
// 假设你的AsyncTask类定义如下 private class VisionTask extends AsyncTask<Void, Void, CombinedVisionResult> { private Exception taskException; @Override protected CombinedVisionResult doInBackground(Void... voids) { try { return process(); } catch (VisionServiceException | IOException ex) { taskException = ex; return null; } } @Override protected void onPostExecute(CombinedVisionResult combinedResult) { super.onPostExecute(combinedResult); mEditText.setText(""); if (taskException != null) { mEditText.setText("Error: " + taskException.getMessage()); taskException = null; } else if (combinedResult != null) { AnalysisResult descResult = combinedResult.descriptionResult; AnalysisInDomainResult celebResult = combinedResult.celebrityResult; // 优先处理名人检测结果 if(celebResult != null && celebResult.result != null && celebResult.result.has("celebrities")){ JsonArray detectedCelebs = celebResult.result.get("celebrities").getAsJsonArray(); mEditText.append("Celebrities detected: "+ detectedCelebs.size()+"\n"); for(JsonElement celebElement: detectedCelebs) { JsonObject celeb = celebElement.getAsJsonObject(); String name = celeb.get("name").getAsString(); // 正确读取数值类型的confidence double confidence = celeb.get("confidence").getAsDouble(); mEditText.append("Name: "+ name +", score: " + String.format("%.2f", confidence) +"\n"); } } else { // 没有检测到名人时,显示普通描述结果 for (Caption caption: descResult.description.captions) { mEditText.append("You're seeing " + caption.text + ", confidence: " + String.format("%.2f", caption.confidence) + "\n"); } } mEditText.setSelection(0); } } }
额外注意事项
- 确保你的Azure账户已经开通了Computer Vision服务的名人检测功能,并且API密钥和端点配置正确;
- 可以在API调用前添加日志,打印请求的状态码和响应内容,方便排查后续问题;
- 处理Bitmap时注意内存占用,避免OOM问题。
内容的提问来源于stack exchange,提问作者rann02
相关产品推荐
相关产品推荐

