IP 摄像机移动应用 SDK 开发入门教程(安卓版)

news2024/11/18 3:21:34

涂鸦智能安卓版摄像机(IP Camera,简称 IPC)SDK 是基于智能生活 App SDK 开发而成。

通过移动应用控制物理网设备是常见的使用场景,但由于设备的品类丰富,增大了应用开发难度。因此 智能生活 App SDK 提供了常见的垂直品类 SDK,例如 IPC SDK,将网络摄像机设备特有的功能抽离,提供了与其通讯的接口封装,加速应用开发过程。 

大家可以通过本教程,在一小时内快速开发一款自己的 IoT App,并实现如下功能:

  •  通过 App 连接一个智能摄像头。
  •  预览摄像机实时采集的影像。
  •  播放摄像机存储卡中录制的视频。
  •  手机端录制摄像机采集的影像。

大家可以 前往App工作台 下载 Sample 查看本教程中的示例代码。本次教程按功能模块进行分类,大家可以快速找到对应的代码参考学习。

效果展示

学习完本教程,结合一定的面板开发可以创建一个类似以下安卓 App 的 Demo。

准备工作

在开始本教程前,请先确保完成一下工作 :

  1. 在涂鸦 IoT 平台,注册账号并创建 App 应用,拿到 SDK 的 AppKey,AppSecret。

    由于 IPC SDK 依赖于 智能生活 App SDK,需要先实现如创建账号、添加家庭的操作后才能借助 IPC SDK 实现摄像机相关功能。具体操作流程可参考我上一篇文章《智能生活 App SDK 开发入门教程》。

  2. 准备一个涂鸦赋能的智能摄像机产品,本教程以摄像头为例。
  3. 使用 Android Studio 将涂鸦安卓智能生活 App SDK 集成到项目中 。 具体教程可参考我之前文章《 IPC SDK 架构及快速集成配置》。

设备配网

由涂鸦赋能的智能摄像机支持智能生活 App SDK 中的所有配网方式,例如 Wi-Fi 热点配网蓝牙配网等。

此外,涂鸦为 IPC 设备提供了独有的扫描二维码配网功能,但如果 IP 摄像机设备无法扫码,可以优先尝试 Wi-Fi 快连方式。本篇教程文档主要讲解扫描二维码配网。

获取 Token

和 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 字符串生成一个二维码图片。

相关依赖为 zxingimplementation ‘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();
                                        }
                                    });

                        }

其中生成二维码图片示例代码如下:

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);
        }
    });
}

第二步:连接 P2P 通道

一系列初始化动作完成后,需要先连接 P2P 通道。P2P 的连接状态需要我们自行维护。

开始连接 P2P 通道,参数 mode 可以指定优先选择的连接模式,是通过局域网还是公网来连接。如果指定局域网连接优先,但是 App 和设备没有在同一个局域网内建立 TCP 连接,或者设备不支持局域网连接优先,SDK 会自动使用公网连接模式。

  • 建立指定通道

    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 监听回调返回。

查询视频列表

创建 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);
  }
});

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);
    }
    

相关概念

涂鸦智能摄像机的视频录像分为 连续录像 和 事件录像

  • 连续录像:视频录像会是 10 分钟一个片段,且所有视频片段是连续的,但是如果中间有停止过视频录像,那么连续录像模式下的视频片段间也可能会有间隔。

    如果某天的视频录像片段是连续的,那么播放录像时,会自动播放下一段。也就是说,即使调用开始播放接口,传入的是当天第一个视频片段的时间点,视频也会一直播放到当天最后一个视频片段的最后一帧视频,才会回调视频播放结束的代理方法。

  • 事件录像:每个录像片段长度不等,且片段间的间隔时间也长短不一。

    如果某天的视频录像片段是不连续的,即视频录像片段 A 结束后隔了一段时间才有视频录像片段 B,在播放到断开的地方(即播放到视频片段 A 的最后一帧),视频流会自动停止。

下一步

IPC SDK 还提供了更多功能,大家可以登录涂鸦 IoT 开发平台​​​​​​​,根据 Sample 工程和 IPC SDK 文档了解如何构建 App。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/29980.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

支付宝支付内网穿透

支付宝支付&内网穿透一 沙箱环境二 python第三方模块python-alipay-sdk三 python-alipay-sdk二次封装四 支付接口五 内网穿透5.1 cpolar软件5.2 测试支付宝post回调一 沙箱环境 注册认证沙箱环境&#xff1a;https://openhome.alipay.com/platform/appDaily.htm?tabinfo …

【FileZila】实现windows与Linux系统文件互传

1、下载安装FileZila客户端 根据自己的PC系统版本&#xff0c;下载对应的FileZila客户端https://www.filezilla.cn/download/client 2、Linux服务端&#xff0c;安装配置vsftpd 2.1 安装ftp服务 sudo apt-get install vsftpd2.2 配置ftp服务 &#xff08;1&#xff09;打开ft…

Verilog 实现CDC中单bit 跨时钟域,从慢时钟域到快时钟域

单bit 跨时钟域&#xff0c;从慢时钟域到快时钟域1&#xff0c;首先&#xff0c;了解一些问题2&#xff0c;RTL代码设计3&#xff0c;testbench测试代码4&#xff0c;RTL代码和testbench综合的电路原理图5&#xff0c;前仿真&#xff0c;验证![在这里插入图片描述](https://img…

关于某些地区延期举办2022年11月27日 PMI认证考试等有关事项的通知

22年.11月22日通知&#xff1a; 关于成都等六个地区延期举办2022年11月27日 PMI认证考试等有关事项的通知 尊敬的考生&#xff1a; 受近日疫情影响&#xff0c;结合当地疫情防控规定和活动举办要求&#xff0c;成都、武汉、西安、昆明、银川、长春地区现不满足组织2022年11月…

A. The Enchanted Forest(思维)

Problem - 1687A - Codeforces 玛丽莎来到魔法森林采摘蘑菇。 魔法森林可以用X轴上编号为1到n的n个点来表示。在玛丽莎开始之前&#xff0c;她的朋友帕秋莉用魔法检测了每个点上的蘑菇的初始数量&#xff0c;用a1,a2,...,an表示。 玛丽莎可以在第0分钟时从森林的任何一点开始…

Allegro如何输出IDF文件操作指导

Allegro如何输出IDF文件操作指导 Allegro支持输出IDF文件,用于导入结构软件中检查和查看,具体操作如下 点击File-export-IDF 会弹出一个对话框,file name type选择IDF 然后点击export,输出IDF文件,文件已经输出 This section is describe what the function allegro h…

项目管理工具需要具备的五点功能

将新产品推向市场是有益的&#xff0c;但也具有挑战性。从一个概念到成功发布的过程涉及很多事情。在产品开发过程中&#xff0c;许多内部团队都参与了将概念推向市场的工作。例如&#xff0c;设计团队、工程团队和营销团队都在这个生命周期中发挥作用。协调时间表、阶段和可交…

【Vue】组件化和声明周期函数

1. 组件化 组件化就是指一个后台我们将它的各个部分拆分成各个组件&#xff0c;比如 csdn 的上边栏、右侧广告区等都可以是组件&#xff0c;组件可以复用。Vue 的一个好处就是组件化。 <!DOCTYPE html> <html lang"en"> <head><meta charset&…

【云原生】Docker的数据卷、数据卷容器,容器互联

内容预知 1.数据卷&#xff08;容器与宿主机之间数据共享&#xff09; 2. 数据卷容器&#xff08;容器与容器之间数据共享&#xff09; 3. 容器互联&#xff08;使用centos镜像&#xff09; 3.1 实现容器互联 3.2 只通过IP进行通信 总结 1.数据卷&#xff08;容器与宿主…

视频编解码 - 帧间预测

目录 帧间预测 块大小 参考帧和运动矢量 运动矢量 运动搜索 1、全搜索算法 2、钻石搜索算法&#xff08;菱形搜索算法&#xff09; 3、六边形搜索算法 搜索起始点的确定 快速搜索与全搜索的优缺点 非整像素的处理 亚像素差值 亚像素精度运动搜索 运动矢量预测 S…

双十二蓝牙耳机哪款好?双十二平价蓝牙耳机推荐

对于许多人来说&#xff0c;音乐即是生活良药&#xff0c;带给我们生活、工作和学习的动力&#xff0c;若想要随时随地都能来上一剂&#xff0c;那么买到一款划算平价的真无线蓝牙耳机便是优秀的选择。 一、南卡小音舱蓝牙耳机 蓝牙&#xff1a;5.3 延迟&#xff1a;45ms 发…

npm、yarn到pnpm的发展历程

npm、yarn到pnpm的发展历程背景价值点npm发展及存在的问题npm v1&#xff08;树状结构&#xff09;安装原则优点不足&#xff1a;npm v3&#xff08;扁平化结构&#xff09;安装原则优点&#xff1a;不足&#xff1a;目录结构不确定依赖A先安装依赖A后安装npm v5优点npm包分身定…

mysql全文索引

引用&#xff1a;https://www.cnblogs.com/miracle-luna/p/11147859.html MySQL 5.7.6之前只支持英文全文索引&#xff0c;不支持中文全文索引&#xff0c;&#xff0c;需要利用分词器把中文段落预处理 拆分成单词&#xff0c;&#xff0c;然后存入数据库 MySQL 5.7.6 开始&am…

FSK/OOK 调制单发射芯片CMT2119A-ESR/CMT2119B-EQR

FSK/OOK 调制单发射芯片CMT2119A-ESR/CMT2119B-EQR CMT2119A 是 HopeRF 旗下CMOSTEK 无线产品线 FSK/OOK 调制单发射芯片&#xff0c;CMT2219A 则是与之对应的 FSK/OOK 调制单接收芯片&#xff0c;均支持 Sub-1G 应用无线发射芯片CMT2119A主要应用&#xff1a; 无线遥控开关、…

接口设计与优化

文章目录接口的注意事项获取对象的属性或方法&#xff0c;先 判断对象是否为空&#xff01;修改老接口&#xff0c;思考接口的兼容性重点接口&#xff0c;考虑线程池隔离调用第三方接口考虑超时、重试接口的熔断、降级接口&#xff0c;需要考虑限流接口要打印好日志接口考虑热点…

ETF动量轮动+RSRS择时,RSRS修正标准分,回撤降至16%

原创文章第113篇&#xff0c;专注“个人成长与财富自由、世界运作的逻辑&#xff0c; AI量化投资”。 昨天的策略我是比较满意的&#xff0c;沿着进化的方向在迭代我们的策略。ETF轮动RSRS择时&#xff0c;加上卡曼滤波&#xff1a;年化48.41%&#xff0c;夏普比1.89 我们会持…

Linux从入门到精通(十)——进程管理

文章篇幅较长&#xff0c;建议先收藏&#xff0c;防止迷路 文章跳转Linux从入门到精通&#xff08;八&#xff09;——Linux磁盘管理goLinux从入门到精通&#xff08;九&#xff09;——Linux编程goLinux从入门到精通&#xff08;十&#xff09;——进程管理goLinux从入门到精…

Go Web项目 接口开发全流程

风离不摆烂学习日志 Day5 — Go Web项目 接口开发全流程 接上篇地址 Web项目学习之项目结构 routes包分析 InitRoutes package routesimport ("fmt""github.com/gin-gonic/gin""go-web-mini/common""go-web-mini/config""go-we…

Charles断点

1、断点测试的含义 1.1、断点&#xff08;英语&#xff1a;Breakpoint&#xff09;是程序中为了调试而故意停止或者暂停的地方。 调试设置断点&#xff1a;可以让程序运行到该行程序时停住&#xff0c;借此观察程序到断点位置时&#xff0c;其变量、寄存器、I/O等相关的变量内…

mysql InnoDB 索引结构

目录 前言 1. InnoDB常见的索引 2. B树索引 2.1 二分查找法 2.2 二叉查找树 2.3 平衡二叉树 2.4 B树索引 2.5 B树索引 2.5.1 聚集索引 2.5.2 非聚集索引 2.5.3 聚集索引与非聚集索引区别 前言 索引的本质是让mysql以最高效、扫描行数最少的方式找到需要的数据。索引…