Skip to content

Android版

集成 Camera SDK

IMPORTANT Android集成时,根据Google Play政策 要求,用户下载的压缩后 APK 大小不能超过 100 MB。如果超过 100 MB,应改为 Android App Bundle 上传应用,这种方式允许的压缩后下载大小上限为 200 MB。

1. SDK 下载

SDK: Android_SDK_v3.1.11Java Latest

SDK 示例: 安卓SDK示例代码 示例安装包  Latest

版本变更: Changelog New

历史版本: All Releases

2. 引入SDK的aar文件

解压SDK压缩包,并将 clobotics-stitching-camera-*.*.*.aarclobotics-image-quality-evaluator-*.*.*.aar 这两个文件放到项目的/app/libs下。

3. 添加依赖

在项目中的build.gradle (Module:app /app/build.gradle)文件,添加以下依赖项

groovy
implementation files('libs/clobotics-stitching-camera-*.*.*.aar')  
implementation files('libs/clobotics-image-quality-evaluator-*.*.*.aar')  

implementation 'com.google.code.gson:gson:2.8.6'  
implementation 'com.github.bumptech.glide:glide:4.12.0'

4. 权限申明配置

AndroidManifest.xml文件中声明以下权限。

xml
<!-- 网络 -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- 读取文件权限 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> 
<!-- 写入文件权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- 相机权限 -->
<uses-permission android:name="android.permission.CAMERA" />

为了确保应用能正常的使用SDK来拍摄,必须声明上述权限。

5.混淆规则配置

如果在 app/build.gradle 中开启了 minifyEnabled true,需要在 proguard-rules.pro 文件中添加以下配置(针对 JNI 常见问题,特别是 JNI_OnLoad 失败导致的 UnsatisfiedLinkError):

proguard
# Keep all classes and classes with native methods in Clobotics Camera SDK's package
-keep class com.clobotics.retail.stitch.R$* { *; }
-keep class com.clobotics.retail.stitch.**{*;}
-keep class com.clobotics.retail.stitch.CloboticsCamera{*;}
-keep class com.clobotics.retail.stitch.StitchingCameraCallback {*;}

-keep class com.clobotics.cvml.** { *; }
-keepclasseswithmembernames class com.clobotics.cvml.$* {
    native <methods>;
}

-keep class com.clobotics.retail.zhiwei.** { *; }
-keepclasseswithmembernames class com.clobotics.retail.zhiwei.$* {
    native <methods>;
}

SDK 回调示例说明

调用步骤请参照以下概要说明。要了解更详细的交互细节,请参考 安卓SDK示例代码

1. 初始化回调监听

java
// 示例代码: 单图信息存储,可以根据业务需求自行调整
List<Object[]> imagesCached = new ArrayList<>(); 

CloboticsCamera.getInstance().setStitchingCameraCallback(
    new StitchingCameraCallback() {
        /**
          * 单张照片拍摄完成后的回调
          * @param imagePath 图片保存路径
          * @param imageIndex 序号,本次拍照的第几张图片
          * @param imageId 图片唯一编码 UUID
          * @param pair 与上一张拼图的区域重叠信息(只有经典拼图拍摄方式才会有此信息,视频拼图拍摄模式 为空),用于后续拼接stitchingInfo 
          * */
         @Override
         public void takeSinglePhotoCallback(String imagePath, int imageIndex, String imageId, String pair) {
            // 示例代码: 存储单图信息,可以根据业务需求自行调整 Images Cache Manager
            imagesCached.add(new Object[]{imagePath, imageIndex, imageId, pair}); 

            // 按imageIndex升序对imagesCached进行排序
            Comparator<Object[]> comparator = Comparator.comparingInt(arr -> (int) arr[1]);
            Collections.sort(imagesCached, comparator);
         }

        /**
          * 结束拼图拍照任务回调
          * 
          * @param stitchingPath 拼图本地路径
          * @param stitchingInfo 拼图信息
          *    stitchingInfoVersion 0(经典拼图拍摄模式)、1(视频拼图拍摄模式)、3(丝融拼图拍摄模式)
          *    info 拼图信息(视频拼图拍摄模式 才会有此信息)
          * */
         @Override
         public void endTakePhotoCallback(String stitchingPath, JSONObject stitchingInfo) {
             // 结束拍摄时可能存在以下两种情况
             // 情况1: imagesCached.size() == 1,不需要向服务器发起拼图任务请求,采用单图识别返回的'task_id'去获取识别结果
             // 情况2: imagesCached.size() > 1,需要向服务器发起[创建拼图任务]的请求
            int stitchingCode = stitchingInfo.has("stitchingInfoVersion") ? stitchingInfo.getInt("stitchingInfoVersion") : 0;
            if (stitchingCode == 0) {
                // 请参考StitchingInfo暂存管理中经典拼图拍摄模式
            }
            if (stitchingCode == 1) {
                // 请参考StitchingInfo暂存管理中视频拼图拍摄模式
            }
            if (stitchingCode == 3) {
                // 请参考StitchingInfo暂存管理中丝融拼图拍摄模式
            }
         }

        /**
          * 取消拍照(点击返回或手势返回)
          * 
          * @param imagesPath 需要清除的单图本地路径数组
          * */
        @Override
        public void cancelTakePhotoCallback(String imagesPath) {
            // 自定义逻辑
        }
    }
);

在配置 StitchingCameraCallback 时,有几个需要关注的回调:

  • delPhotoCallback: 用户在拍摄过程中取消拍摄时会触发该回调。处理该回调逻辑至关重要,尤其是在拼接模式下,以防止出现错误的拼接信息。

  • logCallback: 记录 Camera SDK 的输出日志,在拍照的关键节点会触发日志记录,可根据需要自定义日志记录的回调。

  • initFailCallback: Camera SDK 初始化失败时的回调。在该回调中,务必重试初始化的逻辑。

java
/**
 * 用户撤销拍摄或切换拍摄模式时删除的图片
 * @param imagesPath 图片路径
 * */
@Override
public void delPhotoCallback(String imagesPath) {
    // 可以根据业务需求自行调整 
}

/**
 * 日志消息回调(拍照的关键节点会触发日志记录,可根据需要自定义日志记录的回调)
 * 
 * @param tag  拍照流程节点,部分列出如下:
 *     SupportPreViewSize 支持图片拍摄的分辨率,与当前设备内存信息
 *     isDeviceSupportVideoStitching 硬件条件是否支持视频拼图拍摄模式拼图拍摄模式
 *     Button_ISO: Camera1 ISO 曝光度设置
 *     Button_Torch:Camera1 手电筒点击
 *     Button_ISO2:Camera2 曝光度设置
 *     Button_Torch2:Camera2 手电筒点击
 *     Button_Take: 拍照按钮点击
 *     Button_Cancel:取消按钮点击
 *     Button_Finish:结束拍照按钮点击
 *     Button_Rollback:回退拍照按钮点击
 * @param message
 */
@Override
public void logCallback(String tag, String message) {
    // 可以根据业务需求自行调整 
}

/**
 * SDK 初始化失败
 * @param message 失败原因
 * */
@Override
public void initFailCallback(String message) {
    // 可以根据业务需求自行调整    
}

2. 初始化相机配置 Camera Config,并启用相机实例

有关 Camera Config 的详细配置,请参阅:配置 Camera Config。然后,使用以下代码启用相机实例。

java
/**
 *
 * @param activity 
 * @param jsonString CameraConfig类 的 json 字符串,具体属性请参考使用参数说明
 * @param requestCode 自定义流程结束返回码,用于onActivityResult判断流程 例如 0x001
 */
CloboticsCamera.getInstance().startCameraStitching(Activity activity, String jsonString, int requestCode);

3. 异常处理

异常通常由系统回退事件或不正常退出触发。

java
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
   super.onActivityResult(requestCode, resultCode, data);
   if (resultCode != RESULT_OK) { 
      // 非正常结束,删除 Task 所有数据
     imagesCached.clear();
   }
}

4. StitchingInfo 的管理

图像拼接的关键是存储图像拼接信息的 StitchingInfo。当调用 OpenAPI 中的 创建拼图任务时,如果不能正确传递相关的StitchingInfo,任务可能会失败。请仔细阅读 StitchingInfo 管理,了解详细信息。

配置 CameraConfig

  • 有关 CameraConfig 的所有属性,请参阅 CameraConfig相关属性

  • 关于启用SDK方法startCameraStitching的调用方式,我们实现了接受CameraConfig 或者Json格式字符串两种方法,如下所示:

java
public void startCameraStitching(Activity activity, CameraConfig mCameraConfig, int requestCode)
public void startCameraStitching(Activity activity, String configJsonString, int requestCode)

1. 两种设置方式

我们实现了SDK启用方法startCameraStitching 当调用方法 CloboticsCamera.getInstance().startCameraStitching(Activity activity, String configJsonString, int requestCode)时,第二个参数是从指定的 JSONObject 转换而来的原始字符串。 以下两种方式均可设置:

  • 方案 1:使用 com.clobotics.retail.stitch.utils.CameraConfig 设置 CameraConfig,将其转换为 JSONObject,然后再转为字符串。

  • 方案 2: 直接使用具有正确 JSON 格式的原始字符串。

java
/**
 * 最简配置,其他参数启用默认值
 * 
 */
CloboticsCamera.getInstance().startCameraStitching(..., configJsonString, ...);

2. 拼图拍摄配置

经典拼图模式

  • 方案 1: 使用类 CameraConfig
java
import com.clobotics.retail.stitch.utils.CameraConfig;
import com.google.gson.Gson;

CameraConfig config = new CameraConfig();
// 1 - 视频拼图拍摄模式 2 - 经典拼图拍摄模式    3 - 丝融拼图拍摄模式
config.setUserSelectedStitchingMode(2);   
config.setMaskStyle(2);   //  可缺省不设置  
config.setStitchingMinCount(2);
config.setStitchingMaxCount(4);

String configJsonString = new Gson().toJson(config);
  • 方案 2: 使用 JSON 格式的原始字符串
java
String configJsonString = "{\"userSelectedStitchingMode\": 2, \"maskStyle\": 2, \"stitchingMinCount\": 2, \"stitchingMaxCount\": 4}";

然后调用 startCameraStitching():

注意:

  • 对于参数 stitchingMinCountstitchingMaxCount,可以根据需求设置为适当的值

视频拼图模式

  • 方案 1: 使用类 CameraConfig
java
import com.clobotics.retail.stitch.utils.CameraConfig;
import com.google.gson.Gson;

CameraConfig config = new CameraConfig();
// 1 - 视频拼图拍摄模式 2 - 经典拼图拍摄模式  3 - 丝融拼图拍摄模式
config.setUserSelectedStitchingMode(1);   
config.setStitchingMinCount(2);
config.setStitchingMaxCount(4);

String configJsonString = new Gson().toJson(config);
  • 方案 2: 使用 JSON 格式的原始字符串
java
String configJsonString = "{\"userSelectedStitchingMode\": 1, \"stitchingMinCount\": 2, \"stitchingMaxCount\": 4}";

然后调用 startCameraStitching()

注意:

  • 对于参数 stitchingMinCountstitchingMaxCount,可以根据需求设置为适当的值

丝融拼图模式

  • 方案 1: 使用类 CameraConfig
java
import com.clobotics.retail.stitch.utils.CameraConfig;
import com.google.gson.Gson;

// ...

CameraConfig config = new CameraConfig();

// 1 - 视频拼图拍摄模式 2 - 经典拼图拍摄模式  3 - 丝融拼图拍摄模式
config.setUserSelectedStitchingMode(3);   
config.setStitchingMinCount(2);
config.setMaxRecordingSecs(45);

String configJsonString = new Gson().toJson(config);
  • 方案 2: 使用 JSON 格式的原始字符串
java
String configJsonString = "{\"userSelectedStitchingMode\": 3, \"stitchingMinCount\": 2, \"maxRecordingSecs\": 45}";

然后调用 startCameraStitching()

注意:

  • 对于参数 stitchingMinCountmaxRecordingSecs,可以根据需求设置为适当的值

3. 单图拍摄配置

经典单图模式

在该模式下,用户仍可以同时拍摄多张图像,区别于拼图拍摄,虽然拍摄了多张图像,但 Camera SDK 不会提供 StitchingInfo

  • 方案 1: 使用类 CameraConfig
java
import com.clobotics.retail.stitch.utils.CameraConfig;
import com.google.gson.Gson;


CameraConfig config = new CameraConfig();
config.setUserSelectedStitchingMode(2);  
config.setMaskStyle(1);
  • 方案 2: 使用 JSON 格式的原始字符串
java
String configJsonString = "{\"userSelectedStitchingMode\": 2, \"maskStyle\": 1}";

然后调用 startCameraStitching()

注意:

  • 对于参数 stitchingMinCountstitchingMaxCount,可以根据需求设置为适当的值

纯价签模式

该模式为需要拍摄价格标签的场景引入了导向遮罩。在该模式下,用户可以同时拍摄多张图像,而无需退出摄像机。不同于经典拼图模式和视频拼图拍摄模式 模式,虽然拍摄了多张图像,但 Camera SDK 不会提供 StitchingInfo,也无需管理 StitchingInfo

  • 方案 1: 使用类 CameraConfig
java
import com.clobotics.retail.stitch.utils.CameraConfig;
import com.google.gson.Gson;

CameraConfig config = new CameraConfig();
// 纯价签拍照模式,一次拍摄一张图片配置如下,其他参数启用默认值
config.setUserSelectedStitchingMode(2);     
config.setMaskStyle(3);
config.setStitchingMinCount(1);
config.setStitchingMaxCount(1);

String configJsonString = new Gson().toJson(config);
  • 方案 2: 使用 JSON 格式的原始字符串
java
String configJsonString = "{\"userSelectedStitchingMode\": 2, \"maskStyle\": 3, \"stitchingMinCount\": 1, \"stitchingMaxCount\": 1}";

然后调用 startCameraStitching()

注意:

  • 该模式下,如果想拍摄多张图像,可以更新参数 stitchingMinCountstitchingMaxCount的值。

产品价签模式

该模式为需要拍摄产品和价格标签在陈列的场景引入了导向遮罩。在该模式下,用户可以同时拍摄多张图像,而无需退出摄像机。不同于经典拼图模式和视频拼图拍摄模式 模式的拼图模式,虽然拍摄了多张图像,但 Camera SDK 不会提供 StitchingInfo,也无需管理 StitchingInfo

  • 方案 1: 使用类 CameraConfig
java
import com.clobotics.retail.stitch.utils.CameraConfig;
import com.google.gson.Gson;

CameraConfig config = new CameraConfig();
// 产品价签拍照模式,一次拍摄一张图片配置如下,其他参数启用默认值
config.setUserSelectedStitchingMode(2);     
config.setMaskStyle(4);
config.setStitchingMinCount(1);
config.setStitchingMaxCount(1);

String configJsonString = new Gson().toJson(config);
  • 方案 2: 使用 JSON 格式的原始字符串
java
String configJsonString = "{\"userSelectedStitchingMode\": 2, \"maskStyle\": 4, \"stitchingMinCount\": 1, \"stitchingMaxCount\": 1}";

然后调用 startCameraStitching()

注意:

  • 该模式下,如果想拍摄多张图像,可以更新参数 stitchingMinCountstitchingMaxCount的值。

多语言支持

支持的语言包括:

语言参数值
英文Locale.ENGLISH
简体中文Locale.CHINESE
繁体中文new Locale("zh", "Hant")
泰语new Locale("th")
缅甸语new Locale("my")
法语new Locale("fr")
意大利语new Locale("it")
葡萄牙语new Locale("pt")
西班牙语new Locale("es")
  • 方案 1: 使用类 CameraConfig
java
import java.util.Locale;

CameraConfig config = new CameraConfig();
config.setLanguage(Locale.ENGLISH.toString());

String configJsonString = new Gson().toJson(config);
  • 方案 2: 使用 JSON 格式的原始字符串
java
String lang = Locale.ENGLISH.toString();
String configJsonString = String.format("{\"language\": \"%s\"}", lang);

CameraConfig 相关属性

功能参数说明类型默认值版本
多语言支持language设置显示的语言,支持的语言string跟随系统3.1.6
拍摄模式userSelectedStitchingMode启用时的默认拍摄模式, 1为视频拼图模式,2为经典拍摄(配合maskStyle使用可区分配置拼图拍摄、单图拍摄、价签拍摄),3为丝融拼图模式
注: 配置为1时,需要SDK判断设备硬件支持视频拼图拍摄模式才生效
int23.0.0
maskStyle启用拍摄时的遮罩引导框风格:1为单图拍摄;3为纯价签引导框;4为产品价签引导框
注: 配置为1、3或4时,需要userSelectedStitchingMode = 2才生效。
int03.1.5
isFirstUse首次启动,是否弹出拍摄操作引导图 booleanfalse3.0.0
allowRoll允许用户沿着 前后 方向旋转的角度,取值范围:0~90°float453.0.0
allowPitch允许用户沿着 左右 方向旋转的角度,取值范围:0~90°float453.0.0
stitchingMinCount本次最小允许拍摄张数,0为不限制int03.0.0
stitchingMaxCount本次允许最大拍摄张数,0为不限制int03.0.0
maxRecordingSecs丝融拍摄最大时长限制(单位:秒)
注: userSelectedStitchingMode = 3时才生效。
int03.1.10
enableGEOLocator启用拍摄时照片EXIF是否写入经纬度信息 booleanfalse3.1.4
图片质量检测isUseLargeAngleModel是否启用大角度模型检测
注: 经典拼图模式或丝融拼图模式时(userSelectedStitchingMode = 2 && maskStyle = 2 || userSelectedStitchingMode = 3)才生效
booleanfalse3.1.11
allowLargeAngle大角度模型允许的最大角度,取值范围:0~90°
注: isUseLargeAngleModel=true时才生效
float20.03.1.10
isUseSkuSizeModel是否启用 SKU图片中大小占比检测
注: 经典拼图模式时(userSelectedStitchingMode = 2 && maskStyle = 2)才生效
booleanfalse3.0.0
minSkuSizeRatioSKU大小检测最小比例,取值范围:0.0~1.0
注: isUseSkuSizeModel=true时才生效
float0.33.1.10

StitchingInfo 管理

在经典拼图模式下

如SDK示例代码所示,以下逻辑必须加入到 endTakePhotoCallback(String stitchingPath, JSONObject stitchingInfo) 回调中。

java
/** 
 * 1.global variable Array imageCached definition: 
 *  List<Object[]> imagesCached = new ArrayList<>(); 
 * 2.add image to Array imageCached in function takePhotoCallback
 *  imagesCached.add(new Object[]{imagePath, imageIndex, ...}); 
 * 3.only when imagesCached.size() > 1, stitchingInfo is needed for stitching task for recognition
 * */

JSONArray pairArray = new JSONArray();
// Object[] image = [imagePath, imageIndex, imageId, pair, taskId]
// image's pair info starts from image(i = 1), because image(i=0) pair info is empty
for (int i = 1; i < imagesCached.size(); i++) {
    pairArray.put(new JSONObject(imagesCached.get(i)[3].toString()));
}
stitchingInfo.put("pair", pairArray);

JSONObject jsonObject = new JSONObject();
jsonObject.put("stitchingInfo", stitchingInfo);
String uploadStitchingInfo = jsonObject.toString();

在视频拼图模式下

以下逻辑也必须加入到 endTakePhotoCallback(String stitchingPath, JSONObject stitchingInfo) 回调中。

java
JSONObject jsonObject = new JSONObject();
jsonObject.put("stitchingInfo", new JSONObject(stitchingInfo.getString("info")));
String uploadStitchingInfo = jsonObject.toString();

在丝融拼图模式下

以下逻辑也必须加入到 endTakePhotoCallback(String stitchingPath, JSONObject stitchingInfo) 回调中。

java
JSONObject jsonObject = new JSONObject();
jsonObject.put("stitchingInfo", new JSONObject(stitchingInfo.getString("info")));
String uploadStitchingInfo = jsonObject.toString();

拼图模式下统一管理 StitchingInfo

如果需要在 endTakePhotoCallback(String stitchingPath, JSONObject stitchingInfo) 回调中共同处理 StitchingInfo,请参照以下代码

java
@Override
public void endTakePhotoCallback(String stitchingPath, JSONObject stitchingInfo) {
    super.endTakePhotoCallback(stitchingPath, stitchingInfo);
    print("end:"+stitchingInfo.toString()+":"+groupTaskId+":"+stitchingPath);
    try {
        JSONObject jsonObject = new JSONObject();
        int stitchingInfoVersion = stitchingInfo.has("stitchingInfoVersion") ? stitchingInfo.getInt("stitchingInfoVersion") : 0;
        if (stitchingInfoVersion == 1 || stitchingInfoVersion == 3) { // 视频拼图或丝融拼图拍摄模式
            jsonObject.put("stitchingInfo", new JSONObject(stitchingInfo.getString("info")));
        } else { // 经典拼图模式
            JSONArray pairArray = new JSONArray();
            // Object[] image = [imagePath, imageIndex, imageId, pair, taskId]
            // image's pair info starts from image(i = 1), because image(i=0) pair info is empty
            for (int i = 1; i < images.size(); i++) {
                Object[] image = images.get(i);
                pairArray.put(new JSONObject(image[3].toString()));
            }
            stitchingInfo.put("pair", pairArray);
            jsonObject.put("stitchingInfo", stitchingInfo);
        }
        // 被用于 OpenAPI 的 [创建拼图任务] https://retail-doc.clobotics.com/cn/open-api/api/ir-api#create-stitching-picture-task
        String uploadStitchingInfo = jsonObject.toString();
        print(uploadStitchingInfo);
    } catch (JSONException e) {
        e.printStackTrace();
    }
}

注意:

版本变更

如果需要下载更多历史版本,请参阅 Releases

模块变更项版本号
< 3.1.113.1.11
配置参数isUseLargeAngleModel
变动:新增生效范围
仅在经典拼图模式userSelectedStitchingMode = 2 && maskStyle = 2配置下生效新增支持丝融拼图模式 userSelectedStitchingMode = 3 时生效
< 3.1.103.1.10
配置参数userSelectedStitchingMode
变动:新增枚举值
可选: 1|2可选: 1|2|3
支持配置开启丝融拼图模式
maxRecordingSecs
变动:新增
-支持配置拍摄最大时长(秒)
注: 配置时,需要userSelectedStitchingMode = 3才生效。
allowLargeAngle
变动:新增
-支持设置大角度模型允许的最大角度,取值范围:0~90°
minSkuSizeRatio
变动:新增
-支持设置SKU大小检测最小比例,取值范围:0.0~1.0
< 3.1.83.1.8
依赖变动:删除依赖声明需包含implementation 'fr.avianey.com.viewpagerindicator:library:2.4.1@aar'无需包含
兼容性变动:对齐-支持 16 KB 的页面大小
< 3.1.73.1.7
回调监听cancelTakePhotoCallback
变动:新增
-public void cancelTakePhotoCallback(String imagesPath)
< 3.1.63.1.6
配置参数language
变动:新增
-支持设置相机UI界面显示的语言
< 3.1.53.1.5
配置参数maskStyle
变动:新增枚举值
可选: 3可选: 3 | 4
支持配置产品价签模式
注: 配置为4时,需要userSelectedStitchingMode = 2才生效。
< 3.1.43.1.4
配置参数enableGEOLocator
变动:新增
-支持将拍照时的经纬度信息写入图片的EXIF信息中
< 3.1.23.1.2
类引用CameraConfig
变动:路径调整
import com.clobotics.retail.stitch.utils.CameraConfig;import com.clobotics.retail.stitch.CameraConfig;
3.0.03.1.0
回调监听takePhotoCallback -> takeSinglePhotoCallback
变动:函数名修改、传参
public void takePhotoCallback(String imagePath, int imageIndex, String imageId, String pair, int taskId) public void takeSinglePhotoCallback(String imagePath, int imageIndex, String imageId, String pair)
endTakePhotoCallback
变动:传参
public void endTakePhotoCallback(JSONObject stitchingInfo, int taskId, String groupTaskId, String stitchingPath)public void endTakePhotoCallback(String stitchingPath, JSONObject stitchingInfo)
startTakePhotoCallback
变动:删除
public int startTakePhotoCallback(String groupTaskId, int planId, int sceneId)-
配置参数maskStyle
变动:新增
-可选: 3
注: 支持开启纯价签模式,配置为3时,需要userSelectedStitchingMode = 2才生效。