Android Camera - 获取当前设备屏幕的旋转角度、保存帧到外部存储的私有空间

获取当前设备屏幕的旋转角度

1、基本介绍
java 复制代码
@Surface.Rotation
public int getRotation() {
    synchronized (mLock) {
        updateDisplayInfoLocked();
        return getLocalRotation();
    }
}
  • 返回一个 int 常量
返回值 常量 说明
0 Surface.ROTATION_0 未旋转 0°,竖屏,顶部朝上
1 Surface.ROTATION_90 顺时针旋转 90°,左横屏,顶部朝左
2 Surface.ROTATION_180 旋转 180°,倒置,顶部朝下
3 Surface.ROTATION_270 顺时针旋转 270°,右横屏,顶部朝右
  • 注:这里的顺时针是相对于设备的自然方向而言的,而不是相对于你(用户)的视觉方向
2、演示
xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/root"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#F5F5F5"
    android:gravity="center"
    android:orientation="vertical">

    <TextView
        android:id="@+id/tv_info"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:lineSpacingExtra="12dp"
        android:textSize="24sp" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="32dp"
        android:text="\n点击屏幕刷新"
        android:textColor="#999"
        android:textSize="14sp" />
</LinearLayout>
java 复制代码
public class RotationTestActivity extends AppCompatActivity {

    private TextView tvInfo;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        EdgeToEdge.enable(this);
        setContentView(R.layout.activity_rotation_test);
        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.root), (v, insets) -> {
            Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
            return insets;
        });

        tvInfo = findViewById(R.id.tv_info);
        findViewById(R.id.root).setOnClickListener(v -> showRotation());

        showRotation();
    }

    private void showRotation() {
        int rotation = getWindowManager().getDefaultDisplay().getRotation();

        String[] map = {
                "0 → 竖屏(顶部朝上)",
                "1 → 左横屏(顶部朝左)",
                "2 → 倒置(顶部朝下)",
                "3 → 右横屏(顶部朝右)"
        };

        tvInfo.setText("getRotation() = " + rotation + "\n" + map[rotation]);
    }
}

保存帧到外部存储的私有空间

java 复制代码
private boolean saveRgbFrame = true; // 是否保存 RGB 帧
private boolean saveNirFrame = true; // 是否保存 NIR 帧
private static final String FRAME_SAVE_DIR = "FaceFrames"; // 保存目录

/**
 * 保存 NV21 格式帧数据为 JPEG 图片到本地存储
 *
 * @param data   NV21 格式的帧数据
 * @param width  图像宽度
 * @param height 图像高度
 * @param prefix 文件名前缀,例如,rgb、nir
 */
private void saveFrameToStorage(byte[] data, int width, int height, String prefix) {
    try {
        // 创建保存目录
        File saveDir = new File(MyApplication.getContext().getExternalFilesDir(null), FRAME_SAVE_DIR);
        if (!saveDir.exists()) {
            saveDir.mkdirs();
        }

        // 生成文件名:前缀_时间戳.jpg
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss_SSS", Locale.getDefault()).format(new Date());
        String fileName = prefix + "_" + timeStamp + ".jpg";
        File file = new File(saveDir, fileName);

        // 将 NV21 转换为 Bitmap 并保存为 JPEG
        Bitmap bitmap = nv21ToBitmap(data, width, height);

        FileOutputStream fos = new FileOutputStream(file);
        bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fos);
        fos.close();
        bitmap.recycle();

        Log.i(TAG, "帧已保存到:" + file.getAbsolutePath());
    } catch (IOException e) {
        Log.e(TAG, "保存帧失败:" + e.getMessage());
        e.printStackTrace();
    }
}

/**
 * 将 NV21 格式数据转换为 Bitmap
 */
private Bitmap nv21ToBitmap(byte[] nv21, int width, int height) {
    YuvImage yuvImage = new YuvImage(nv21, ImageFormat.NV21, width, height, null);
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    yuvImage.compressToJpeg(new Rect(0, 0, width, height), 100, out);
    byte[] imageBytes = out.toByteArray();
    return BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length);
}
相关推荐
阮小贰23 分钟前
干支编码的确定性实现:节气切分 + 1000 条溯源断语(附 JS 源码)
开发语言·javascript·ecmascript
niuniudengdeng25 分钟前
从小程序到 WebView:一个理发店管理系统的全栈架构设计与落地实践
java·python
DogDaoDao27 分钟前
HarmonyOS 深度解析:从微内核到 ArkTS 工程实战
android·linux·ios·华为·程序员·harmonyos·harmonyos next
LccKyI32 分钟前
C#基础编程 面试题汇总(二)
java·面试·c#
一晌小贪欢36 分钟前
Python办公17:暴力拆分——按页数或指定范围提取 PDF 核心页面
java·开发语言·python·pdf·excel·数据可视化·python办公
2401_8346369936 分钟前
Docker 容器化技术全解:从镜像构建到容器编排的完整教案1
java·docker·容器
孫治AllenSun37 分钟前
【LangChain4J-06】Prompt 工程与模板化开发
开发语言·python·prompt
jjjava2.043 分钟前
初步认识接口测试
java·可用性测试
吠品44 分钟前
TortoiseSVN 状态图标不显示的排查与解决办法
java·服务器·数据库