Android-Studio-NativeActivity创建流程
1. Android-Studio和Android.mk方案 - 配置解析
1. 新建Android-studio工程
选择Native C++就可以了
2. 修改AndroidManifest.xml文件
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.opensl_triangle">
<!-- 1. 没有java代码,设置android:hasCode="false" -->
<application
android:allowBackup="true"
android:hasCode="false"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<!-- 2. 将activity替换为nativeactivity -->
<activity android:name="android.app.NativeActivity">
<!-- 告诉nativeactivity它的库名为Hello_Triangle -->
<meta-data android:name="android.app.lib_name"
android:value="Hello_Triangle" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
3. ndk配置
1. 打开local.properties,添加:
ndk.dir=C\:\\Users\\jetson\\AppData\\Local\\Android\\Sdk\\ndk\\22.0.7026061
2. 打开gradle.properties,添加:
android.useDeprecatedNdk=true
3. 右键cpp文件夹,然后选link c++ project with gradle,选择jni下的Android.mk文件
4. 删除java文件夹
5. 配置Android.mk文件,调整文件夹
LOCAL_PATH := $(call my-dir)
COMMON_PATH := $(LOCAL_PATH)/../Common
COMMON_INC_PATH := $(COMMON_PATH)/Include/
COMMON_SRC_PATH := $(COMMON_PATH)/Source
include $(CLEAR_VARS)
# 要编译生成的库,和上面AndroidManifest.xml文件中<meta-data android:name="android.app.lib_name" android:value="Hello_Triangle" />配置一致
LOCAL_MODULE := Hello_Triangle
# 定义ANDROID宏
LOCAL_CFLAGS += -DANDROID
LOCAL_SRC_FILES := $(COMMON_SRC_PATH)/esShader.c \
$(COMMON_SRC_PATH)/esShapes.c \
$(COMMON_SRC_PATH)/esTransform.c \
$(COMMON_SRC_PATH)/esUtil.c \
$(COMMON_SRC_PATH)/esUtil_Android.c \
$(LOCAL_PATH)/Hello_Triangle.c
LOCAL_C_INCLUDES := $(COMMON_INC_PATH)
# 需要链接EGL的库
LOCAL_LDLIBS := -llog -landroid -lEGL -lGLESv3
# 需要android_native_app_glue静态库
LOCAL_STATIC_LIBRARIES := android_native_app_glue
include $(BUILD_SHARED_LIBRARY)
# 需要import native_app_glue
$(call import-module,android/native_app_glue)
2. 源码解析
1. nativeactivity实现框架
1. 进入到android_main函数
///
// android_main()
//
// Main entrypoint for Android application
//
void android_main ( struct android_app *pApp )
{
ESContext esContext;
float lastTime;
// Make sure glue isn't stripped.
app_dummy();
// Initialize the context
memset ( &esContext, 0, sizeof ( ESContext ) );
esContext.platformData = ( void * ) pApp->activity->assetManager;
// 1. 设置轮询回调函数
pApp->onAppCmd = HandleCommand;
// 2. 设置私有的数据,可以在各个函数中获取,如回调函数中
pApp->userData = &esContext;
lastTime = GetCurrentTime();
while ( 1 )
{
int ident;
int events;
struct android_poll_source *pSource;
// 3. 调用onAppCmd中的回调函数来处理事件
while ( ( ident = ALooper_pollAll ( 0, NULL, &events, ( void ** ) &pSource ) ) >= 0 )
{
if ( pSource != NULL )
{
pSource->process ( pApp, pSource );
}
if ( pApp->destroyRequested != 0 )
{
return;
}
}
if ( esContext.eglNativeWindow == NULL )
{
continue;
}
// Call app update function
if ( esContext.updateFunc != NULL )
{
float curTime = GetCurrentTime();
float deltaTime = ( curTime - lastTime );
lastTime = curTime;
esContext.updateFunc ( &esContext, deltaTime );
}
// 处理完事件之后,就进行绘制操作
if ( esContext.drawFunc != NULL )
{
esContext.drawFunc ( &esContext );
eglSwapBuffers ( esContext.eglDisplay, esContext.eglSurface );
}
}
}
2. 进入到HandleCommand函数中
static void HandleCommand ( struct android_app *pApp, int32_t cmd )
{
ESContext *esContext = ( ESContext * ) pApp->userData;
switch ( cmd )
{
case APP_CMD_SAVE_STATE:
// the OS asked us to save the state of the app
break;
case APP_CMD_INIT_WINDOW:
// 进行初始化操作
esContext->eglNativeDisplay = EGL_DEFAULT_DISPLAY;
esContext->eglNativeWindow = pApp->window;
// Call the main entrypoint for the app
if ( esMain ( esContext ) != GL_TRUE )
{
exit ( 0 ); //@TEMP better way to exit?
}
break;
case APP_CMD_TERM_WINDOW:
// Cleanup on shutdown
if ( esContext->shutdownFunc != NULL )
{
esContext->shutdownFunc ( esContext );
}
if ( esContext->userData != NULL )
{
free ( esContext->userData );
}
memset ( esContext, 0, sizeof ( ESContext ) );
break;
case APP_CMD_LOST_FOCUS:
// if the app lost focus, avoid unnecessary processing (like monitoring the accelerometer)
break;
case APP_CMD_GAINED_FOCUS:
// bring back a certain functionality, like monitoring the accelerometer
break;
}
}
///
// Global extern. The application must declare this function
// that runs the application.
//
extern int esMain ( ESContext *esContext );
//////////////////////////////////////////////////////////////////
//
// Public Functions
//
//
综上所述,总的流程为:
初始化操作 -> 进行绘制 -> 退出
问题
1. avd emulator不支持OpenGL 3.0
点击emulator的... -> Settings -> Advanced -> OpenGL ES API level -> 选择3.1 -> 重启即可
参考
1. 示例:native-activity
https://developer.android.com/ndk/samples/sample_na?hl=zh-cn
2. native-activity的示例代码:
https://github.com/android/ndk-samples/tree/main/native-activity
3. NativeActivity开发示例-使用AndroidStudio和CMake
https://www.jianshu.com/p/f91ba94b60f4
4. avd emulator不支持OpenGL 3.0
https://stackoverflow.com/questions/40797975/android-emulator-and-opengl-es3-egl-bad-config
5. 源码位置: