SDL2:Android APP编译使用
SDL2:Android APP编译使用
- 3. SDL2:Android APP编译使用
- 3.1 Android Studio环境准备:
- 3.2 构建Android APP
- (1)方式一:快速构建APK工程
- (2)方式二:自定义APK工程
- (3)方式三:CMake构建APK工程
- 3.3 android-project 项目文件说明
3. SDL2:Android APP编译使用
参考:https://github.com/mayzelf/SDL2/blob/release-2.28.4/docs/README-android.md
3.1 Android Studio环境准备:
(1)安装JDK、Android Studio
(2)安装Android SDK、Android NDK
export AS_DIR=$MY_ENV_HOME/App/Android_Studio/android-studio-2022.1.1.19
export ANDROID_HOME=$MY_ENV_HOME/App/Android_Studio/Android-2022.1.1.19
export ANDROID_NDK_HOME=$ANDROID_HOME/Sdk/ndk/28.0.12674087
export PATH=$PATH:$AS_DIR
3.2 构建Android APP
先下载SDL2源代码,SDL2官方网站下载或以下方式:
wget https://www.libsdl.org/release/SDL2-2.28.4.tar.gz
tar -zxvf SDL2-2.28.4.tar.gz
mv SDL2-2.28.4 /home/SDL
有以下方式,构建不同程度需求的APK:
(1)方式一:快速构建APK工程
cd /home/SDL
cd build-scripts
./androidbuild.sh org.libsdl.testgles ../test/testgles.c
# 或
# ./androidbuild.sh org.libsdl.audio ../test/*audio*# 输出
To build and install to a device for testing, run the following:
cd /home/SDL/build/org.libsdl.testgles
./gradlew installDebug
(2)方式二:自定义APK工程
-
将
SDL/android-project目录复制并重命名,如YOURPROJECT。 -
将
SDL目录移动或符号链接到YOURPROJECT/app/jni目录。 -
编辑
YOURPROJECT/app/jni/src/Android.mk以包含您的源文件:
- 它们应该在
LOCAL_SRC_FILES :=声明后用空格分隔
4a. 如想用 Android Studio,只需打开您的YOURPROJECT目录并开始构建。
4b. 如要手动构建,在项目目录运行 ./gradlew installDebug。
- 它将在任何连接的 Android 设备上构建和安装您的 .apk
实际操作如下:
# 构建工程目录
cp -rf SDL/android-project/ YOURPROJECT
cp -rf SDL YOURPROJECT/app/jni/SDL# APK工程相应修改# (1) 替换源和gradle版本:# 打开YOURPROJECT/gradle/wrapper/gradle-wrapper.properties#distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zipdistributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-7.5-bin.zip# 打开YOURPROJECT/build.gradle// classpath 'com.android.tools.build:gradle:8.1.1'classpath 'com.android.tools.build:gradle:7.4.0'# (2) 添加音频权限声明: 在AndroidManifest.xml中添加<uses-permission android:name="android.permission.RECORD_AUDIO"/># (3) 生成源文件:YOURPROJECT/app/jni/src/*.cpp(例如testSDL2.cpp, 代码详情附在下面)# 在YOURPROJECT/app/jni/src/Android.mk中,“LOCAL_SRC_FILES := ” 声明*.cpp后用空格分隔# 编译运行apk# 方式一:用 Android Studio构建# 方式二:运行 ./gradlew installDebug
#include "SDL.h"#include <stdlib.h>
#include <stdio.h>static SDL_AudioSpec spec;
static SDL_AudioDeviceID devid_in = 0;
static SDL_AudioDeviceID devid_out = 0;static void
audio_callback(void *userdata, Uint8 *stream, int len)
{// 这里可以添加音频处理逻辑SDL_Log("标志:音频回调函数被调用,数据长度 = %d\n", len);
}int main(int argc, char **argv)
{SDL_AudioSpec wanted;int devcount;int i;/* 启用标准应用程序日志 */SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);/* 加载SDL库 */if (SDL_Init(SDL_INIT_AUDIO) < 0) {SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "标志:无法初始化SDL: %s\n", SDL_GetError());return 1;}SDL_Log("标志:使用的音频驱动: %s\n", SDL_GetCurrentAudioDriver());devcount = SDL_GetNumAudioDevices(SDL_TRUE);for (i = 0; i < devcount; i++) {SDL_Log("标志:捕获设备 #%d: '%s'\n", i, SDL_GetAudioDeviceName(i, SDL_TRUE));}SDL_zero(wanted);wanted.freq = 44100; // 采样率wanted.format = AUDIO_S16SYS; // 格式wanted.channels = 1; // 通道数wanted.samples = 1024; // 样本数wanted.callback = audio_callback;SDL_zero(spec);/* 打开默认播放设备 */SDL_Log("标志:打开默认播放设备...\n");devid_out = SDL_OpenAudioDevice(NULL, SDL_FALSE, &wanted, &spec, SDL_AUDIO_ALLOW_ANY_CHANGE);if (!devid_out) {SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "标志:无法打开音频播放设备: %s!\n", SDL_GetError());SDL_Quit();exit(1);}/* 打开默认捕获设备 */SDL_Log("标志:打开默认捕获设备...\n");// devid_in = SDL_OpenAudioDevice(NULL, SDL_TRUE, &spec, &spec, 0);devid_in = SDL_OpenAudioDevice(SDL_GetAudioDeviceName(0, SDL_TRUE), SDL_TRUE, &spec, &spec, 0);if (!devid_in) {SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "标志:无法打开音频捕获设备: %s!\n", SDL_GetError());SDL_Quit();exit(1);}SDL_Log("标志:音频设备成功打开!\n");/* 启动音频播放和捕获 */SDL_PauseAudioDevice(devid_out, 0);SDL_PauseAudioDevice(devid_in, 0);SDL_Log("标志:音频播放和捕获已启动。按回车键停止。\n");/* 等待用户输入停止 */getchar();/* 停止音频播放和捕获 */SDL_PauseAudioDevice(devid_out, 1);SDL_PauseAudioDevice(devid_in, 1);SDL_Log("标志:关闭音频设备。\n");/* 关闭音频设备 */SDL_CloseAudioDevice(devid_out);SDL_CloseAudioDevice(devid_in);/* 退出SDL库 */SDL_Quit();return 0;
}
(3)方式三:CMake构建APK工程
-
将
SDL/android-project目录复制并重命名,如YOURPROJECT。 -
将
SDL目录移动或符号链接到YOURPROJECT/app/jni目录。 -
编辑
YOURPROJECT/app/build.gradle:注掉 ndk-build 的部分,取消注释 cmake 部分。向CMake调用添加参数。
4.编辑YOURPROJECT/app/jni/CMakeLists.txt以包含您的项目(默认添加src子目录):
-
请注意,您的项目中将
SDL2、SDL2main 和 SDL2-static作为目标,因此您的 CMakeLists.txt 文件中应该有target_link_libraries(yourgame SDL2 SDL2main)。 -
另请注意,对包含
main函数的目标,应使用add_library()而不是add_executable()。
5a. 如想用 Android Studio,只需打开您的YOURPROJECT目录并开始构建。
6b. 如要手动构建,在项目目录运行 ./gradlew installDebug。
- 它将在任何连接的 Android 设备上构建和安装您的 .apk
3.3 android-project 项目文件说明
android-project/appbuild.gradle - 构建信息,包括应用程序版本和SDKsrc/main/AndroidManifest.xml - 包清单。其中包含主Activity的类名和应用程序的包名等信息。jni/ - 存放原生代码的目录jni/Application.mk - 应用程序JNI设置,包括目标平台和STL库jni/Android.mk - 可递归调用所有子目录中Android.mk文件的Android makefilejni/CMakeLists.txt - 顶级CMake项目,将SDL作为子项目添加jni/SDL/ - (指向)存放SDL库文件的目录jni/SDL/Android.mk - 创建SDL共享库的Android makefilejni/src/ - 存放C/C++源代码的目录jni/src/Android.mk - 你应该定制的Android makefile,用于包含源代码和任何库引用jni/src/CMakeLists.txt - 你可以定制的CMake文件,用于包含源代码和任何库引用src/main/assets/ - 存放应用程序资产文件的目录src/main/res/ - 存放应用程序资源的目录src/main/res/mipmap-* - 存放不同手机硬件图标文件的目录src/main/res/values/strings.xml - 应用程序中使用的字符串,包括应用程序名称src/main/java/org/libsdl/app/SDLActivity.java - 处理SDL初始化和绑定的Java类。要非常小心地修改这个类,因为SDL库依赖于这个实现。你应该为你的应用程序继承这个类。
.
声明:资源可能存在第三方来源,若有侵权请联系删除!
相关文章:
SDL2:Android APP编译使用
SDL2:Android APP编译使用 3. SDL2:Android APP编译使用3.1 Android Studio环境准备:3.2 构建Android APP(1)方式一:快速构建APK工程(2)方式二:自定义APK工程(…...
linux systemd 服务连续启动失败,不会再重启分析
1. 问题现象 在Linux 系统中,将自已写的可执行文件放到 systemd 服务中做成service 服务,以支持开机自启和失败重启。但是发现服务在重启多次失败后再也起不来,服务状态是 failed,并且报 start request repeated too quickly. 2.…...
【云岚到家】-day03-门户缓存方案选择
【云岚到家】-day03-门户缓存方案选择 1.门户常用的技术方案 什么是门户 说到门户马上会想到门户网站,中国比较早的门户网站有新浪、网易、搜狐、腾讯等,门户网站为用户提供一个集中的、易于访问的平台,使他们能够方便地获取各种信息和服务…...
在IDEA中使用通义灵码插件:全面提升开发效率的智能助手
在IDEA中使用通义灵码插件:全面提升开发效率的智能助手 随着软件开发行业对效率和质量要求的不断提高,开发者们一直在寻找能够简化工作流程、提升代码质量的工具。阿里云推出的通义灵码插件正是这样一个旨在帮助开发者更高效地编写高质量代码的强大工具…...
【正则表达式】从0开始学习正则表达式
正则表达式(英语:Regular Expression,在代码中常简写为regex、regexp或RE) 一、推荐学习网站 正则表达式 – 语法 | 菜鸟教程 正则表达式30分钟入门教程 | 菜鸟教程 编程胶囊-打造学习编程的最好系统 二、必知必记 2.1 元字符…...
PHP智慧小区物业管理小程序
🌟智慧小区物业管理小程序:重塑社区生活,开启便捷高效新篇章 🌟 智慧小区物业管理小程序是一款基于PHPUniApp精心雕琢的智慧小区物业管理小程序,它犹如一股清新的科技之风,吹进了现代智慧小区的每一个角落…...
Linux安装Docker教程(详解)
如果想要系统学习docker,建议进入官方文档中学习:docker官方文档 一. 基本概念 Docker Desktop 和 Docker Engine 有什么区别? Docker Desktop for Linux 提供用户友好的图形界面,可简化容器和服务的管理。它包括 Docker Engine,…...
开源AI微调指南:入门级简单训练,初探AI之路
112,如何让 113? 简单的微调你的 AI, 微调前的效果,怎么调教它都是 112. 要对其进行微调(比如训练113),可以按以下步骤进行。 确保你已经安装了以下工具和库: ollamallama3.2Pyt…...
Leetcode 91. 解码方法 动态规划
原题链接:Leetcode 91. 解码方法 自己写的代码: class Solution { public:int numDecodings(string s) {int ns.size();vector<int> dp(n,1);if(s[n-1]0) dp[n-1]0;for(int in-2;i>0;i--){if(s[i]!0){string ts.substr(i,2);int tmpatoi(t.c…...
ASP .NET Core 学习(.NET9)配置接口访问路由
新创建的 ASP .NET Core Web API项目中Controller进行请求时,是在地址:端口/Controller名称进行访问的,这个时候Controller的默认路由配置如下 访问接口时,是通过请求方法(GET、Post、Put、Delete)进行接口区分的&…...
将 AzureBlob 的日志通过 Azure Event Hubs 发给 Elasticsearch(2 换掉付费的Event Hubs)
前情回顾: 将 AzureBlob 的日志通过 Azure Event Hubs 发给 Elasticsearch(1)-CSDN博客 前边的方案是挺好的,但 Azure Event Hubs 是付费服务,我这里只是一个获取日志进行必要的分析,并且不要求实时性&am…...
idea 如何安装 github copilot
idea 如何安装 github copilot 要在 IntelliJ IDEA 中安装 GitHub Copilot,可以按照以下步骤操作: 打开 IntelliJ IDEA: 启动 IntelliJ IDEA。 打开插件管理器: 点击菜单栏中的 File。 选择 Settings(Windows/Linux)或 Prefere…...
1.17学习
crypto nssctf-[SWPUCTF 2021 新生赛]crypto8 不太认识这是什么编码,搜索一下发现是一个UUENCODE编码,用在线工具UUENCODE解码计算器—LZL在线工具解码就好 misc buuctf-文件中的秘密 下载附件打开后发现是一个图片,应该是一个图片隐写&…...
Redis系列之底层数据结构整数集IntSet
Redis系列之底层数据结构整数集IntSet 什么是IntSet IntSet,整数集合,是Redis集合类型的一种底层数据结构,当一个集合只包含整数值元素,并且这个集合的元素数量不多时,redis就会选用intset作为底层实现。 IntSet的数…...
外包公司名单一览表(成都)
大家好,我是苍何。 之前写了一篇武汉的外包公司名单,评论区做了个简单统计,很多人说,在外包的日子很煎熬,不再想去了。 有小伙伴留言说有些外包会强制离职,不行就转岗,让人极度没有安全感。 这…...
个人vue3-学习笔记
声明:这只是我个人的学习笔记(黑马),供以后复习用 。一天学一点,随时学随时更新。明天会更好的! 这里只给代码,不给运行结果,看不出来代码的作用我也该进厂了。。。。。 Day1 使用create-vue创建项目。 1.检查版本。 node -v 2.创建项目 npm init vue@latest 可…...
STM32 FreeRTOS消息队列
队列简介 队列是任务间通信的主要形式。 它们可以用于在任务之间以及中断和任务之间发送消息。 队列是线程安全的数据结构,任务可以通过队列在彼此之间传递数据。有以下关键特点: FIFO顺序:队列采用先进先出 (FIFO) 的顺序,即先…...
Datawhale-self-llm-Phi-4 Langchain接入教程
本项目是一个围绕开源大模型、针对国内初学者、基于 AutoDL 平台的中国宝宝专属大模型教程,针对各类开源大模型提供包括环境配置、本地部署、高效微调等技能在内的全流程指导,简化开源大模型的部署、使用和应用流程,让更多的普通学生、研究者…...
窥探QCC518x/308x系列与手机之间的蓝牙HCI记录与分析 - 手机篇
今天要介绍给大家的是, 当我们在开发高通耳机时如果遇到与手机之间相容性问题, 通常会用Frontline或Ellisys的Bluetooth Analyzer来截取资料分析, 如果手边没有这样的仪器, 要如何窥探Bluetooth的HCI log.这次介绍的是手机篇. 这次跟QCC518x/QCC308x测试的手机是Samsung S23 U…...
Golang Gin系列-1:Gin 框架总体概述
本文介绍了Gin框架,探索了它的关键特性,并建立了简单入门的应用程序。在这系列教程里,我们会探索Gin的主要特性,如路由、中间件、数据库集成等,最终能使用Gin框架构建健壮的web应用程序。 总体概述 Gin是Go编程语言的…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...
《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...
测试markdown--肇兴
day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...
相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...
C# SqlSugar:依赖注入与仓储模式实践
C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...
如何在最短时间内提升打ctf(web)的水平?
刚刚刷完2遍 bugku 的 web 题,前来答题。 每个人对刷题理解是不同,有的人是看了writeup就等于刷了,有的人是收藏了writeup就等于刷了,有的人是跟着writeup做了一遍就等于刷了,还有的人是独立思考做了一遍就等于刷了。…...
.Net Framework 4/C# 关键字(非常用,持续更新...)
一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...
