当前位置: 首页 > news >正文

安卓第一个项目

测试所有摄像头

安卓CameraX:https://developer.android.com/media/grow/spatial-audio?hl=zh-cn

1、MainActivity.java

// 定义包名
package com.mms.densenapplication;// 引入 AppCompatActivity,支持兼容性更强的 Activity
import androidx.appcompat.app.AppCompatActivity;// 引入上下文和生命周期相关的类
import android.content.Context;
import android.os.Bundle;// 引入 CameraX 的预览控件
import androidx.camera.view.PreviewView;// Java 的集合类
import java.util.ArrayList;
import java.util.Map;
import java.util.List;
import java.util.HashMap;// 下拉选择框相关类
import android.widget.Spinner;
import android.widget.ArrayAdapter;
import android.widget.AdapterView;// View 相关类
import android.view.View;// Camera2 API 相关类
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraManager;// CameraX 核心组件
import androidx.camera.core.CameraSelector;
import androidx.camera.core.CameraInfo;
import androidx.camera.core.Preview;
import androidx.camera.core.ImageAnalysis;
import androidx.camera.lifecycle.ProcessCameraProvider;// 异步执行与线程池
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;// 工具类
import android.util.Size;
import android.util.Log;import androidx.core.content.ContextCompat;// CameraX 与 Camera2 的互操作类
import androidx.camera.camera2.interop.Camera2CameraInfo;public class MainActivity extends AppCompatActivity {// 摄像头预览组件private PreviewView previewView;// 摄像头选择下拉框private Spinner cameraSpinner;// 用于显示在下拉框中的摄像头列表(带说明文字)private List<String> cameraIdList = new ArrayList<>();// 用于保存显示名和真实 cameraId 的映射关系private Map<String, String> cameraIdMap = new HashMap<>();// Camera2 管理器private CameraManager cameraManager;// CameraX 的生命周期相机提供器private ProcessCameraProvider cameraProvider;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 加载布局文件 activity_main.xmlsetContentView(R.layout.activity_main);// 获取布局中的预览视图和摄像头选择下拉框控件previewView = findViewById(R.id.previewView);cameraSpinner = findViewById(R.id.cameraSpinner);// 获取系统摄像头服务cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);try {// 遍历系统中所有摄像头for (String id : cameraManager.getCameraIdList()) {// 获取该摄像头的属性CameraCharacteristics cc = cameraManager.getCameraCharacteristics(id);// 获取摄像头朝向(前置/后置)Integer facing = cc.get(CameraCharacteristics.LENS_FACING);// 生成显示用的摄像头名称String name = "Camera ID: " + id;if (facing != null) {if (facing == CameraCharacteristics.LENS_FACING_BACK) name += " (BACK)";else if (facing == CameraCharacteristics.LENS_FACING_FRONT) name += " (FRONT)";else name += " (EXTERNAL)";}// 添加到显示列表和 ID 映射表中cameraIdList.add(name);cameraIdMap.put(name, id);}} catch (CameraAccessException e) {e.printStackTrace();}// 设置下拉框的适配器ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, cameraIdList);cameraSpinner.setAdapter(adapter);// 当用户选择某个摄像头时触发cameraSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {@Overridepublic void onItemSelected(AdapterView<?> parent, View view, int position, long id) {// 获取选中的显示项String selected = cameraIdList.get(position);// 查找对应的真实摄像头 IDString realCameraId = cameraIdMap.get(selected);// 调用绑定摄像头的方法if (realCameraId != null) {bindCamera(realCameraId);}}@Override public void onNothingSelected(AdapterView<?> parent) {}});// 异步获取 ProcessCameraProvider 实例(生命周期感知)ProcessCameraProvider.getInstance(this).addListener(() -> {try {cameraProvider = ProcessCameraProvider.getInstance(this).get();} catch (ExecutionException | InterruptedException e) {e.printStackTrace();}}, ContextCompat.getMainExecutor(this));}/*** 绑定指定 ID 的摄像头,并显示预览及处理图像帧*/private void bindCamera(String cameraId) {if (cameraProvider == null) return;// 解绑之前所有的摄像头使用cameraProvider.unbindAll();// 构建 CameraSelector,通过 cameraId 过滤匹配的摄像头CameraSelector cameraSelector = new CameraSelector.Builder().addCameraFilter(cameras -> {List<CameraInfo> matched = new ArrayList<>();for (CameraInfo info : cameras) {// 将 CameraInfo 转换为 Camera2CameraInfo 以获取其 cameraIdCamera2CameraInfo camera2CameraInfo = Camera2CameraInfo.from(info);if (camera2CameraInfo.getCameraId().equals(cameraId)) {matched.add(info);}}return matched;}).build();// 创建预览用的 Preview 对象,并设置其 SurfaceProviderPreview preview = new Preview.Builder().build();preview.setSurfaceProvider(previewView.getSurfaceProvider());// 创建图像分析器,并设置分辨率与策略ImageAnalysis imageAnalysis = new ImageAnalysis.Builder().setTargetResolution(new Size(224, 224)) // 设置目标分辨率.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) // 丢弃旧帧.build();// 设置分析器线程和回调(这里只打印帧大小)imageAnalysis.setAnalyzer(Executors.newSingleThreadExecutor(), image -> {Log.d("CameraDebug", "Frame: " + image.getWidth() + "x" + image.getHeight());image.close(); // 一定要关闭,否则会卡住});// 将预览和分析器绑定到生命周期cameraProvider.bindToLifecycle(this, cameraSelector, preview, imageAnalysis);}
}

2、layout/activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="match_parent"android:layout_height="match_parent"><Spinnerandroid:id="@+id/cameraSpinner"android:layout_width="match_parent"android:layout_height="wrap_content" /><androidx.camera.view.PreviewViewandroid:id="@+id/previewView"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"/>
</LinearLayout>

3、build.gradle.kts(app)

import com.android.build.gradle.internal.packaging.createDefaultDebugStoreplugins {alias(libs.plugins.androidApplication)
}android {namespace = "com.mms.densenapplication"compileSdk = 34defaultConfig {applicationId = "com.mms.densenapplication"minSdk = 30targetSdk = 34versionCode = 1versionName = "1.0"testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"ndk {
//            abiFilters += listOf("armeabi-v7a", "arm64-v8a")abiFilters += listOf("arm64-v8a")}externalNativeBuild {cmake {cppFlags("")arguments("-DANDROID_STL=c++_shared")}}}signingConfigs{getByName("debug") {storeFile = file("${project.rootDir}/platform_2.0.jks")storePassword = "android"keyAlias = "androiddebugkey"keyPassword = "android"}}buildTypes {release {isMinifyEnabled = falseproguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"),"proguard-rules.pro")}}compileOptions {sourceCompatibility = JavaVersion.VERSION_1_8targetCompatibility = JavaVersion.VERSION_1_8}externalNativeBuild {cmake {path = file("src/main/cpp/CMakeLists.txt")version = "3.22.1"}}buildFeatures {viewBinding = true}aaptOptions {noCompress("dat", "zip", "bin", "")}
}dependencies {implementation(libs.appcompat)implementation("com.fasterxml.jackson.core:jackson-databind:2.15.0")implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.15.0")implementation(libs.material)implementation(libs.constraintlayout)testImplementation(libs.junit)androidTestImplementation(libs.ext.junit)androidTestImplementation(libs.espresso.core)implementation("androidx.camera:camera-camera2:1.3.0")  // 下面三个是摄像头相关implementation("androidx.camera:camera-lifecycle:1.3.0")implementation("androidx.camera:camera-view:1.3.0")
}

4、AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:sharedUserId="android.uid.system"><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.CAMERA" />  <!-- 摄像头权限 --><applicationandroid:allowBackup="true"android:dataExtractionRules="@xml/data_extraction_rules"android:fullBackupContent="@xml/backup_rules"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/Theme.DensenApplication"tools:targetApi="31"><uses-native-libraryandroid:name="libcdsprpc.so"android:required="true" /><activityandroid:name=".MainActivity"android:exported="true"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity></application></manifest>
http://www.dtcms.com/a/290699.html

相关文章:

  • 信息学奥赛一本通 1576:【例 2】选课 | 洛谷 P2014 [CTSC1997] 选课
  • Netty中CompositeByteBuf的使用
  • 位标志法处理多选字段在数据库中的存储方式 查询效率与扩展性之间的权衡
  • https正向代理 GoProxy
  • 苹果最新系统iOS 17的调试和适配方法 - Xcode 14.3.1 真机调试指南
  • How does Misinformation Affect Large Language ModelBehaviors and Preferences?
  • Spring Boot 集成 RabbitMQ:普通队列、延迟队列与死信队列全解析
  • iOS WebView 调试实战 页面跳转失效与历史记录错乱的排查路径
  • 物流链上的智慧觉醒:Deepoc具身智能如何重塑搬运机器人的“空间思维”
  • 达梦数据库JSON_TABLE使用说明
  • grpc: debug: GRPC_TRACE
  • ESP32开发——基于idf框架使用NVS操作存储设备读写
  • 家庭服务具身智能机器人体系架构
  • 一次 POI 版本升级踩坑记录
  • lesson20:Python函数的标注
  • docker nginx 部署前端踩坑记录
  • WinUI3开发_Frame用法
  • MYSQL:数据库约束
  • 【PTA数据结构 | C语言版】拓扑排序
  • 通信刚需小能手,devicenet转PROFINET网关兼容物流分拣自动化
  • 自动化计算机经过加固后有什么好处?
  • OpenAI API(2) OpenAI Responses API使用
  • 设备管理系统(MMS)如何在工厂MOM功能设计和系统落地
  • 深入解析 Linux 硬链接与软链接:原理、区别及应用场景
  • 龙虎榜——20250721
  • Linux中ELF区域与文件偏移量的关系
  • 【AI论文】EXAONE 4.0:融合非推理模式与推理模式的统一大语言模型
  • Neovim 安装与解压 tar.gz 文件
  • AXI接口学习
  • Python 模块未找到?这样解决“ModuleNotFoundError”