Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Android

วิธีถ่ายภาพแบบโปรแกรมใน Android (Camera Intent)

ภาพรวม

ตัวอย่างนี้สาธิตการถ่ายภาพโดยใช้ Camera App ของระบบผ่าน MediaStore.ACTION_IMAGE_CAPTURE Intent และรับภาพคืนมาแสดงใน ImageView

ขั้นตอนที่ 1: สร้างโปรเจกต์ใหม่

เปิด Android Studio เลือก File → New Project

ขั้นตอนที่ 2: Layout (activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@id/imageView"
        android:layout_centerInParent="true"
        android:layout_marginBottom="10dp"
        android:text="Tap button to take photo from camera"
        android:textAlignment="center"
        android:textColor="@android:color/holo_purple"
        android:textSize="16sp"
        android:textStyle="bold" />

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_above="@id/btnCaptureImage"
        android:layout_marginTop="16dp"
        android:layout_weight="1"
        android:scaleType="centerCrop"
        android:src="@drawable/ic_baseline_image_24" />

    <Button
        android:id="@+id/btnCaptureImage"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:text="Capture Image" />

</RelativeLayout>

ขั้นตอนที่ 3: MainActivity.kt

import android.Manifest
import android.content.ContentValues
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.provider.MediaStore
import android.widget.Button
import android.widget.ImageView
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat

class MainActivity : AppCompatActivity() {
    private lateinit var imageView: ImageView
    private lateinit var button: Button
    private var imageUri: Uri? = null

    // ใช้ Activity Result API (สมัยใหม่ แทน onActivityResult)
    private val takePictureLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
        if (result.resultCode == RESULT_OK) {
            imageUri?.let { uri ->
                imageView.setImageURI(uri)
            }
        } else {
            Toast.makeText(this, "Photo capture cancelled", Toast.LENGTH_SHORT).show()
        }
    }

    private val requestPermissionLauncher = registerForActivityResult(ActivityResultContracts.RequestPermission()) { granted ->
        if (granted) {
            openCamera()
        } else {
            Toast.makeText(this, "Camera permission denied", Toast.LENGTH_SHORT).show()
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        title = "KotlinApp"

        imageView = findViewById(R.id.imageView)
        button = findViewById(R.id.btnCaptureImage)

        button.setOnClickListener {
            checkPermissionAndOpenCamera()
        }
    }

    private fun checkPermissionAndOpenCamera() {
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) 
            == PackageManager.PERMISSION_GRANTED) {
            openCamera()
        } else {
            requestPermissionLauncher.launch(Manifest.permission.CAMERA)
        }
    }

    private fun openCamera() {
        // สร้าง URI สำหรับเก็บรูป (ใช้ MediaStore)
        val values = ContentValues().apply {
            put(MediaStore.Images.Media.TITLE, "New Picture")
            put(MediaStore.Images.Media.DESCRIPTION, "From Camera App")
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                put(MediaStore.Images.Media.RELATIVE_PATH, "Pictures/${getString(R.string.app_name)}")
            }
        }

        imageUri = contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)

        val cameraIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE).apply {
            putExtra(MediaStore.EXTRA_OUTPUT, imageUri)
            // ให้ผลลัพธ์คุณภาพสูง
            putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1)
        }

        // ตรวจสอบว่ามี App รองรับ Intent นี้
        if (cameraIntent.resolveActivity(packageManager) != null) {
            takePictureLauncher.launch(cameraIntent)
        } else {
            Toast.makeText(this, "No camera app found", Toast.LENGTH_SHORT).show()
        }
    }
}

วิธีเก่า (Deprecated) - onActivityResult

// Deprecated ใน API 30+
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    if (requestCode == IMAGE_CAPTURE_CODE && resultCode == RESULT_OK) {
        imageUri?.let { imageView.setImageURI(it) }
    }
}

ขั้นตอนที่ 4: Manifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
    package="com.example.cameraapp">

    <uses-permission android:name="android.permission.CAMERA" />
    <uses-feature android:name="android.hardware.camera" android:required="true" />
    <uses-feature android:name="android.hardware.camera.autofocus" android:required="false" />

    <application ... >
        <activity android:name=".MainActivity"> ... </activity>
        
        <!-- สำหรับ Android 10+ (Scoped Storage) -->
        <provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="${applicationId}.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
        </provider>
    </application>
</manifest>

file_paths.xml (res/xml/file_paths.xml)

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="https://schemas.android.com/apk/res/android">
    <external-files-path name="camera_photos" path="Pictures/" />
    <external-cache-path name="camera_cache" path="." />
</paths>

หมายเหตุสำคัญ

  • ทดสอบบนอุปกรณ์จริงเท่านั้น Emulator จำลองกล้องได้แต่ไม่เหมือนจริง
  • ใช้ Activity Result API (registerForActivityResult) แทน onActivityResult ที่ Deprecated
  • Scoped Storage (Android 10+): ใช้ MediaStore + FileProvider ไม่ใช่ File URI ตรงๆ
  • รูปภาพจะเก็บใน Gallery อัตโนมัติ (Pictures/<AppName>/)
  • ควรจัดการ Rotation ของรูป (EXIF Orientation) หากแสดงผิดทิศทาง

การทดสอบ

รันบนโทรศัพท์จริง กด "Capture Image" → เลือก Camera App → ถ่ายรูป → ยืนยัน → รูปจะแสดงใน ImageView