- 博客(209)
- 资源 (19)
- 收藏
- 关注
原创 Android 使用MediaMuxer+MediaCodec编码MP4视频
摘要:该代码实现了一个基于Android MediaCodec和MediaMuxer的YUV420转MP4编码工具类。主要功能包括:初始化编码器参数(宽高、帧率、比特率)、准备编码环境、接收YUV420帧数据并编码、输出MP4文件。通过状态机管理编码过程(IDLE/PREPARED/ENCODING/STOPPED),支持时间戳计算和缓冲区管理,实现了高效的视频编码流程。关键点包括H.264编码配置、输入输出缓冲区处理、时间戳同步以及资源释放机制。
2025-08-28 10:49:13
340
原创 Android GLSurfaceView图像显示优化完整方案
本文介绍了一个基于OpenGL的图像查看器项目结构及核心代码实现。项目采用模块化设计,主要包含图像渲染、格式定义和工具类等组件。核心代码包括:1) ImageFormat.kt定义了8种图像格式枚举和图像数据类;2) ShaderUtils.kt提供了着色器加载和程序创建功能;3) ImageUtils.kt实现了Bitmap与RGB/BGR格式的转换工具。项目结构清晰,通过OpenGL ES 3.0实现高效图像渲染,支持多种常见图像格式的处理和显示。
2025-08-28 10:48:23
589
原创 Android开发JNI控制C++代码块是否编译
本文介绍了在Android开发中控制C++代码块编译的几种方法:1)使用预处理器指令#ifdef等;2)通过CMakeLists.txt配置宏定义;3)在Gradle中动态设置编译标志;4)提供了具体代码示例。这些方法可以根据不同构建类型、产品风味等场景灵活控制代码编译,实现条件编译和功能开关。
2025-08-27 09:45:36
281
原创 Android 的 Binder 通信线程管理
Android Binder机制中,当多个客户端并发调用Service的AIDL接口时,Binder驱动会自动管理线程池处理请求:1)初始线程池有限但会动态扩展;2)请求与线程无固定绑定关系,由空闲线程处理;3)RPC调用在后台线程执行避免阻塞主线程。这种设计要求AIDL接口实现必须保证线程安全,特别是访问共享资源时需同步处理。Binder通过动态线程分配确保系统响应性和吞吐量,开发者需注意并发访问问题。
2025-08-27 09:45:08
562
原创 Android主模块和子模块渠道包映射
摘要:在Android项目中实现主模块与子模块的渠道包对应,需在主模块定义渠道维度(如华为、小米),子模块声明相同配置。通过Gradle的Variant-Aware特性自动匹配渠道变体,可配置渠道专属依赖(如华为渠道使用HMS推送)。若渠道名不对称,可用matchingFallbacks映射。核心是保持主-子模块渠道命名一致,确保构建时自动关联对应变体。(149字)
2025-08-26 10:26:33
143
原创 CardView实现SurfaceView圆角
本文介绍了在Android中实现圆形SurfaceView的方法。通过CardView的cardCornerRadius属性设置圆形效果,内部放置SurfaceView,并使用ViewOutlineProvider进行硬件加速的圆形裁剪。关键实现包括:1) XML配置CardView为圆形;2) 动态适配尺寸;3) 硬件加速的圆形裁剪。当圆角半径设为视图尺寸一半时,可获得完美的圆形效果。
2025-08-26 10:26:29
308
原创 DataBinding错误:Cannot find a setter for that accepts parameter type ‘boolean‘
DataBinding自定义控件报错解决方法 当出现"找不到boolean类型setter方法"错误时,主要检查以下三点: 确保自定义控件中有标准的setTest(boolean)方法 或通过@BindingAdapter创建适配器方法 注意方法必须是public、参数类型严格匹配 Kotlin示例提供了两种解决方案:直接添加setter方法或使用BindingAdapter注解方式。关键要保证方法签名与XML属性类型完全一致。
2025-08-25 10:11:40
249
原创 Activity与多个 Fragment 共享ViewModel
Android开发中通过Kotlin实现Activity与多个Fragment共享ViewModel的关键是将ViewModel作用域限定在Activity级别。主要步骤包括:添加必要依赖、创建ViewModel类、在Activity中初始化ViewModel、在Fragment中使用activityViewModels()获取实例。注意事项包括:确保生命周期安全、使用viewLifecycleOwner观察数据、遵循单向数据流原则。该方法适用于单Activity多Fragment场景,如需跨Activit
2025-08-25 10:11:09
465
原创 Android includeFontPadding属性
Android的includeFontPadding属性控制文本是否包含顶部/底部额外空白,默认开启以兼容特殊字符。可通过XML或代码设置为false来消除空白,也可通过主题样式全局配置。对于中文优化有限,需注意低版本兼容性。开发者可自定义TextView基类自动关闭该属性,但需权衡特殊字符显示需求与布局空间节省。
2025-07-03 10:05:12
480
原创 Android Camera2 + OpenGL离屏渲染示例
本文介绍了在Android中使用EGL环境初始化GL线程并创建SurfaceTexture的方法。首先通过GLThread类初始化EGL显示、配置和上下文,创建离屏渲染的虚拟Surface。然后在GL线程中生成纹理ID并创建SurfaceTexture,设置帧可用监听器处理图像数据。最后将SurfaceTexture转换为Surface用于相机输出配置。关键注意事项包括:SurfaceTexture操作必须在同一线程完成,updateTexImage()需在创建线程调用,以及资源释放时需销毁EGL上下文。该
2025-07-03 10:05:10
1457
原创 Android OpenGL图像绘制支持多格式
本文介绍了一种基于OpenGL ES 3.0的Android图像绘制实现方案,支持灰度图、RGB、YUV420和YUYV格式。方案通过多纹理绑定和着色器转换实现高效GPU渲染,主要步骤包括:创建GLSurfaceView作为渲染容器,自定义Renderer接口实现,多纹理管理(根据格式创建1-3个纹理),以及在片段着色器中完成格式转换。核心代码展示了顶点/纹理坐标缓冲区的初始化、着色器编译、纹理创建与绑定等关键实现,通过统一着色器处理多种格式转换,简化了绘制流程。
2025-07-02 14:38:36
589
原创 Kotlin Data包含ByteArray类型
摘要:在Kotlin中使用包含ByteArray的数据类时,需特别注意自动生成方法的行为差异。由于默认的equals()和hashCode()会基于数组引用而非内容进行比较,需要手动重写这三个方法:使用contentEquals()比较数组内容,contentHashCode()生成哈希值,contentToString()输出可读字符串。这种处理确保了数据类能正确比较和显示ByteArray的实际内容。
2025-07-02 14:38:30
359
原创 Android开发通过ViewModel实现两个Activity之间的数据传递
在Android开发中,通过Kotlin实现跨Activity数据共享需要借助全局ViewModel。关键步骤包括:1)创建Application级别的ViewModelStore,使其生命周期与Application一致;2)定义共享ViewModel类,使用LiveData管理数据;3)各Activity通过Application获取同一ViewModel实例进行数据交互。这种方法突破了ViewModel默认的Activity作用域限制,实现了全局数据共享,同时保持了ViewModel的生命周期管理优势
2025-07-01 13:54:48
716
原创 Android开发渠道包配置指定jniLibs目录
Android开发中可以通过Gradle配置为不同渠道包指定专属jniLibs目录。在项目结构中为每个渠道(如flavorA、flavorB)创建单独的jniLibs目录,然后在build.gradle中通过sourceSets配置对应路径。编译时系统会优先使用渠道包目录的so文件,若存在相同ABI则覆盖main目录的文件,未指定的仍使用main目录资源。这种方式实现了渠道包原生库的差异化配置,同时保持代码结构清晰。
2025-07-01 13:54:45
170
原创 Linux环境编译Android App
摘要:本文介绍了在Linux环境下编译Android项目的完整流程。首先需要安装JDK和配置Android SDK(包括设置镜像源和环境变量),然后使用gradlew命令进行项目编译。针对常见的Gradle下载失败问题,提供了手动下载并替换缓存文件的解决方案。最后建议在构建失败时清理缓存并重启构建。整个过程包含详细的命令行操作和常见错误处理方法,适用于Linux系统下的Android开发环境搭建。
2025-06-30 10:56:20
1112
原创 灰度图转YUV420格式
摘要:灰度图转换为YUV420格式的关键在于处理缺失的色度分量。灰度图仅含亮度(Y),需补充分辨率减半的中性U/V值(128)。YUV420格式中Y保留原分辨率,U/V为1/4大小。转换步骤包括:1)直接使用灰度数据作为Y平面;2)创建填充128的U/V平面;3)按I420(Y+U+V)或NV21(Y+VU交替)格式合并数据。代码示例展示了通过ByteBuffer高效合并YUV分量的方法,适用于实时视频处理场景。
2025-06-30 10:56:15
306
原创 Android开发中使用LeakCanary
LeakCanary 是 Android 开发中用于检测内存泄漏的强大工具,能够帮助开发者快速定位和修复资源泄漏问题。从版本 2.0 开始,LeakCanary 支持自动集成,只需在 build.gradle 中添加依赖即可。它默认监控常见对象(如 Activity、Fragment 等)的泄漏情况,并支持手动监控自定义对象。开发者可以通过模拟内存泄漏来验证 LeakCanary 的功能,检测到泄漏后,LeakCanary 会生成详细的泄漏路径报告,帮助快速定位问题。此外,LeakCanary 还支持自定义
2025-05-15 09:52:29
1194
原创 Kotlin将异常信息转换为包含完整调用栈信息的字符串
在Kotlin中,将Exception转换为包含完整调用栈信息的字符串,可以通过两种方法实现。第一种方法是使用StringWriter和PrintWriter组合,通过内存字符流捕获异常堆栈信息,适用于所有Throwable类型。代码示例如下: fun exceptionToString(e: Exception): String { val sw = StringWriter() val pw = PrintWriter(sw) e.printStackTrace(pw) // 将堆栈信息写入流 retu
2025-05-15 09:51:42
299
原创 Kotlin通过反射随机测试目标类的静态方法
文章摘要:本文介绍了使用反射机制动态调用类方法的实现步骤。首先,通过反射获取类的所有公共静态方法,并过滤出符合条件的集合。接着,随机选择其中一个方法,并根据其参数类型动态生成参数值,包括基本类型、接口类型等。对于接口类型,使用动态代理生成空实现对象,避免空指针异常。最后,通过反射调用选定的方法,并处理可能的异常。文章还提供了完整的Kotlin示例代码,展示了如何实现这些功能,包括随机生成字符串、枚举值、数组等复杂类型的参数。
2025-05-14 11:04:14
729
原创 Android TextView实现垂直滚动
本文介绍了如何在 Android 应用中实现动态追加文本并自动滚动到底部的功能。首先,在 XML 布局文件中,将 TextView 包裹在 ScrollView 中,并设置 TextView 的高度为 wrap_content 以允许内容扩展。接着,在 Activity 或 Fragment 中初始化控件,并通过 textView.append() 方法动态追加文本。为了确保自动滚动到底部,使用 scrollView.fullScroll(ScrollView.FOCUS_DOWN) 方法,并通过 post
2025-05-14 11:03:48
563
原创 Android 使用libYUV垂直翻转RGB数据
本文介绍了如何使用libYUV库中的CopyPlane函数实现图像的垂直翻转。首先,需要明确输入图像的RGB格式(如RGB24)及其参数(宽度、高度和行跨度)。接着,分配与源数据大小相同的目标缓冲区。通过设置负步长(Negative Stride),将源数据从最后一行开始反向复制到目标缓冲区,从而实现垂直翻转。代码示例展示了如何调用CopyPlane函数,并详细说明了参数设置,包括源数据指针、步长、目标起始位置等。该方法简单高效,适用于图像处理中的垂直翻转需求。
2025-05-13 09:52:53
303
原创 Android OpenGL从帧缓冲区读取像素数据
OpenGL ES 2.0 中的 GLES20.glReadPixels 函数用于从帧缓冲区读取像素数据,支持多种像素格式和数据类型。其主要应用场景包括截图保存、图像处理分析和机器学习数据提取等。函数原型包括读取区域的坐标、宽高、像素格式、数据类型和目标缓冲区。使用步骤包括分配缓冲区、调用函数读取数据以及进行数据后处理,如将数据转换为 Bitmap 并进行垂直翻转。该函数在图形渲染和图像处理中具有重要作用。
2025-05-13 09:52:16
449
原创 Android 使用OpenCV解码视频
本文介绍了如何在Android平台上使用OpenCV 4.11实现视频解码的完整代码步骤。首先,通过VideoCapture类加载视频文件,并逐帧读取视频数据。每帧数据被转换为YUV420格式,并存储在字节数组中。为了保持视频播放的流畅性,代码还实现了帧率控制,确保每帧之间的延迟符合25帧/秒的要求。最后,释放所有资源,完成视频解码过程。该代码适用于需要实时处理视频帧的Android应用场景。
2025-05-12 09:36:06
147
原创 jsoncpp 生成的 JSON 字符串换行符问题
jsoncpp 生成的 JSON 字符串默认包含换行符和缩进,以提高可读性。使用 toStyledString() 方法时,自动添加这些格式化字符。若需生成紧凑的 JSON 字符串,可以使用 Json::FastWriter 或 Json::StreamWriterBuilder 来禁用换行符和缩进。Json::FastWriter 直接生成紧凑格式,而 Json::StreamWriterBuilder 通过设置 "indentation" 为空字符串来实现。换行符在调试和日志输出中有
2025-05-12 09:35:40
496
原创 JNI开发使用jsoncpp
在 Android JNI 开发中,如果使用 jsoncpp 库来生成和解析 JSON 数据,可以通过以下步骤进行集成。jsoncpp 是一个流行的 C++ JSON 库,可以方便地用于处理 JSON 数据。2.1. src\lib_json目录copy到项目main/cpp目录。2.2. include\json目录copy到项目main/cpp目录。在 JNI 中使用 jsoncpp 生成和解析 JSON 数据。手动将 jsoncpp 源代码文件加入到项目。修改 CMakeLists.txt。
2025-01-15 10:04:38
1118
原创 taskset命令
taskset 是 Linux 系统中的一个命令,用于设置或获取进程的 CPU 亲和性(CPU affinity)。CPU 亲和性决定了进程可以在哪些 CPU 核心上运行,通常用于优化性能,避免多个进程在同一核心上竞争资源。在 Android 系统中,由于它是基于 Linux 内核的,因此 taskset 命令也可以使用,但需要确保设备已经启用了 taskset 工具,并且你的设备具备了 root 权限,或者你正在使用开发者选项中的 ADB 工具。
2025-01-15 10:04:13
821
原创 Constructor of inner class ... can be called only with receiver of containing class
内类 (inner class) 必须通过外部类的实例来创建,因为它持有外部类的引用。确保你先实例化外部类,再通过外部类的实例来实例化内部类。
2025-01-14 14:42:44
405
原创 CSV文件对包含逗号的
使用 field.replace(“”“, “””") 处理字符串中的双引号,将每个双引号替换为两个双引号(这是 CSV 标准要求的做法)。在保存数据到 CSV 文件时,如果数据中包含逗号,应该对包含逗号的数据进行处理,以避免它被误认为是字段分隔符。将每个字段写入文件,并加上逗号分隔符。field.contains(“”") 检查数据是否包含双引号。field.contains(“,”) 检查数据是否包含逗号。如果数据中包含逗号或双引号,使用双引号将数据包裹起来。将每个字段通过逗号分隔写入 CSV 文件。
2025-01-14 14:42:00
875
原创 Android App获取root权限
在 Android 中,获取 root 权限通常意味着你需要通过 su(superuser)命令来执行具有更高权限的操作。对于系统应用(System App)来说,由于它们具有一定的系统权限,可以访问一些普通应用无法访问的资源,但它们通常并不能直接获得 root 权限,除非设备已经被 root 过。要执行带有 root 权限的命令,只需要调用上述方法并传递想要执行的命令。例如,删除一个只读文件或写入受保护的目录。
2024-12-02 09:49:02
1337
原创 Android 输入事件拦截机制
doInterceptKeyBeforeDispatchingLockedInterruptible调用Java层的interceptKeyBeforeDispatching做拦截操作,然后根据返回结果设置 key event的interceptKeyResult, 如果没有拦截,设置interceptKeyResult为INTERCEPT_KEY_RESULT_CONTINUE, 否则设置为INTERCEPT_KEY_RESULT_SKIP或TRY_AGAIN.
2024-11-30 23:01:49
1081
原创 android WakeLock简介
以下代码为WakeLock申请释放示例,要申请WakeLock,必须有PowerManager实例,如下。如果是通过acquire(long timeout)方法申请的超时锁,则会在到达时间后自动去释放,如果是通过acquire()方法申请的永久锁,则必须进行显式的释放,否则由于系统一直持有wakelock锁,将导致无法进入休眠状态,从而导致耗电过快等功耗问题。根据作用时间,WakeLock可以分为永久锁和超时锁,永久锁表示只要获取了WakeLock锁,必须显式的进行释放,否则系统会一直持有该锁;
2024-11-30 23:01:20
1322
原创 Android开发获取目录空间
在 Android 中,totalSpace 返回的是存储设备的总空间(以字节为单位)。该值表示该存储设备的总容量,不同于 freeSpace 和 usableSpace,后者分别表示可用的空间和当前系统可以使用的空间。
2024-11-29 09:44:32
246
原创 Android监听USB设备并获取挂载路径
在 Android 开发中,如果你想要监听 USB 设备的连接和断开事件,通常会使用 UsbManager 类来管理和处理 USB 设备的连接。Android 提供了 BroadcastReceiver 来接收系统广播,监听 USB 设备的插拔。通过创建一个 BroadcastReceiver 来监听系统发送的与 USB 设备连接相关的广播事件。首先,你需要在 AndroidManifest.xml 文件中声明 USB 权限和设备特性。动态注册 BroadcastReceiver。
2024-11-29 09:44:21
1609
原创 Android使用UVCCamera打开USBCamera-预览
获取TextureView的Surface,开启预览。写一个管理类封装UVCCamera相关API。导入libuvccamera.aar。
2024-11-28 09:29:36
1574
原创 Android使用UVCCamera打开USBCamera-编译
直接删除下面引用,后面根据编译报错删除HandlerThreadHandler和BuildCheck相关API的调用,不影响后面使用。执行后生成libuvccamera\build\outputs\aar\libuvccamera-release.aar。NDK版本过高,我这边使用r12版本,下载地址。在local.properties文件后添加。修改build.gradle文件。libcommon库问题。
2024-11-27 09:44:10
1284
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人