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. 获取到了。

相关推荐
alexhilton13 小时前
Android的Agent优先时代:构建时vs运行时
android·kotlin·android jetpack
Cutecat_14 小时前
视频字幕处理工具横向:提取模式 vs 编辑模式,该如何选择
android·前端·ios·语音识别
2601_9617652915 小时前
【分享】PlayerPro媒体音乐播放器 完整专业版
android·媒体
JohnnyDeng9417 小时前
【Android】Android 包体积优化:R8/ProGuard 深度配置全攻略
android·性能优化·kotlin·jetpack
故渊at17 小时前
第九板块:Android 多媒体体系 | 第二十四篇:Camera Service 与 HAL3 成像流水线
android·camera·多媒体体系·hal3
Jinkxs21 小时前
Python基础 - 初识内置函数 Python自带的便捷工具
android·java·python
私人珍藏库21 小时前
【Android】VLLO-韩国热门手机剪辑APP
android·app·工具·软件·多功能
Cloud_Shy6181 天前
解读《Effective Python 3rd Edition》:从练气到老魔(第六章 Item 40 - 43)
android·开发语言·人工智能·笔记·python·学习方法
AFinalStone1 天前
Android12 U盘插拔链路源码全解析(五):Framework层(下) StorageManagerService
android·frameworks
林九生1 天前
【实用技巧】MySQL 绿色版一键路径更新脚本详解 —— update_path.bat 深度解析
android·数据库·mysql