使用OkHttp调用MindeeAPI发送图片无法获取JSON响应,求排查
无法获取Mindee API响应的排查方向及解决办法
以下是针对你代码和流程的几个核心问题点,按优先级排查:
1. UI更新必须在主线程执行
OkHttp的onResponse/onFailure回调是在子线程中执行的,直接调用txtItems.setText()会触发UI线程异常——要么文本不更新,要么程序直接崩溃。
修改方式:用runOnUiThread切换到主线程更新UI:
@Override public void onFailure(Call call, IOException e) { e.printStackTrace(); Log.e("MindeeAPI", "API call failed: " + e.getMessage()); // 切回主线程更新文本 runOnUiThread(() -> txtItems.setText(e.getMessage())); } @Override public void onResponse(Call call, Response response) throws IOException { final String responseBody = response.body().string(); Log.d("MindeeAPI", "Response Code: " + response.code()); Log.d("MindeeAPI", "Response Body: " + responseBody); // 同样切主线程更新UI runOnUiThread(() -> txtItems.setText(responseBody)); }
2. 图片文件可能未创建成功
你的convertBitmapToFile方法如果抛出IOException,会直接返回null,但调用API时没有做判空处理——相当于给API传了无效文件,请求自然出问题。
修改方式:先检查文件有效性,再调用API:
File imageFile = convertBitmapToFile(imageBitmap); // 判空+检查文件是否存在 if (imageFile == null || !imageFile.exists()) { Log.e("MindeeAPI", "图片文件创建失败"); runOnUiThread(() -> txtItems.setText("图片文件创建失败")); return; } // 文件有效再调用API MindeeApiManager.callMindeeAPI(imageFile, apiKey, ...);
同时优化convertBitmapToFile方法,确保文件能正确写入:
private File convertBitmapToFile(Bitmap bitmap) { File imageFile = null; try { File cacheDir = getCacheDir(); imageFile = new File(cacheDir, "temp_image.jpg"); // 确保父目录存在 if (!imageFile.getParentFile().exists()) { imageFile.getParentFile().mkdirs(); } FileOutputStream fos = new FileOutputStream(imageFile); // 压缩质量设为80即可,既保证清晰度又减小文件大小 boolean compressSuccess = bitmap.compress(Bitmap.CompressFormat.JPEG, 80, fos); if (!compressSuccess) { Log.e("FileConvert", "Bitmap压缩失败"); return null; } fos.flush(); fos.close(); } catch (IOException e) { Log.e("FileConvert", "创建文件出错: " + e.getMessage()); e.printStackTrace(); } return imageFile; }
3. 相机返回的是缩略图,API无法识别
默认相机Intent的data字段只返回低分辨率缩略图,Mindee API对图片分辨率有要求,这种小图可能导致API无法识别,返回无效响应。
修改方式:让相机直接把完整图片保存到指定文件,无需转换缩略图:
// 定义成员变量 private File photoFile; private static final int REQUEST_IMAGE_CAPTURE = 1; // 启动相机的方法 private void takePicture() { Intent takePicIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); if (takePicIntent.resolveActivity(getPackageManager()) == null) { return; } // 创建要保存图片的文件 try { photoFile = createImageFile(); } catch (IOException e) { Log.e("Camera", "创建图片文件失败: " + e.getMessage()); return; } if (photoFile != null) { // 用FileProvider获取Uri(Android 7+强制要求) Uri photoUri = FileProvider.getUriForFile(this, "com.your.app.fileprovider", // 替换成你的FileProvider授权名 photoFile); takePicIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri); startActivityForResult(takePicIntent, REQUEST_IMAGE_CAPTURE); } } // 创建图片文件的工具方法 private File createImageFile() throws IOException { String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.CHINA).format(new Date()); String fileName = "JPEG_" + timeStamp + "_"; File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES); return File.createTempFile(fileName, ".jpg", storageDir); } // 修改onActivityResult逻辑 @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == RESULT_OK && requestCode == REQUEST_IMAGE_CAPTURE) { // 直接用之前创建的完整图片文件 if (photoFile != null && photoFile.exists()) { MindeeApiManager.callMindeeAPI(photoFile, apiKey, new Callback() { // 回调逻辑同上,记得切主线程更新UI }); } else { Log.e("Camera", "找不到拍摄的图片文件"); } } }
注意:需要在AndroidManifest.xml中配置FileProvider,否则会出现权限问题。
4. 未处理API的错误响应
onResponse被调用不代表请求成功——比如API密钥错误返回401、图片格式错误返回400,这些情况的响应体可能不是预期的JSON,甚至为空。
修改方式:先判断响应是否成功,再处理内容:
@Override public void onResponse(Call call, Response response) throws IOException { if (!response.isSuccessful()) { Log.e("MindeeAPI", "请求失败,状态码:" + response.code()); String errorBody = response.body() != null ? response.body().string() : "无错误信息"; Log.e("MindeeAPI", "错误内容:" + errorBody); runOnUiThread(() -> txtItems.setText("请求失败,状态码:" + response.code())); return; } // 请求成功才处理响应体 final String responseBody = response.body().string(); Log.d("MindeeAPI", "响应状态码:" + response.code()); Log.d("MindeeAPI", "响应内容:" + responseBody); runOnUiThread(() -> txtItems.setText(responseBody)); }
5. 其他基础检查
- 确认
AndroidManifest.xml中添加了网络权限:<uses-permission android:name="android.permission.INTERNET" /> - 检查API密钥是否正确,可通过Postman等工具单独测试API,确认能正常返回响应
- 确认Mindee API的URL是最新版本(比如v5版本是否仍在维护)
内容的提问来源于stack exchange,提问作者Jakov Spirovski
相关产品推荐
相关产品推荐

