Android平台的原生图形与声音API开发指南
立即解锁
发布时间: 2025-08-21 02:37:15 阅读量: 1 订阅数: 6 


Android C++与NDK开发实战指南
### Android 平台的原生图形与声音 API 开发指南
#### 1. 基于 OpenGL ES 渲染器的 AVI 播放器
AVI 播放器应用程序已配备 OpenGL ES 渲染器。若要在 Android 模拟器上运行此示例应用程序,可参照 JNI 图形 API 部分的相同步骤操作。
#### 2. 使用原生窗口 API 进行渲染
从 Android API 级别 9 开始,Android NDK 提供了原生窗口 API,允许原生代码直接访问和操作原生窗口的像素缓冲区,无需涉及任何基于 Java 的 API。
##### 2.1 启用原生窗口 API
若要在原生应用程序中使用原生窗口 API,可按以下步骤操作:
1. 包含原生窗口头文件:
```c
#include <android/native_window.h>
#include <android/native_window_jni.h>
```
2. 更新 `Android.mk` 构建文件,以动态链接 `android` 库:
```makefile
LOCAL_LDLIBS += -landroid
```
##### 2.2 使用原生窗口 API
原生窗口 API 提供了四个用于访问和操作 Bitmap 对象的原生函数。
- **从 Surface 对象检索原生窗口**:
`ANativeWindow_fromSurface` 函数可从给定的 Surface 对象中检索原生窗口:
```c
ANativeWindow* ANativeWindow_fromSurface(JNIEnv* env, jobject surface);
```
该函数接受一个 JNIEnv 接口指针和一个 Surface 对象引用,并返回一个指向原生窗口实例的指针。同时,该函数会获取返回的原生窗口实例的引用,需要通过 `ANativeWindow_release` 函数释放该引用,以防止内存泄漏。
- **获取原生窗口实例的引用**:
为防止原生窗口实例被删除,原生代码可使用 `ANativeWindow_acquire` 函数获取其引用:
```c
void ANativeWindow_acquire(ANativeWindow* window);
```
每次调用 `ANativeWindow_acquire` 函数后,都应调用 `ANativeWindow_release` 函数进行平衡。
- **释放原生窗口引用**:
为防止内存泄漏,应使用 `ANativeWindow_release` 函数释放每个原生窗口引用:
```c
void ANativeWindow_release(ANativeWindow* window);
```
该函数接受一个指向原生窗口实例的指针。
- **检索原生窗口信息**:
原生窗口 API 提供了一组函数,用于获取原生窗口的信息,如尺寸和像素格式:
- `ANativeWindow_getWidth` 函数可获取原生窗口的宽度。
- `ANativeWindow_getHeight` 函数可获取原生窗口的高度。
- `ANativeWindow_getFormat` 函数可获取原生窗口的像素格式。
- **设置原生窗口缓冲区几何形状**:
原生窗口的尺寸和像素格式应与要渲染的图像数据相匹配。若图像数据的尺寸或像素格式不同,可使用 `ANativeWindow_setBuffersGeometry` 函数重新配置原生窗口缓冲区:
```c
int32_t ANativeWindow_setBuffersGeometry(ANativeWindow* window, int32_t width, int32_t height, int32_t format);
```
该函数接受一个指向先前获取的原生窗口实例的指针、新的宽度、新的高度和新的像素格式。若操作成功,返回零。若所有参数都提供零,则参数值将恢复为原生窗口缓冲区的默认值。
- **访问原生窗口缓冲区**:
`ANativeWindow_lock` 函数用于锁定原生窗口缓冲区,并获取指向原始像素缓冲区的指针:
```c
int32_t ANativeWindow_lock(ANativeWindow* window, ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds);
```
该函数接受一个指向先前获取的原生窗口实例的指针、一个指向 `ANativeWindow_Buffer` 结构的指针,以及一个可选的指向 `ARect` 结构的指针。`ANativeWindow_Buffer` 结构的定义如下:
```c
typedef struct ANativeWindow_Buffer {
int32_t width;
int32_t height;
int32_t stride;
int32_t format;
void* bits;
uint32_t reserved[6];
} ANativeWindow_Buffer;
```
若操作成功,`ANativeWindow_lock` 函数返回零。
- **释放原生窗口缓冲区**:
原生代码完成操作后,应使用 `ANativeWindow_unlockAndPost` 函数解锁并提交原生窗口缓冲区:
```c
int32_t ANativeWindow_unlockAndPost(ANativeWindow* window);
```
该函数接受一个指向已锁定的原生窗口实例的指针。若操作成功,返回零。
#### 3. 使用原生窗口渲染器更新 AVI 播放器
以下是使用原生窗口渲染器更新 AVI 播放器的步骤:
1. 使用项目资源管理器打开 `AndroidManifest.xml` 清单文件,并声明新的活动:
```xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.apress.aviplayer"
android:versionCode="1"
android:versionName="1.0" >
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".OpenGLPlayerActivity"
android:label="@string/title_activity_open_gl_player" >
</activity>
<activity
android:name=".NativeWindowPlayerActivity"
android:label="@string/title_activity_native_window_player" >
</activity>
</application>
</manifest>
```
2. 将新的 Bitmap 播放器活动的标题和 Bitmap 播放器单选按钮的标签添加到字符串资源中。打开 `strings.xml` 字符串资源文件,并添加新的字符串资源:
```xml
<resources>
<string name="title_activity_native_window_player">Native Window Player</string>
<string name="native_window_player_radio">Native Window Player</string>
</resources>
```
3. Bitmap 播放器活动需要一个 `SurfaceView` 小部件才能正常工作。使用项目资源管理器展开 `res` 目录。
4. 右键单击 `layout` 子目录,从上下文菜单中选择 `New ➤ File`。
5. 将文件名设置为 `activity_native_window_player.xml`。
6. 用以下代码替换新布局的内容:
```xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<SurfaceView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/surface_view" />
</LinearLayout>
```
7. 使用项目资源管理器展开 `src` 目录。
8. 右键单击 `com.apress.aviplayer` 包,从上下文菜单中选择 `New ➤ Class`。
9. 将名称设置为 `NativeWindowPlayerActivity`。
10. 点击 `Finish` 按钮创建新类。
11. 用以下代码替换新类的内容:
```java
package com.apress.aviplayer;
import java.util.concurrent.atomic.AtomicBoolean;
import android.os.Bundle;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import
```
0
0
复制全文
相关推荐






