Android 获取系统内存页大小:sysconf(_SC_PAGESIZE) 与 JNI 实现

最近一个应用准备上架 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. 获取到了。

相关推荐
千里马学框架3 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台3 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone3 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc3 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo3 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077003 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼3 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone3 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen3 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone3 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui