最近一个应用准备上架 Google Play,其中某个 SDK 未适配 16KB 内存页大小的设备,因此需要根据设备的内存页大小进行功能屏蔽。具体做法:获取当前设备的内存页大小,若为 16KB,则禁用该 SDK 的相关功能。
先写个工具类,用于获取当前设备的内存页大小。
PageSizeHelper 定义native方法,代码贴出来如下:
java
package com.example.nativedemo;
public class PageSizeHelper {
static {
System.loadLibrary("page_size_jni"); // should is same with lib name in CMakeLists.txt
}
public static native long getPageSize();
}
再这个java文件目录执行 javac -h . PageSizeHelper.java 命令生成头文件:

可以看到生成了头文件和class文件:

其中,com_example_nativedemo_PageSizeHelper.h 文件内容如下:
cpp
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_nativedemo_PageSizeHelper */
#ifndef _Included_com_example_nativedemo_PageSizeHelper
#define _Included_com_example_nativedemo_PageSizeHelper
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_example_nativedemo_PageSizeHelper
* Method: getPageSize
* Signature: ()J
*/
JNIEXPORT jlong JNICALL Java_com_example_nativedemo_PageSizeHelper_getPageSize
(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
#endif
class文件没用,可以删了。
再右击main目录, 按照下面步骤创建jni目录:


创建好jni目录如下:

再把头文件移动到该jni目录。
再在jni目录里创建c++文件实现其功能, page_size_jni.cpp内容如下:
cpp
#include <jni.h>
#include <unistd.h>
#include "com_example_nativedemo_PageSizeHelper.h"
extern "C"
JNIEXPORT jlong JNICALL JNICALL Java_com_example_nativedemo_PageSizeHelper_getPageSize
(JNIEnv * env, jclass cls) {
// sysconf(_SC_PAGESIZE) 返回 long,直接转为 jlong
long pageSize = sysconf(_SC_PAGESIZE);
return (jlong) pageSize;
}
其中sysconf是一个c语言库函数,获取系统当前的各项配置信息或限制值, 使用它需要包含<unistd.h> 头文件。
Jni目录创建CMakeLists.txt,步骤:

CMakeLists.txt 内容如下:
bash
cmake_minimum_required(VERSION 3.4.1)
project("zx_native") # 项目名称 可以随意修改
# 添加一个共享库,名称必须与 System.loadLibrary() 中一致
add_library(
page_size_jni # 库名, System.loadLibrary("page_size_jni") 就是加载的这个库
SHARED # 动态库
page_size_jni.cpp # 源文件
)
# 可选:如果需要查找 log 库等,可以添加
# find_library(log-lib log)
# target_link_libraries(page_size_jni ${log-lib})
修改app/build.gradle.kts :

app/build.gradle.kts完整内容如下:
Groovy
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.compose)
}
android {
namespace = "com.example.nativedemo"
compileSdk = 36
defaultConfig {
applicationId = "com.example.nativedemo"
minSdk = 29
targetSdk = 36
versionCode = 1
versionName = "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
ndk {
abiFilters.addAll(listOf("arm64-v8a", "armeabi-v7a"))
}
externalNativeBuild {
cmake {
cppFlags("-std=c++17")
}
}
ndkVersion = "30.0.14904198"
}
externalNativeBuild {
cmake {
path = file("src/main/jni/CMakeLists.txt")
}
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
buildFeatures {
viewBinding = true
}
}
dependencies {
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.appcompat)
implementation(libs.androidx.material)
// Compose 可以保留
implementation(libs.androidx.lifecycle.runtime.ktx)
implementation(libs.androidx.activity.compose)
implementation(platform(libs.androidx.compose.bom))
implementation(libs.androidx.compose.ui)
implementation(libs.androidx.compose.ui.graphics)
implementation(libs.androidx.compose.ui.tooling.preview)
implementation(libs.androidx.compose.material3)
// MVI核心依赖
implementation(libs.androidx.lifecycle.viewmodel.ktx)
implementation(libs.kotlinx.coroutines.android)
implementation(libs.androidx.recyclerview)
implementation(libs.androidx.swiperefreshlayout)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
}
同步报错:

下载ndk:

下载完再同步就ok了。
在MainActivity测试下:

运行:

ok. 获取到了,看下对不对,用adb命令再看下PAGESIZE值:

ok. 获取到了。