通过C获取Android屏幕尺寸

7

我希望能够通过C语言获取屏幕大小。我知道JNI支持从C语言调用Java代码,但是否有其他方法可以在不调用Java的情况下从低级模块中获取屏幕大小呢?

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;

public class MainActivity extends Activity
{

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
    super.onCreate(savedInstanceState);
    Log.v("getWidth", Integer.toString(getWindowManager().getDefaultDisplay().getWidth()));
    Log.v("getHeight", Integer.toString(getWindowManager().getDefaultDisplay().getHeight()));
    }
}

我认为/dev/graphics与我的问题相关。
6个回答

3

是的,你可以从/dev/graphics/fb0获取屏幕分辨率,但至少在我的手机上,读取访问权限受到root和“graphics”组中的用户的限制。无论如何,你可以像这样做(为了清晰起见,已删除错误检查):

// ... other standard includes ...
#include <sys/ioctl.h>
#include <linux/fb.h>

//...

struct fb_var_screeninfo fb_var;
int fd = open("/dev/graphics/fb0", O_RDONLY);
ioctl(fd, FBIOGET_VSCREENINFO, &fb_var);
close(fd);
// screen size will be in fb_var.xres and fb_var.yres

我不确定这些是否被认为是“公共”NDK接口,因为我不知道Google是否认为“Android在Linux上运行并使用Linux Framebuffer接口”是公共API的一部分,但它似乎可以工作。

如果您确实希望确保可移植性,您应该有一个JNI回退,调用Java WindowManager API。


1

对于像我这样寻找纯C++方法的人来说,读取/dev/graphics/fb0并不可靠。在许多设备上,它返回一个错误的结果(在我的设备上返回640 X 400)。

这是一些情况下无法使用ANativeWindowANativeWindow_Buffer的问题,例如在本地二进制可执行文件中。

对我有效的方法:

假设您有一个已root的手机,您可以处理以下命令的输出以可靠地读取分辨率。

su -c dumpsys display | grep mBaseDisplayInfo

0

你不需要缓冲区,但如果你从Java传入一个Surface,你可以使用ANativeWindow类。

void Java_com_justinbuser_nativecore_NativeMethods_setSurface(JNIEnv * env, jobject this, jobject surface){
        ANativeWindow nativeWindow = ANativeWindow_fromSurface(env, surface);
    int width =  ANativeWindow_getWidth(renderEngine->nativeWindow);
    int height = ANativeWindow_getHeight(renderEngine->nativeWindow);
}

问题是关于获取屏幕尺寸的。 - user7860670
ANativeWindow_getHeight 不可靠地减去了导航栏。 - Scorb

0

在处理本地活动时,您还可以像这样获取窗口大小,即处理APP_CMD_INIT_WINDOW“应用程序命令”:

static void engine_handle_cmd(struct android_app* app, int32_t cmd) {
struct engine* engine = (struct engine*)app->userData;
switch (cmd) {
case APP_CMD_INIT_WINDOW:
    if (engine->app->window != NULL) {
        int width = ANativeWindow_getWidth(engine->app->window);
        int height = ANativeWindow_getHeight(engine->app->window);
    }

如果你想知道如何设置engine结构体和engine_handle_cmd回调函数,请查看NDK项目中的native-activity示例中的main.c文件。


问题是关于获取屏幕尺寸的。 - user7860670

-1
要获取屏幕分辨率,您必须使用结构体ANativeWindow_Buffer
typedef struct ANativeWindow_Buffer {
    // The number of pixels that are show horizontally.
    int32_t width;

    // The number of pixels that are shown vertically.
    int32_t height;

    // The number of *pixels* that a line in the buffer takes in
    // memory.  This may be >= width.
    int32_t stride;

    // The format of the buffer.  One of WINDOW_FORMAT_*
    int32_t format;

    // The actual bits.
    void* bits;

    // Do not touch.
    uint32_t reserved[6];
} ANativeWindow_Buffer;

要获得它,请使用函数ANativeWindow_lock

/**
 * Lock the window's next drawing surface for writing.
 */
int32_t ANativeWindow_lock(ANativeWindow* window, ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds);

这里是文档

如果你正在寻找此函数的用法,请查看名为native-plasma的android-ndk示例。


问题是关于获取屏幕尺寸的。 - user7860670
1
嘿,@user7860670,感谢您的回复。我使用上面的代码来获取屏幕大小。洗手了,阿尔特姆。 - ArtemStorozhuk

-3
这对我有效:
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int height = displaymetrics.heightPixels;
int width = displaymetrics.widthPixels;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接