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

วิธีเปิดไฟล์แสง (Flashlight) แบบโปรแกรมใน Android ด้วย Kotlin

ภาพรวม

ตัวอย่างนี้สาธิตการเปิด/ปิดไฟฉาย (Flashlight/Torch) ของกล้องหลังโดยใช้ Camera2 API (CameraManager.setTorchMode) ซึ่งเป็นวิธีมาตรฐานตั้งแต่ Android 6.0 (API 23)

ขั้นตอนที่ 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_centerHorizontal="true"
        android:layout_marginTop="50dp"
        android:text="Tutorials Point"
        android:textAlignment="center"
        android:textColor="@android:color/holo_green_dark"
        android:textSize="32sp"
        android:textStyle="bold" />

    <ToggleButton
        android:id="@+id/onOffFlashlight"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:textOff="Turn On Flashlight"
        android:textOn="Turn Off Flashlight"
        android:checked="false" />

</RelativeLayout>

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

import android.content.Context
import android.content.pm.PackageManager
import android.hardware.camera2.CameraAccessException
import android.hardware.camera2.CameraManager
import android.os.Build
import android.os.Bundle
import android.widget.CompoundButton
import android.widget.Toast
import android.widget.ToggleButton
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat

class MainActivity : AppCompatActivity() {
    private lateinit var cameraManager: CameraManager
    private lateinit var cameraId: String
    private lateinit var toggleButton: ToggleButton

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

        // ตรวจสอบว่ามี Flashlight หรือไม่
        val hasFlash = packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH)
        if (!hasFlash) {
            showNoFlashError()
            return
        }

        cameraManager = getSystemService(Context.CAMERA_SERVICE) as CameraManager

        try {
            // ใช้กล้องหลังตัวแรก (มักมี Flash)
            cameraId = cameraManager.cameraIdList.first { id ->
                val characteristics = cameraManager.getCameraCharacteristics(id)
                val facing = characteristics.get(android.hardware.camera2.CameraCharacteristics.LENS_FACING)
                facing == android.hardware.camera2.CameraCharacteristics.LENS_FACING_BACK
            }
        } catch (e: CameraAccessException) {
            e.printStackTrace()
            Toast.makeText(this, "Cannot access camera", Toast.LENGTH_SHORT).show()
            finish()
            return
        }

        toggleButton = findViewById(R.id.onOffFlashlight)
        toggleButton.setOnCheckedChangeListener { _, isChecked ->
            switchFlashLight(isChecked)
        }
    }

    private fun showNoFlashError() {
        AlertDialog.Builder(this)
            .setTitle("Oops!")
            .setMessage("Flashlight not available on this device")
            .setPositiveButton("OK") { _, _ -> finish() }
            .show()
    }

    private fun switchFlashLight(enable: Boolean) {
        try {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                cameraManager.setTorchMode(cameraId, enable)
            }
        } catch (e: CameraAccessException) {
            e.printStackTrace()
            runOnUiThread {
                toggleButton.isChecked = !enable // Revert toggle state
                Toast.makeText(this, "Failed to toggle flashlight: ${e.message}", Toast.LENGTH_SHORT).show()
            }
        }
    }

    override fun onStop() {
        super.onStop()
        // ปิดไฟฉายเมื่อแอปไปอยู่ Background
        try {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                cameraManager.setTorchMode(cameraId, false)
            }
        } catch (e: CameraAccessException) {
            e.printStackTrace()
        }
    }
}

ขั้นตอนที่ 4: Manifest (AndroidManifest.xml)

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

    <!-- สิทธิ์ Camera (จำเป็นสำหรับ Camera2 API) -->
    <uses-permission android:name="android.permission.CAMERA" />
    
    <!-- Feature Flash (บอก Play Store ว่าต้องการอุปกรณ์ที่มี Flash) -->
    <uses-feature android:name="android.hardware.camera.flash" android:required="false" />
    <uses-feature android:name="android.hardware.camera" android:required="false" />

    <application ... >
        <activity android:name=".MainActivity"> ... </activity>
    </application>
</manifest>

ขอสิทธิ์ Runtime (Android 6.0+)

Camera เป็น Dangerous Permission ต้องขอใน Runtime:

// ใน onCreate ก่อนใช้ CameraManager
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) 
    != PackageManager.PERMISSION_GRANTED) {
    ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA), CAMERA_PERMISSION_CODE)
} else {
    initCamera()
}

override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    if (requestCode == CAMERA_PERMISSION_CODE && grantResults.isNotEmpty() 
        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        initCamera()
    } else {
        Toast.makeText(this, "Camera permission required", Toast.LENGTH_SHORT).show()
        finish()
    }
}

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

  • ทดสอบบนอุปกรณ์จริงเท่านั้น Emulator ไม่มี Flashlight
  • ใช้ FEATURE_CAMERA_FLASH ไม่ใช่ FEATURE_CAMERA_FRONT (โค้ดเดิมผิด)
  • ปิดไฟฉายใน onStop() หรือ onDestroy() เพื่อไม่ให้ไฟติดค้าง
  • บางอุปกรณ์มีหลายกล้อง ต้องเลือก Camera ID ที่มี Flash (ปกติคือกล้องหลัง)
  • Android 12+ อาจต้องการ Foreground Service สำหรับ Flashlight แบบค้างนาน

การทดสอบ

รันบนโทรศัพท์จริง กด Toggle Button จะเปิด/ปิดไฟฉายได้