[android] calculate EFL

This commit is contained in:
Vadim 2025-05-11 11:50:01 +02:00
parent 383fbab7d9
commit 56ac6fe558
4 changed files with 85 additions and 1 deletions

View file

@ -4,6 +4,7 @@ import android.os.Bundle
import android.view.KeyEvent
import android.view.WindowManager
import androidx.core.view.WindowCompat
import com.vodemn.lightmeter.PlatformChannels.CameraInfoPlatformChannel
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.EventChannel
@ -17,6 +18,8 @@ class MainActivity : FlutterActivity() {
private var volumeEventsEmitter: EventSink? = null
private var handleVolume = false
private val cameraInfoPlatformChannel = CameraInfoPlatformChannel()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
WindowCompat.setDecorFitsSystemWindows(window, false)
@ -24,6 +27,8 @@ class MainActivity : FlutterActivity() {
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
cameraInfoPlatformChannel.onAttachedToEngine(flutterEngine.dartExecutor.binaryMessenger, context)
keepScreenOnChannel = MethodChannel(
flutterEngine.dartExecutor.binaryMessenger,
"com.vodemn.lightmeter/keepScreenOn"
@ -76,6 +81,7 @@ class MainActivity : FlutterActivity() {
keepScreenOnChannel.setMethodCallHandler(null)
volumeHandlingChannel.setMethodCallHandler(null)
volumeEventChannel.setStreamHandler(null)
cameraInfoPlatformChannel.onDestroy()
super.onDestroy()
}

View file

@ -0,0 +1,57 @@
package com.vodemn.lightmeter.PlatformChannels
import android.content.Context
import android.hardware.camera2.CameraCharacteristics
import android.hardware.camera2.CameraManager
import android.hardware.camera2.CameraMetadata.LENS_FACING_BACK
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import kotlin.math.pow
import kotlin.math.sqrt
/** CameraInfoPlatformChannel */
class CameraInfoPlatformChannel : MethodChannel.MethodCallHandler {
private lateinit var channel: MethodChannel
private lateinit var cameraManager: CameraManager
private var mainCameraEfl: Double? = null
fun onAttachedToEngine(binaryMessenger: BinaryMessenger, context: Context) {
channel = MethodChannel(binaryMessenger, "com.vodemn.lightmeter.CameraInfoPlatformChannel")
cameraManager = context.getSystemService(Context.CAMERA_SERVICE) as CameraManager
channel.setMethodCallHandler(this)
}
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
when (call.method) {
"mainCameraEfl" -> {
mainCameraEfl = mainCameraEfl ?: getMainCameraFocalLength35mm()
result.success(mainCameraEfl)
}
else -> result.notImplemented()
}
}
fun onDestroy() {
channel.setMethodCallHandler(null)
}
private fun getMainCameraFocalLength35mm(): Double? {
return cameraManager.cameraIdList.map {
cameraManager.getCameraCharacteristics(it)
}.first {
it.get(CameraCharacteristics.LENS_FACING) == LENS_FACING_BACK
}.focalLength35mm()
}
private fun CameraCharacteristics.focalLength35mm(): Double? {
val defaultFocalLength = get(CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS)?.first()
val sensorSize = get(CameraCharacteristics.SENSOR_INFO_PHYSICAL_SIZE)
return if (defaultFocalLength != null && sensorSize != null) {
// https://en.wikipedia.org/wiki/35_mm_equivalent_focal_length#Conversions
43.27 * defaultFocalLength / sqrt(sensorSize.height.pow(2) + sensorSize.width.pow(2))
} else {
null
}
}
}

View file

@ -5,6 +5,7 @@ import 'package:flutter_native_splash/flutter_native_splash.dart';
import 'package:lightmeter/data/analytics/analytics.dart';
import 'package:lightmeter/data/analytics/api/analytics_firebase.dart';
import 'package:lightmeter/data/caffeine_service.dart';
import 'package:lightmeter/data/camera_info_service.dart';
import 'package:lightmeter/data/haptics_service.dart';
import 'package:lightmeter/data/light_sensor_service.dart';
import 'package:lightmeter/data/permissions_service.dart';
@ -99,11 +100,13 @@ class _ApplicationWrapperState extends State<ApplicationWrapper> {
await Future.wait([
SharedPreferences.getInstance(),
const LightSensorService(LocalPlatform()).hasSensor(),
const CameraInfoService().mainCameraEfl(),
remoteConfigService.activeAndFetchFeatures(),
equipmentProfilesStorageService.init(),
filmsStorageService.init(),
]).then((value) {
userPreferencesService = UserPreferencesService((value[0] as SharedPreferences?)!);
userPreferencesService = UserPreferencesService((value[0] as SharedPreferences?)!)
..cameraFocalLength = value[2] as int?;
hasLightSensor = value[1] as bool? ?? false;
});
}

View file

@ -0,0 +1,18 @@
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
class CameraInfoService {
@visibleForTesting
static const cameraInfoPlatformChannel = MethodChannel("com.vodemn.lightmeter.CameraInfoPlatformChannel");
const CameraInfoService();
Future<int?> mainCameraEfl() async {
if (Platform.isIOS) {
return null;
}
return (await cameraInfoPlatformChannel.invokeMethod<double?>('mainCameraEfl'))?.round();
}
}