8
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

スマプロAdvent Calendar 2023

Day 17

Jetpack Composeでカメラアプリを作ろう!

Last updated at Posted at 2023-12-17

今回のアプリ

アプリにカメラの許可を与える
スクリーンショット 2023-12-16 20.39.07.png
カメラ機能
スクリーンショット 2023-12-16 20.38.36.png

はじめに

今、開発中のアプリでカメラ機能を実装した!!!!!
でも、JetpackComposeでカメラ機能を使う情報が少ないい!!!
そこで、あらゆるサイトを調べてまくって実装までこぎつけました。
今回は、その内容をまとめてみました。

# 開発環境
Android Studio Flamingo | 2022.2.1 Patch 2
MacBook Air M2

1 プロジェクトを作成する

スクリーンショット 2023-12-16 20.49.37.png
EmptyActivityを選びます
スクリーンショット 2023-12-16 20.49.59.png
プロジェクト名を「myCamera」
MinimumSDK「API29:Android 10.0(Q)」

2 必要な権限をリクエストします

スクリーンショット 2023-12-16 20.57.40.png
AndroidManifest.xml を開き、application タグの前に次の行を追加します。
コード

<uses-feature android:name="android.hardware.camera.any" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"android:maxSdkVersion="28" />

3 CameraX の依存関係を追加する

def camerax_version = "1.2.1"
implementation "androidx.camera:camera-core:${camerax_version}"
implementation "androidx.camera:camera-camera2:${camerax_version}"
implementation "androidx.camera:camera-lifecycle:${camerax_version}"
implementation "androidx.camera:camera-video:${camerax_version}"
implementation "androidx.camera:camera-view:${camerax_version}"
implementation "androidx.camera:camera-extensions:${camerax_version}"

このコードをbuild.gradle(Module:app)に追加します。

4 AccompanistのPermissionsライブラリを追加する

JetpackComposeでパーミッションを取得するために、必要なライブラリを追加します。

implementation "com.google.accompanist:accompanist-permissions:0.28.0"

このコードをbuild.gradle(Module:app)に追加します。
ここまでで、下準備は終わりです。

5 アプリ作成開始

MainActivity

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MyCameraTheme {
                // A surface container using the 'background' color from the theme
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    MainCamera()
                }
            }
        }
    }
}

ここは、アプリの中心で一番最初に実行されます。後述するMainCameraを実行させます。

MainCamera

@OptIn(ExperimentalPermissionsApi::class)
@Composable
fun MainCamera() {
    val permissionState: PermissionState = rememberPermissionState(permission = Manifest.permission.CAMERA)

    if(permissionState.status.isGranted){
        CametaStert()
    }else{
        NoPermission(onRequestPermission = permissionState::launchPermissionRequest)
    }
}

この関数では、アプリにカメラの使用許可が降りているのかを判断して、
許可があればCametaStert(カメラを起動させる関数)、許可がなければNoPermission(許可をリクエストする関数)を実行する。
重要なポイントは、

val permissionState: PermissionState = rememberPermissionState(permission = Manifest.permission.CAMERA)

ここで、カメラのパーミッションの状況を取得しています。

NoPermission

@Composable
fun NoPermission(onRequestPermission:() -> Unit){
    Column(modifier = Modifier.fillMaxSize(),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center)
    {
        Button(onClick =  onRequestPermission ) {
            Text(text = "カメラの許可を与えてください")
        }
    }
}

ここでは、ユーザーに確認を取り、カメラ許可のリクエストを送ります。

CametaStert

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun CametaStert(){
    val context = LocalContext.current
    val lifecycleOwner = LocalLifecycleOwner.current
    val imageCapture =  remember {
        ImageCapture.Builder()
            .setFlashMode(ImageCapture.FLASH_MODE_AUTO) // フラッシュモードを設定
            .setTargetAspectRatio(AspectRatio.RATIO_4_3) // ターゲットのアスペクト比を設定
            .build()
    }
    val previewView = PreviewView(context).apply {
        layoutParams = LinearLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT)
        scaleType = PreviewView.ScaleType.FILL_CENTER
    }
    val cameraProviderFuture = ProcessCameraProvider.getInstance(context)
    DisposableEffect(Unit) {
        val cameraProvider = cameraProviderFuture.get()
        Log.d("cameraProvider",cameraProvider.toString())
        val preview = androidx.camera.core.Preview.Builder().build()

        val cameraSelector = CameraSelector.Builder()
            .requireLensFacing(CameraSelector.LENS_FACING_BACK)
            .build()

        preview.setSurfaceProvider(previewView.surfaceProvider)
        cameraProvider.bindToLifecycle(
            lifecycleOwner,
            cameraSelector,
            preview,
            imageCapture
        )
        onDispose {
            cameraProvider.unbindAll()
        }
    }
    Scaffold(floatingActionButton = {
        FloatingActionButton(onClick = { }) {
            Icon(imageVector = Icons.Default.Add, contentDescription = "Clothesadd")
        }
    }) {paddingValues: PaddingValues ->
     AndroidView(factory = {previewView},
         modifier = Modifier.padding(paddingValues))
    }
}

この関数では、カメラのプレビューを実装しています。

終わり

今回は、単純にプレビューを表示させるアプリを作りました。
次は、このアプリに写真を取って保存する機能を追加します。

8
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?