自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(97)
  • 收藏
  • 关注

原创 SPP 与 RFCOMM 的层级关系

RFCOMM 是底层传输协议,SPP 是基于 RFCOMM 封装出来的上层应用规范,SPP 不是独立传输协议,SPP 的完整实现必须基于 RFCOMM;RFCOMM 是 SPP 的底层承载。- SPP(Serial Port Profile):蓝牙官方应用剖面/协议规范,专门规定如何用 RFCOMM 模拟串口。- 蓝牙协议栈的传输层协议(基础通道),跑在 L2CAP 之上;- 是一套标准化业务规则:规定设备配对、通道建立、流控、串口参数、断开逻辑;- RFCOMM:蓝牙协议栈的传输层协议(基础通道)

2026-07-08 14:57:47 185

原创 Activity切换监听(系统级APP)

普通 Activity 跳转、Launcher 桌面切换、普通 App 页面可监听。弹窗、悬浮 Window、系统 Dialog、Toast、自定义全局弹窗监听不到。必须加的权限(AndroidManifest.xml)TaskStackListener 封装类。

2026-05-08 21:38:33 54

原创 生成pcm文件并播放查看波形

音频流开始时要初始化PcmFile,我目前采用的是覆盖模式,只生成一个car_audio.pcm文件,新的音频会覆盖旧的。音频数据回调时写入文件 ByteBuffer byteBufferData。可以用此程序播放并查看波形。文件->导入->原始数据。音频流结束时关闭文件。

2026-05-08 09:59:58 95

原创 裁剪SurfaceView

outline.setRoundRect( left, // 左边界 top, // 上边界 right, // 右边界 bottom, // 下边界 radius // 圆角半径 );,让 FrameLayout 把超出圆角的部分 “挡住”,从而让矩形 SurfaceView 看起来是圆角的。并不是真正的裁剪SurfaceView,而是用。包裹 SurfaceView达到视觉裁剪。

2026-05-05 22:59:05 70

原创 Future

Future是一个占位符,它代表一个尚未完成但将来会完成的计算结果。你可以把它想象成一张“取餐小票”:你点完咖啡,服务员给你一张小票。这张小票不是咖啡本身,但它承诺未来你会凭此拿到咖啡。在小票有效期间(计算进行中),你可以去做其他事(不阻塞主线程),等咖啡做好了,你再凭票取咖啡(获取结果)。Kotlin 的Deferred= 协程版的 Future,用async创建,await()等待不阻塞线程await()是挂起点,不是阻塞点结构化并发自动管理生命周期,取消会传播比 Java Future 更轻量。

2026-02-13 16:47:02 844

原创 android studio中怎么引用SVG

(Scalable Vector Graphics)是一种基于XML的矢量图像格式,用于在Web和其他环境中显示二维图形。与基于像素的栅格图像(如JPEG、PNG)不同,SVG使用数学描述来定义图形,因此可以无限缩放而不失真。选择你的 SVG 文件。

2026-01-28 16:48:19 212

原创 不同车型drawable不同

在build.gradle文件中 定义了两种平台::代表平台1的配置:代表平台2的配置它们属于同一个维度 'platform':这意味着它们是互斥的构建时只能选择其中一个一个平台有多款车型,只有车型6图片不一样。1. 作用:确保所有 Android 插件配置都已完成,可以安全地访问和修改配置。3. 获取当前资源目录作用:获取 flavor 当前配置的所有资源目录 是一个目录路径的列表保存到变量 中这是最关键的一行,分解说明:// 1. 创建一个新列表,

2026-01-27 18:05:31 77

原创 SQLite数据库版本升级降级

【代码】SQLite数据库版本升级降级。

2025-12-08 09:19:51 146

原创 SoundPool

短音效(<5秒)、游戏音效、频繁播放的音效。:低延迟、可同时播放多个音效、音量独立控制。:不适合长音频(内存占用大)

2025-12-02 19:43:11 315

原创 AIDL讲解

如果要传递自定义的类(例如User创建自定义类,实现Parcelable接口,并重写相关方法。创建对应的 AIDL 文件声明这个 Parcelable 类型(例如User.aidl在接口 AIDL 文件中 import这个类型。示例:// 必须实现 Parcelable 接口// 构造方法、getter、setter 省略...@Override@Override@Overridereturn 0;@Override// 声明为 Parcelable。

2025-09-18 14:17:52 1304

原创 链表 (C/C++)

链表是一种动态数据结构,由一系列节点组成,每个节点包含数据和指向下一个节点的指针。// 最基本的链表节点int data;// 数据域// 指针域,指向下一个节点} Node;int data;// 指向前一个节点// 指向下一个节点} DNode;int val;// 存储的数据// 指向下一个节点的指针// 构造函数构造函数:用于创建新的ListNode对象:构造函数名,接受一个整数参数x:成员初始化列表val(x):将参数x的值赋给val成员:将next指针初始化为空指针{}

2025-09-08 16:20:16 827

原创 C语言 基础语法学习Demo

从lib->books数组的起始地址开始,将sizeof(lib->books)个字节的内存全部设置为0。strcmp比较两个字符串的字典序, 它逐个字符比较,直到遇到不同的字符或字符串结束。sizeof(lib->books): 整个数组的大小(字节数):如果需要修改结构体实现,只需修改typedef。:在链表为空时,需要修改head指针指向新节点。:代码更清晰,特别是对于复杂的数据结构。返回从1970年1月1日开始的秒数。包含年、月、日、时、分、秒等信息。:适用于任何需要修改指针的情况。

2025-09-08 15:32:18 636

原创 Stream API 讲解

Stream 不是数据结构,而是对数据源(集合、数组等)的元素序列进行函数式操作的管道。

2025-08-29 10:54:02 784

原创 C代码学习笔记(二)

数组名是指向首元素的常量指针arr[i]等价于*(arr + i)数组作为函数参数时会退化为指针指针算术根据指向类型的大小进行理解指针数组和数组指针的区别注意sizeof在数组和指针上的不同行为。

2025-08-26 19:55:49 702

原创 C语言 结构体

结构体是一种用户自定义的数据类型,它允许你将多个不同类型的变量组合在一起,形成一个逻辑上的整体。这些变量称为结构体的成员(Members)。使用struct关键字来定义结构体。struct 结构体标签 {数据类型 成员1;数据类型 成员2;// ... 更多成员示例:定义一个表示学生的结构体// 定义结构体类型 (这只是一份蓝图,尚未分配内存)int id;// 学号// 姓名// 成绩// 注意这里的分号不能丢知识点描述关键语法定义创建一种新的复合数据类型声明变量创建该类型的实例。

2025-08-26 18:12:46 455

原创 C语言 指针

指针本质上是一个变量,但它的特殊之处在于,它存储的不是一个普通的值,而是另一个变量的内存地址。

2025-08-26 17:26:36 461

原创 C代码学习笔记(一)

概念描述关键点char*指向字符或字符串的指针。理解指针本身和它指向的数据。char* str指向(通常是只读的)字符串字面量。字符串不可修改,指针可指向别处。char str[]一个字符数组。字符串可修改,数组名不可指向别处。指向常量字符串的指针。安全,明确意图,推荐使用。动态分配使用malloc为char*在堆上分配内存。字符串可修改,必须手动free。

2025-08-23 16:42:19 927

原创 C ++代码学习笔记(一)

对于基本类型数组(如 int[], float[] 等),不能直接使用 GetObjectArrayElement,而应该使用对应的函数如 GetIntArrayElements。用于在 C/C++ 代码中获取 Java 对象的类引用。用于将 C/C++ 的 UTF-8 字符串 转换为 Java 的。如果你想获取某个已知类的引用(而不是通过对象实例),可以使用。这几行代码展示了一个类中常见的特殊成员函数的声明和定义方式。用于从 Java 对象数组中获取指定索引处的元素。用于获取 Java 数组的长度。

2025-08-21 20:10:06 393

原创 JNI_OnLoad 和 RegisterNatives

使用 RegisterNatives 时,函数指针是通过直接转换获取的,不需要通过名称查找。:在 Android 中使用 RegisterNatives 方式注册本地方法。:始终检查 FindClass 和 RegisterNatives 的返回值。RegisterNatives 使用的是函数指针,不需要这些修饰。是 JNI 的一个特殊钩子函数,当本地库被加载时(通过。:在 JNI_OnLoad 中返回正确的 JNI 版本。只有需要被动态查找的函数才需要这些修饰符。:避免首次调用方法时的动态查找开销。

2025-08-18 16:36:28 591

原创 C++ #if

(Preprocessor Directive),用于。,即在编译阶段根据条件决定是否包含某段代码。跨平台适配(Windows/Linux/macOS)如果条件成立(非零),则编译。(决定哪些代码参与编译)。被定义且非零,则输出。(编译时可确定的值)。防止头文件重复包含(

2025-08-15 14:24:17 531

原创 INT_MIN

在大多数现代系统上,int是32 位有符号整数,范围是到。INT_MIN的值通常是 -2,147,483,648(即-2³¹。

2025-08-15 11:15:50 648

原创 Room 数据存储

Room 是 Android Jetpack 组件中的一个持久化库,它是在 SQLite 上提供了一个抽象层,使得数据库访问更加简单、高效。

2025-08-14 19:49:38 471

原创 C++ 标准库容器常用成员函数

rbegin()end()C++ 标准库提供了多种容器类型,每种容器都有一系列成员函数。以下是主要容器(vectorarraylistdequesetmap。

2025-08-08 17:17:55 1187

原创 C++ 算术函子

用于封装基本的算术运算(如加、减、乘、除等)。它们本质上是类模板,重载了。,因此可以像函数一样被调用。这些函子通常与标准算法(如。)结合使用,提供高效且语义清晰的运算操作。从 C++14 开始,可以使用。通常会被编译器内联优化,性能与直接写。是模板参数,表示运算的数据类型(如。:算术函子是空类(无成员变量),调用。(透明运算符函子)自动推导类型。

2025-08-08 16:04:05 291

原创 std::transform

是 C++ 标准库中的一个重要算法,用于对容器(如等)中的元素进行转换操作。:对输入范围的每个元素应用unary_op,并将结果存储到d_first开始的输出位置。first1last1:输入范围的起始和结束迭代器。d_first:输出位置的起始迭代器(可以是输入容器的起始位置,实现原地修改)。unary_op:一元操作函数(如::tolower::toupper或自定义:返回输出范围的结束迭代器(:对两个输入范围和的对应元素应用binary_op,结果存储到d_first。first2。

2025-08-08 15:12:34 692

原创 C++ 键值对

当使用自定义类型作为键时,需要提供哈希函数或比较函数。#include <unordered_map> // 使用 unordered_map 容器#include <string> // 使用 string 类型#include <functional> // 使用 std::hashint id;// 关键点:重载了 == 运算符,这是 unordered_map 判断键是否相等所必需的// const 修饰符表示这个比较操作不会修改对象状态// 自定义哈希函数。

2025-08-08 14:07:51 1187

原创 unordered_map

是 C++ 标准模板库 (STL) 中的一个关联容器,它提供了一种高效的键值对 (key-value) 存储和访问方式。下面我将详细讲解它的特性、用法和在罗马数字转换中的应用。

2025-08-07 18:33:12 366

原创 修复MediaCodec最后一帧未渲染

【代码】修复MediaCodec最后一帧未渲染。

2025-07-28 09:56:35 185 1

原创 C++ 结构体(struct)与联合体(union)

声明方式struct 结构体名 {数据类型 成员1;数据类型 成员2;// ...定义结构体变量Person p1;// 创建一个Person类型的变量// 初始化列表方式声明方式union 联合体名 {数据类型 成员1;数据类型 成员2;// ...定义联合体变量Data d1;d1.i = 10;// 当前存储的是int// 现在存储的是float,之前的值被覆盖。

2025-07-22 17:20:05 556

原创 C++ 指针与引用

指针和引用是 C++ 中两个强大的特性,它们都提供了间接访问数据的能力,但在语法和语义上有重要区别。

2025-07-15 18:26:51 1635

原创 右值引用 (C++11)

右值引用(Rvalue Reference)是 C++11 引入的关键特性,用于实现。:减少不必要的拷贝(特别是处理容器、字符串等资源密集型对象):模板函数参数传递时丢失左右值属性。:使模板函数能保持参数的原始值类别。:临时对象、字面量、即将销毁的值。:有持久状态、可取地址的表达式。:通过右值引用"窃取"资源。:深拷贝临时对象效率低下。(注意与通用引用区分)

2025-07-15 18:26:01 352

原创 本地线程(Native Thread)、主线程(UI 线程) 和 子线程(Java 子线程)

(如网络请求、文件读写),否则会导致 ANR(Application Not Responding)。协程是轻量级线程管理工具,底层仍运行在 JVM 线程池上,属于。:C++ 层高性能计算,需手动管理 JNI 环境。处理 UI 渲染(如 View 绘制、触摸事件)内存耗尽(每个线程默认占用 1~2MB 栈内存)简单异步任务(用 Java 线程或协程更高效)调用底层硬件(如 OpenGL、传感器)高性能计算(如音视频编解码、图像处理)(不像 Java 线程受线程池约束)。:Java 层多任务,适合 I/O。

2025-07-14 18:33:15 1033

原创 Android Studio C++/JNI/Kotlin 示例 三

构造函数:接收 JNI 环境和 Java 回调对象析构函数:负责资源清理start():启动工作线程stop():停止工作线程:检查线程是否在运行线程管理:使用 C++11 的创建本地线程JNI 环境处理:正确处理线程附加/分离 JVMJava 回调:通过全局引用和方法 ID 安全回调 Java 方法异常处理:检查并清除 JNI 调用可能产生的异常内存管理:正确管理全局引用和本地对象线程安全:使用running标志控制线程生命周期。

2025-07-14 18:19:03 784

原创 C++ STL算法

STL算法是C++标准库中一组高度优化的通用算法,主要定义在<numeric>和头文件中。它们通过迭代器抽象与容器交互,提供丰富的操作功能。

2025-07-14 13:58:59 546

原创 Android Studio C++/JNI/Kotlin 示例 二

这段代码是用C++实现的JNI(Java Native Interface)接口,它连接了Java/Kotlin代码和本地C++代码。使用 UTF-8 编码转换,这是 Java 和 C++ 之间最常用的编码方式。:JNI开发必需的头文件,定义了Java和本地代码交互的所有类型和函数。这是防止头文件被多次包含的标准做法,避免重复定义错误。:包含 Java 字符串内容的 std::string。:包含对应的头文件,确保函数声明与定义一致。:包含 Java 数组数据的 vector。

2025-07-14 11:39:00 1342

原创 Android Studio C++/JNI/Kotlin 示例 一

创建一个名为Learn1项目(Android Studio)。build.gradle.kts(:app)settings.gradle.kts(Learn1)三、创建 CMakeLists.txtAndroid NDK(Native Development Kit)允许你在 Android 应用中使用 C/C++ 代码,通常用于高性能计算、游戏引擎、音视频处理等场景。NDK 项目的核心是通过 或 (较旧)来配置本地代码的编译。以下是详细的配置示例和解析:假设你有一个 JNI 模块,

2025-07-10 17:58:39 1246

原创 学习JNI (Java Native Interface)

JNI 是 Java 平台提供的一套标准,它允许 Java 代码与其他语言(主要是 C 和 C++)编写的本地代码进行交互。注意函数名 `Java_com_example_NativeDemo_sayHello`,它遵循特定的命名规则,将包名、类名和方法名用下划线连接起来。工具(或者更现代的方法,如 Android Studio 的 Gradle 插件会自动处理)根据包含。这些方法只有方法签名,没有方法体。方法实现对应的 C/C++ 函数。这个头文件包含了本地方法对应的 C/C++ 函数签名。

2025-07-09 14:07:06 1244

原创 何时使用指针(*)?

Android NDK的MediaCodec API是用C语言编写的,C API通常使用指针来传递和操作对象。:如果对象需要在运行时动态创建,并且生命周期需要手动管理,通常使用指针。:如果对象较大(如视频帧数据),直接传递会导致性能问题,使用指针更高效。:如果对象生命周期仅限于当前作用域(如函数内部),直接使用对象更安全。:如果函数需要修改传入的对象,必须传递指针(或引用)。是栈上的对象,但内部数据在堆上,无需手动管理内存。这些对象是在堆上分配的,必须通过指针访问。,因为它是C函数,无法返回C++对象。

2025-07-08 17:22:42 990

原创 C++ MediaCodec H264解码

用于Android日志输出:Android NDK提供的媒体编解码API:媒体格式相关APIunistd.h:包含sleep等函数LOGTAG:日志标签,便于在logcat中过滤日志LOGE和LOGI:日志宏,分别用于输出错误和普通信息日志:可变参数宏,允许宏接受可变数量的参数public:定义了一个类,封装了H.264解码功能构造函数使用成员初始化列表初始化指针成员析构函数中释放了所有分配的资源::停止解码器:销毁解码器实例:销毁媒体格式对象。

2025-07-08 16:13:55 1351

原创 C++中的析构函数

/ 析构函数声明MyClass::~MyClass() { // 析构函数定义// 清理代码。

2025-07-08 15:48:38 503

跟随手指移动的冒心动画

跟随手指移动的冒心

2023-05-30

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除