add button settings, and no sleep for devices
This commit is contained in:
parent
eb3fd7aca3
commit
30321e051c
|
|
@ -5,12 +5,14 @@ import android.os.Build
|
|||
import android.os.VibrationEffect
|
||||
import android.os.Vibrator
|
||||
import android.os.VibratorManager
|
||||
import android.view.WindowManager
|
||||
import io.flutter.embedding.android.FlutterActivity
|
||||
import io.flutter.embedding.engine.FlutterEngine
|
||||
import io.flutter.plugin.common.MethodChannel
|
||||
|
||||
class MainActivity : FlutterActivity() {
|
||||
private val vibrationChannel = "smart_vision_assist/vibration"
|
||||
private val screenChannel = "smart_vision_assist/screen"
|
||||
|
||||
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
|
||||
super.configureFlutterEngine(flutterEngine)
|
||||
|
|
@ -31,6 +33,30 @@ class MainActivity : FlutterActivity() {
|
|||
else -> result.notImplemented()
|
||||
}
|
||||
}
|
||||
|
||||
MethodChannel(
|
||||
flutterEngine.dartExecutor.binaryMessenger,
|
||||
screenChannel
|
||||
).setMethodCallHandler { call, result ->
|
||||
when (call.method) {
|
||||
"setKeepScreenOn" -> {
|
||||
val enabled = call.argument<Boolean>("enabled") ?: false
|
||||
setKeepScreenOn(enabled)
|
||||
result.success(null)
|
||||
}
|
||||
else -> result.notImplemented()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setKeepScreenOn(enabled: Boolean) {
|
||||
runOnUiThread {
|
||||
if (enabled) {
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||
} else {
|
||||
window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun vibrate(milliseconds: Long): Boolean {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import 'dart:ui' as ui;
|
|||
|
||||
import 'package:camera/camera.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import '../services/tts_service.dart';
|
||||
|
|
@ -19,7 +20,10 @@ class CameraScreen extends StatefulWidget {
|
|||
State<CameraScreen> createState() => _CameraScreenState();
|
||||
}
|
||||
|
||||
class _CameraScreenState extends State<CameraScreen> {
|
||||
class _CameraScreenState extends State<CameraScreen> with WidgetsBindingObserver {
|
||||
static const MethodChannel _screenChannel =
|
||||
MethodChannel("smart_vision_assist/screen");
|
||||
|
||||
CameraController? controller;
|
||||
List<CameraDescription>? cameras;
|
||||
|
||||
|
|
@ -36,15 +40,31 @@ class _CameraScreenState extends State<CameraScreen> {
|
|||
Timer? _vibrationTimer;
|
||||
|
||||
bool _isLoggingOut = false;
|
||||
bool _isStatusActive = true;
|
||||
String _lastSpokenMessage = "";
|
||||
DateTime? _lastSpokenAt;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addObserver(this);
|
||||
unawaited(_setKeepScreenOn(true));
|
||||
initCamera();
|
||||
}
|
||||
|
||||
Future<void> _setKeepScreenOn(bool enabled) async {
|
||||
try {
|
||||
await _screenChannel.invokeMethod<void>(
|
||||
"setKeepScreenOn",
|
||||
{"enabled": enabled},
|
||||
);
|
||||
} on MissingPluginException {
|
||||
// Platform selain Android boleh mengabaikan fitur ini.
|
||||
} catch (_) {
|
||||
// Jangan sampai kegagalan wakelock mengganggu kamera.
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> initCamera() async {
|
||||
try {
|
||||
cameras = await availableCameras();
|
||||
|
|
@ -281,15 +301,91 @@ class _CameraScreenState extends State<CameraScreen> {
|
|||
await _tts.speak(message);
|
||||
}
|
||||
|
||||
Future<bool> _confirmDeactivateAccount() async {
|
||||
final bool? confirmed = await showDialog<bool>(
|
||||
context: context,
|
||||
builder: (BuildContext confirmationContext) {
|
||||
return AlertDialog(
|
||||
title: const Text("Konfirmasi"),
|
||||
content: const Text("Apakah anda yakin menonaktifkan akun ini?"),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(confirmationContext).pop(false),
|
||||
child: const Text("Tidak"),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(confirmationContext).pop(true),
|
||||
child: const Text("Ya"),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
return confirmed ?? false;
|
||||
}
|
||||
|
||||
void _showSettings() {
|
||||
showDialog<void>(
|
||||
context: context,
|
||||
builder: (BuildContext dialogContext) {
|
||||
return StatefulBuilder(
|
||||
builder: (BuildContext context, StateSetter setDialogState) {
|
||||
return AlertDialog(
|
||||
title: const Text("Setting"),
|
||||
content: SwitchListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
title: const Text("Status"),
|
||||
subtitle: Text(_isStatusActive ? "Aktif" : "Nonaktif"),
|
||||
value: _isStatusActive,
|
||||
onChanged: (bool value) async {
|
||||
if (!value) {
|
||||
final bool isConfirmed =
|
||||
await _confirmDeactivateAccount();
|
||||
if (!isConfirmed || !mounted) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
setState(() {
|
||||
_isStatusActive = value;
|
||||
});
|
||||
setDialogState(() {});
|
||||
},
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(dialogContext).pop(),
|
||||
child: const Text("Tutup"),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_detectionTimer?.cancel();
|
||||
_vibrationTimer?.cancel();
|
||||
WidgetsBinding.instance.removeObserver(this);
|
||||
unawaited(_setKeepScreenOn(false));
|
||||
unawaited(_vibrationService.stop());
|
||||
controller?.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeAppLifecycleState(AppLifecycleState state) {
|
||||
if (state == AppLifecycleState.resumed) {
|
||||
unawaited(_setKeepScreenOn(true));
|
||||
} else {
|
||||
unawaited(_setKeepScreenOn(false));
|
||||
}
|
||||
}
|
||||
|
||||
Widget buildCameraPreview() {
|
||||
final Size? previewSize = controller?.value.previewSize;
|
||||
if (previewSize == null) {
|
||||
|
|
@ -421,6 +517,20 @@ class _CameraScreenState extends State<CameraScreen> {
|
|||
),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
bottom: 40,
|
||||
left: MediaQuery.of(context).size.width / 2 - 130,
|
||||
child: Semantics(
|
||||
label: "Buka setting",
|
||||
button: true,
|
||||
child: FloatingActionButton(
|
||||
heroTag: "camera_settings",
|
||||
backgroundColor: Colors.black,
|
||||
onPressed: _showSettings,
|
||||
child: const Icon(Icons.settings, color: Colors.white),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ class ApiConfig {
|
|||
static const bool useAndroidEmulator = false;
|
||||
|
||||
// Ganti IP ini dengan IP laptop/PC Anda saat menggunakan HP fisik (ADB).
|
||||
static const String deviceHost = "192.168.110.147:8000";
|
||||
static const String deviceHost = "192.168.0.31:8000";
|
||||
|
||||
static String get baseUrl {
|
||||
if (Platform.isAndroid && useAndroidEmulator) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue