🔆
Jetpack Composeで、周囲の明るさを計測する
💡Tips
Androidアプリで、周囲の光の明るさを測定するセンサーアプリを作ってみました。ネイティブだと、センサーの機能が強力なので、クロスプラットフォームにはない魅了がありましたね。多くのコードを書かなくても機能を実装できた。素晴らしいな😅
実験するときは、実機のAndroid端末を使ってください。私は、Pixel7aを使っております。
SensorManager lets you access the device's sensors.
Always make sure to disable sensors you don't need, especially when your activity is paused. Failing to do so can drain the battery in just a few hours. Note that the system will not disable sensors automatically when the screen turns off.
SensorManager を使用すると、デバイスのセンサーにアクセスできます。アクティビティを一時停止しているときは特に、必要のないセンサーを必ず無効にしてください。そうしないと、わずか数時間でバッテリーが消耗する可能性があります。画面がオフになっても、システムはセンサーを自動的に無効にしないことに注意してください。
example
package com.junichi.lightsensorapp
import android.content.Context
import android.hardware.Sensor
import android.hardware.SensorEvent
import android.hardware.SensorEventListener
import android.hardware.SensorManager
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.junichi.lightsensorapp.ui.theme.LightSensorAppTheme
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
LightSensorAppTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
LightSensorApp()
}
}
}
}
}
@Composable
fun LightSensorApp() {
val context = LocalContext.current
var lightLevel by remember { mutableStateOf(0f) }
DisposableEffect(context) {
val sensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager
val lightSensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT)
val listener = object : SensorEventListener {
override fun onSensorChanged(event: SensorEvent?) {
if (event?.sensor?.type == Sensor.TYPE_LIGHT) {
lightLevel = event.values[0]
}
}
override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {}
}
sensorManager.registerListener(listener, lightSensor, SensorManager.SENSOR_DELAY_NORMAL)
onDispose {
sensorManager.unregisterListener(listener)
}
}
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Text(
text = "現在の明るさ",
style = MaterialTheme.typography.headlineMedium
)
Spacer(modifier = Modifier.height(16.dp))
Text(
text = String.format("%.1f lux", lightLevel),
style = MaterialTheme.typography.displayLarge
)
Spacer(modifier = Modifier.height(32.dp))
LightLevelDescription(lightLevel)
}
}
@Composable
fun LightLevelDescription(lightLevel: Float) {
val description = when {
lightLevel < 10 -> "非常に暗い (夜間)"
lightLevel < 50 -> "暗い (屋内照明)"
lightLevel < 200 -> "やや暗い (曇りの日)"
lightLevel < 400 -> "普通 (室内)"
lightLevel < 1000 -> "明るい (曇りの屋外)"
lightLevel < 10000 -> "非常に明るい (晴れた日)"
else -> "極めて明るい (直射日光)"
}
Text(
text = "明るさの状態: $description",
style = MaterialTheme.typography.bodyLarge
)
}
@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
LightSensorAppTheme {
LightSensorApp()
}
}
感想
センサーはどの辺にあるのか、調べてみたのですが、スクリーンの上にある自分を写したりするインカメラのあたりにあるようです。ちなみに、天気の良い日に、ベランダに出て、直射日光を浴びせると、数値がすごい速さで上昇して、「直射日光」と表示されます。
Discussion
スイッチOFFにしないとパフォーマンスが悪い
センサー起動したままだとよくないので、スイッチつけました。