更新时间:2023-05-22 06:38:30下载pdf
涂鸦智能安卓版摄像机(IP Camera,简称 IPC)SDK 是基于智能生活 App SDK 开发而成。通过移动应用控制物理网设备是常见的使用场景,但由于设备的品类丰富,增大了应用开发难度。因此 智能生活 App SDK 提供了常见的垂直品类 SDK,例如 IPC SDK,将网络摄像机设备特有的功能抽离,提供了与其通讯的接口封装,加速应用开发过程。
您可以通过本教程,在一小时内快速开发一款自己的 IoT App,并实现如下功能:
您可以点击下方按钮下载 Sample 查看本教程中的示例代码。本次教程按功能模块进行分类,您可以快速找到对应的代码参考学习。
学习完本教程,结合一定的面板开发您可以创建一个类似以下安卓 App 的 Demo。
在您开始本教程前,请先确保您已经 :
由于 IPC SDK 依赖于 智能生活 App SDK,您需要首先实现如创建账号、添加家庭的操作后才能借助 IPC SDK 实现摄像机相关功能。详情请参考 智能生活 App SDK 快速入门教程。
由涂鸦赋能的智能摄像机支持智能生活 App SDK 中的所有 配网方式,例如 Wi-Fi 热点配网和蓝牙配网等。此外,涂鸦为 IPC 设备提供了独有的扫描二维码配网功能,但如果 IP 摄像机设备无法扫码,可以优先尝试 Wi-Fi 快连方式。本篇教程文档主要讲解扫描二维码配网。
和 Wi-Fi 快连和 Wi-Fi 热点模式类似,开始配网之前,SDK 需要在手机已联网的状态下从涂鸦 获取配网 Token,然后才可以开始配网。
配网 Token 的有效期为 10 分钟,且配置成功后就会失效,再次配网需要重新获取。获取 Token 需要上传当前的 homeId
,因此您需要确保用户处于登录状态,并至少创建了一个家庭。
TuyaHomeSdk.getActivatorInstance().getActivatorToken(homeId,
new ITuyaActivatorGetToken() {
@Override
public void onSuccess(String token) {
}
@Override
public void onFailure(String s, String s1) {
}
});
获取到配网 Token 后,您还需要当前 Wi-Fi 的名称(SSID)和密码,通过初始化配网参数的回调 onQRCodeSuccess
,拿到二维码的 URL 字符串生成一个二维码图片。
相关依赖为 zxing
(implementation ‘com.google.zxing:core:3.2.1’
)。
// Get Network Configuration Token
TuyaHomeSdk.getActivatorInstance().getActivatorToken(homeId,
new ITuyaActivatorGetToken() {
@Override
public void onSuccess(String token) {
//Create and show qrCode
TuyaCameraActivatorBuilder builder = new TuyaCameraActivatorBuilder()
.setToken(token)
.setPassword(wifiPwd)
.setTimeOut(100)
.setContext(QrCodeConfigActivity.this)
.setSsid(wifiSSId)
.setListener(new ITuyaSmartCameraActivatorListener() {
@Override
public void onQRCodeSuccess(String qrcodeUrl) {
final Bitmap bitmap;
try {
bitmap = QRCodeUtil.createQRCode(qrcodeUrl, 300);
QrCodeConfigActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
mIvQr.setImageBitmap(bitmap);
mLlInputWifi.setVisibility(View.GONE);
mIvQr.setVisibility(View.VISIBLE);
}
});
} catch (WriterException e) {
e.printStackTrace();
}
}
@Override
public void onError(String errorCode, String errorMsg) {
}
@Override
public void onActiveSuccess(DeviceBean devResp) {
Toast.makeText(QrCodeConfigActivity.this,"config success!",Toast.LENGTH_LONG).show();
}
});
}
timeout
单位为秒,默认为 100,您可以设置为任意值。但不建议将此值设置得过小,否则将影响配网结果。
其中生成二维码图片示例代码如下:
public static Bitmap createQRCode(String url, int widthAndHeight)
throws WriterException {
Hashtable hints = new Hashtable();
hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
hints.put(EncodeHintType.MARGIN,0);
BitMatrix matrix = new MultiFormatWriter().encode(url,
BarcodeFormat.QR_CODE, widthAndHeight, widthAndHeight, hints);
int width = matrix.getWidth();
int height = matrix.getHeight();
int[] pixels = new int[width * height];
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
if (matrix.get(x, y)) {
pixels[y * width + x] = BLACK; //0xff000000
}
}
}
Bitmap bitmap = Bitmap.createBitmap(width, height,
Bitmap.Config.ARGB_8888);
bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
return bitmap;
}
开始配网前,请确保设备处于待配网状态。操作方法可参考设备的使用说明书。
在成功生成二维码后,引导用户将二维码对准摄像头,捕捉到二维码信息后会发出提示音。开始配网操作后,SDK 会持续广播配网信息,直到配网成功或是超时才停止。
调用 配网接口。目前已经创建好 TuyaCameraActivatorBuilder
对象 builder
,只需进行下面几行代码调用即可。
mTuyaActivator = TuyaHomeSdk.getActivatorInstance().newCameraDevActivator(builder);
mTuyaActivator.createQRCode();
mTuyaActivator.start();
在上面构建配网参数时候,您通过 TuyaCameraActivatorBuilder
对象 builder
设置监听,通过 ITuyaSmartCameraActivatorListener
回调监听配网结果。
public interface ITuyaSmartCameraActivatorListener {
void onQRCodeSuccess(String qrcodeUrl);
void onError(String errorCode, String errorMsg);
void onActiveSuccess(DeviceBean devResp);
}
如果需要中途取消配网,如离开配网页面,或配网完成,请调用 停止配网接口。
mTuyaActivator.stop();
IPC SDK 提供智能摄像机的实时视频播放、设备存储卡录像播放、对当前正在播放的视频截图、录制视频、与摄像机实时通话等基础能力。
您需要首先初始化一个 ITuyaSmartCameraP2P
对象。该对象用于读取智能摄像机设备的相关属性和方法。
TuyaCameraView
是 IPC SDK 提供的视频渲染视图,通过它您可以快速的搭建渲染出视频预览画面。
// 1. 创建 ITuyaSmartCameraP2P
ITuyaSmartCameraP2P mCameraP2P = null;
ITuyaIPCCore cameraInstance = TuyaIPCSdk.getCameraInstance();
if (cameraInstance != null) {
mCameraP2P = cameraInstance.createCameraP2P(devId));
}
TuyaCameraView mVideoView = findViewById(R.id.camera_video_view);
// 2. 为渲染视图容器设置回调
mVideoView.setViewCallback(new AbsVideoViewCallback() {
@Override
public void onCreated(Object view) {
super.onCreated(view);
//4. 渲染视图构造完成时,为 ITuyaSmartCameraP2P 绑定渲染视图
if (null != mCameraP2P){
mCameraP2P.generateCameraView(view);
}
}
});
// 3. 构造渲染视图
mVideoView.createVideoView(p2pType);
// 4. 注册 P2P 监听
if (null != mCameraP2P){
mCameraP2P.registerP2PCameraListener(new AbsP2pCameraListener() {
@Override
public void onSessionStatusChanged(Object camera, int sessionId, int sessionStatus) {
super.onSessionStatusChanged(o, i, i1);
}
});
}
建议不要为一个设备同时创建两个 ITuyaSmartCameraP2P
对象,否则会导致资源错误释放出现异常情况。
一系列初始化动作完成后,需要先连接 P2P 通道。P2P 的连接状态需要您自行维护。
开始连接 P2P 通道,参数 mode
可以指定优先选择的连接模式,是通过局域网还是公网来连接。如果指定局域网连接优先,但是 App 和设备没有在同一个局域网内建立 TCP 连接,或者设备不支持局域网连接优先,SDK 会自动使用公网连接模式,详情请参考 P2P 连接。
建立指定通道
void connect(String devId, int mode, OperationDelegateCallBack callBack);
断开通道
在关闭通道或离开当前页面时,您需要调用接口关闭通道。
void disconnect(String devId, OperationDelegateCallBack callBack);
状态监听
若您需要在过程中监听通道的连接和断开,通过 OperationDelegateCallBack
来实现监听。
mCameraP2P.connect(devId, new OperationDelegateCallBack() {
@Override
public void onSuccess(int sessionId, int requestId, String data) {
//连接成功
}
@Override
public void onFailure(int sessionId, int requestId, int errCode) {
//连接失败
}
});
}
在建立 P2P 通道后,用户就可以预览在线视频了。
开始预览
以下代码中,clarity
是清晰度模式,2
代表标清、4
代表高清。
void startPreview(int clarity, OperationDelegateCallBack callBack);
结束预览
int stopPreview(OperationDelegateCallBack callBack);
状态监听
实现如下代码可以监听视频开始预览的状态变化,stopPreview
同理。
mCameraP2P.startPreview(new OperationDelegateCallBack() {
@Override
public void onSuccess(int sessionId, int requestId, String data) {
//开始播放实时视频成功
}
@Override
public void onFailure(int sessionId, int requestId, int errCode) {
//开始播放实时视频失败
}
});
不再使用摄像机视频功能的时候,请务必注销 P2P 监听器和删除 P2P 对象。
@Override
public void onDestroy() {
if (null != mCameraP2P) {
mCameraP2P.removeOnP2PCameraListener();
mCameraP2P.destroyP2P();
}
}
在预览实时视频的同时,您还可以对录制在线视频或通过摄像机实时对讲。更多接口的使用说明,可参考 音视频功能。
请注意,录制视频需要写存储卡权限。根据不同的安卓版本,设置会有所不同。
开始录制或对讲
int startRecordLocalMp4(String folderPath, Context context, OperationDelegateCallBack callBack);
void startAudioTalk(OperationDelegateCallBack callBack);
结束录制/对讲
int stopRecordLocalMp4(OperationDelegateCallBack callBack);
void stopAudioTalk(OperationDelegateCallBack callBack);
监听状态
您可以通过监听回调事件 OperationDelegateCallBack
来监听录制和实时对讲的状态。
public interface OperationDelegateCallBack {
void onSuccess(int sessionId, int requestId, String data);
void onFailure(int sessionId, int requestId, String data);
}
设备在存储卡中保存视频录像后,可以通过 IPC SDK 在 App 端播放视频录像。
和视频预览一样,在开始回放前,您需要先连接上 P2P 通道。
IPC SDK 支持以天为单位查看和播放视频录像,并且提供查询某年某月中,哪几天保存有视频录像,以便于用户查看,查询结果通过 OperationDelegateCallBack
监听回调返回。
设备端保存在存储卡中的视频片段,最长为 10 分钟一段,最短为 10 秒钟一段。有关存储卡的录制功能和相关设置,请参考 存储卡功能。
创建 ITuyaSmartCameraP2P
对象,连接上 P2P 通道。P2P 通道连接成功后,可以获取到设备端存储卡中录制的视频片段时间信息。
第一步:查询特定月份保存过视频的日期
int year = Integer.parseInt(substring[0]);
int mouth = Integer.parseInt(substring[1]);
queryDay = Integer.parseInt(substring[2]);
mCameraP2P.queryRecordDaysByMonth(year, mouth, new OperationDelegateCallBack() {
@Override
public void onSuccess(int sessionId, int requestId, String data) {
//data 是获取到的月份数据
MonthDays monthDays = JSONObject.parseObject(data, MonthDays.class);
mBackDataMonthCache.put(mCameraP2P.getMonthKey(), monthDays.getDataDays());
mHandler.sendMessage(MessageUtil.getMessage(MSG_DATA_DATE, ARG1_OPERATE_SUCCESS, data));
}
@Override
public void onFailure(int sessionId, int requestId, int errCode) {
mHandler.sendMessage(MessageUtil.getMessage(MSG_DATA_DATE, ARG1_OPERATE_FAIL));
}
});
第二步:获取特定日期的视频列表
您可以根据上一步返回的日期查询当天的视频信息列表。
int year = Integer.parseInt(substring[0]);
int mouth = Integer.parseInt(substring[1]);
int day = Integer.parseInt(substring[2]);
mCameraP2P.queryRecordTimeSliceByDay(year, mouth, day, new OperationDelegateCallBack() {
@Override
public void onSuccess(int sessionId, int requestId, String data) {
//data 是获取到指定日期的视频片段数据
parsePlaybackData(data);
}
@Override
public void onFailure(int sessionId, int requestId, int errCode) {
mHandler.sendEmptyMessage(MSG_DATA_DATE_BY_DAY_FAIL);
}
});
data
不会直接返回视频数据本身,您可以参考下面方法进行解析。
private void parsePlaybackData(Object obj) {
RecordInfoBean recordInfoBean = JSONObject.parseObject(obj.toString(), RecordInfoBean.class);
if (recordInfoBean.getCount() != 0) {
List<TimePieceBean> timePieceBeanList = recordInfoBean.getItems();
if (timePieceBeanList != null && timePieceBeanList.size() != 0) {
mBackDataDayCache.put(mCameraP2P.getDayKey(), timePieceBeanList);
}
mHandler.sendMessage(MessageUtil.getMessage(MSG_DATA_DATE_BY_DAY_SUCC, ARG1_OPERATE_SUCCESS));
} else {
mHandler.sendMessage(MessageUtil.getMessage(MSG_DATA_DATE_BY_DAY_FAIL, ARG1_OPERATE_FAIL));
}
}
以上代码涉及了以下 2 个实体对象类:
RecordInfoBean
数据模型:
参数 | 说明 |
---|---|
count | 片段个数 |
List |
视频片段集合 |
TimePieceBean
数据模型:
参数 | 说明 |
---|---|
startTime | 视频片段开始时间 |
endTime | 视频片段结束时间 |
playTime | 视频片段播放时间 |
完成以上步骤,您就可以获取到有回放的视频片段。
成功查询到某天中的视频录像片段后,就可以开始播放录像视频了。
在以下场景中,您需要重新 查询当天的视频录像片段,避免出现播放异常:
开始播放
mCameraP2P.startPlayBack(timePieceBean.getStartTime(),
timePieceBean.getEndTime(),
timePieceBean.getStartTime(), new OperationDelegateCallBack() {
@Override
public void onSuccess(int sessionId, int requestId, String data){
isPlayback = true;
}
@Override
public void onFailure(int sessionId, int requestId, int errCode){
isPlayback = false;
}
}, new OperationDelegateCallBack() {
@Override
public void onSuccess(int sessionId, int requestId, String data){
isPlayback = false;
}
@Override
public void onFailure(int sessionId, int requestId, int errCode){
isPlayback = false;
}
});
该方法的三个参数均为时间戳:
PlayTime
为播放的初始帧时间,可以与startTime
设置为同一值。StartTime
为播放的开始时间,为 TimePieceBean
数据模型中 startTime
相对应的值。EndTime
为播放的结束时间,为 TimePieceBean
数据模型中 endTime
相对应的值。暂停回放
void pausePlayBack(OperationDelegateCallBack callBack);
继续回放
void resumePlayBack(OperationDelegateCallBack callBack);
停止回放
void stopPlayBack(OperationDelegateCallBack callBack);
监听回调(OperationDelegateCallBack)
public interface OperationDelegateCallBack {
void onSuccess(int sessionId, int requestId, String data);
void onFailure(int sessionId, int requestId, String data);
}
pausePlayBack
和 stopPlayBack
都能达到停止播放视频的目的,它们之间的区别和联系是:
stopPlayback
后,无法调用 resumePlayBack
来恢复播放。停止播放后,如果想要继续之前的进度开始播放,那么必须保存停止播放时,最后一帧视频的时间戳,以及播放的视频录像的时间片段,以重新调用 startPlayBack
方法来继续播放。startPlayBack
重新播放另一个视频录像片段,而不必先调用 stopPlayBack
停止播放。涂鸦智能摄像机的视频录像分为 连续录像 和 事件录像。
连续录像:视频录像会是 10 分钟一个片段,且所有视频片段是连续的,但是如果中间有停止过视频录像,那么连续录像模式下的视频片段间也可能会有间隔。
如果某天的视频录像片段是连续的,那么播放录像时,会自动播放下一段。也就是说,即使调用开始播放接口,传入的是当天第一个视频片段的时间点,视频也会一直播放到当天最后一个视频片段的最后一帧视频,才会回调视频播放结束的代理方法。
事件录像:每个录像片段长度不等,且片段间的间隔时间也长短不一。
如果某天的视频录像片段是不连续的,即视频录像片段 A 结束后隔了一段时间才有视频录像片段 B,在播放到断开的地方(即播放到视频片段 A 的最后一帧),视频流会自动停止。
IPC SDK 还提供了更多功能,您可以根据 Sample 工程和 IPC SDK 文档了解如何构建 App。
该内容对您有帮助吗?
是意见反馈该内容对您有帮助吗?
是意见反馈