diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml
index 288304cb..f548d112 100644
--- a/android/app/src/debug/AndroidManifest.xml
+++ b/android/app/src/debug/AndroidManifest.xml
@@ -1,7 +1,124 @@
-
-
-
+
+ package="com.freaccess.hub"
+
+ xmlns:tools="http://schemas.android.com/tools">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 46d26daf..f548d112 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -1,118 +1,124 @@
-
-
-
-
-
-
-
-
-
-
+ package="com.freaccess.hub"
-
+ xmlns:tools="http://schemas.android.com/tools">
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/app/src/main/kotlin/com/freaccess/hub/MainActivity.kt b/android/app/src/main/kotlin/com/freaccess/hub/MainActivity.kt
index 10a40dac..767f00ff 100644
--- a/android/app/src/main/kotlin/com/freaccess/hub/MainActivity.kt
+++ b/android/app/src/main/kotlin/com/freaccess/hub/MainActivity.kt
@@ -1,5 +1,29 @@
package com.freaccess.hub
+import android.os.Bundle
+import android.provider.Settings
import io.flutter.embedding.android.FlutterFragmentActivity
+import io.flutter.embedding.engine.FlutterEngine
+import io.flutter.plugin.common.MethodChannel
-class MainActivity: FlutterFragmentActivity() {}
+class MainActivity: FlutterFragmentActivity() {
+ private val CHANNEL = "com.freaccess.hub/getAndroidId"
+ override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
+ super.configureFlutterEngine(flutterEngine)
+ MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
+ if (call.method == "getAndroidId") {
+ val androidId = getAndroidId()
+ if (androidId != null) {
+ result.success(androidId)
+ } else {
+ result.error("UNAVAILABLE", "Android ID not available.", null)
+ }
+ } else {
+ result.notImplemented()
+ }
+ }
+ }
+ private fun getAndroidId(): String? {
+ return Settings.Secure.getString(contentResolver, Settings.Secure.ANDROID_ID)
+ }
+}
\ No newline at end of file
diff --git a/lib/components/organism_components/bottom_arrow_linked_locals_component/bottom_arrow_linked_locals_component_widget.dart b/lib/components/organism_components/bottom_arrow_linked_locals_component/bottom_arrow_linked_locals_component_widget.dart
index 1565e678..0c68525e 100644
--- a/lib/components/organism_components/bottom_arrow_linked_locals_component/bottom_arrow_linked_locals_component_widget.dart
+++ b/lib/components/organism_components/bottom_arrow_linked_locals_component/bottom_arrow_linked_locals_component_widget.dart
@@ -14,7 +14,8 @@ import '/backend/api_requests/api_calls.dart';
import '/flutter_flow/flutter_flow_theme.dart';
class BottomArrowLinkedLocalsComponentWidget extends StatefulWidget {
- const BottomArrowLinkedLocalsComponentWidget({super.key});
+ const BottomArrowLinkedLocalsComponentWidget({super.key, required this.response});
+ final ApiCallResponse? response;
@override
State createState() => _BottomArrowLinkedLocalsComponentWidgetState();
@@ -71,16 +72,15 @@ class _BottomArrowLinkedLocalsComponentWidgetState extends State _fetchLocals() async {
try {
setState(() => _loading = true);
- var response = await PhpGroup.getLocalsCall.call();
- final bool isError = response.jsonBody['error'];
+ final bool isError = widget.response?.jsonBody['error'];
if (isError) {
- final String errorMsg = response.jsonBody['error_msg'];
+ final String errorMsg = widget.response?.jsonBody['error_msg'];
_handleError(context, errorMsg);
- return response;
+ return widget.response;
}
- final List locals = response.jsonBody['locais'] ?? [];
+ final List locals = widget.response?.jsonBody['locais'] ?? [];
final bool isEmpty = locals.isEmpty;
final bool isUnique = locals.length == 1;
@@ -99,7 +99,7 @@ class _BottomArrowLinkedLocalsComponentWidgetState extends State getData() async {
cliName = (await StorageHelper().get(SQLiteStorageKey.clientName.value, Storage.SQLiteStorage)) ?? '';
cliUUID = (await StorageHelper().get(SQLiteStorageKey.clientUUID.value, Storage.SQLiteStorage)) ?? '';
- ;
setStateCallback?.call();
}
diff --git a/lib/components/organism_components/local_profile_component/local_profile_component_widget.dart b/lib/components/organism_components/local_profile_component/local_profile_component_widget.dart
index 05890176..0a8bb410 100644
--- a/lib/components/organism_components/local_profile_component/local_profile_component_widget.dart
+++ b/lib/components/organism_components/local_profile_component/local_profile_component_widget.dart
@@ -3,6 +3,8 @@ import 'dart:developer';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
+import 'package:hub/shared/helpers/base_storage.dart';
+import 'package:hub/shared/helpers/storage_helper.dart';
import '/flutter_flow/custom_functions.dart' as functions;
import '/flutter_flow/flutter_flow_theme.dart';
@@ -34,10 +36,15 @@ class _LocalProfileComponentWidgetState extends State LocalProfileComponentModel());
_model.setOnUpdate(onUpdate: () => setState(() {}));
_model.setStateCallback = () => safeSetState(() {});
- //
- // WidgetsBinding.instance
- // .addPostFrameCallback((_) async => await LocalizationService.processLocals(context).then((value) => value == true ? onUpdate() : null));
- // LocalizationService.processLocals(context).then((value) => value == true ? onUpdate() : null);
+
+ WidgetsBinding.instance.addPostFrameCallback((_) async {
+ bool initialized = false;
+ bool isDevLinked = _model.cliUUID.isNotEmpty;
+ if (!isDevLinked && !initialized) {
+ initialized = true;
+ await LocalizationService.processLocals(context).then((value) => value == true ? onUpdate() : null);
+ }
+ });
}
@override
@@ -90,7 +97,8 @@ class _LocalProfileComponentWidgetState extends State value == true ? onUpdate() : null);
},
child: ClipRRect(
diff --git a/lib/main.dart b/lib/main.dart
index 24ebdf9b..7fcd9d7b 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -281,7 +281,7 @@ class _AppState extends State with WidgetsBindingObserver {
if (state == AppLifecycleState.detached) {
await LocalizationService.processLocals(context);
FirebaseMessagingService().updateDeviceToken();
- }
+ }
}
@override
diff --git a/lib/shared/services/localization/localization_service.dart b/lib/shared/services/localization/localization_service.dart
index 5803cd78..e8c44c87 100644
--- a/lib/shared/services/localization/localization_service.dart
+++ b/lib/shared/services/localization/localization_service.dart
@@ -3,9 +3,12 @@
import 'dart:developer';
import 'package:flutter/material.dart';
+import 'package:http/src/response.dart';
+import 'package:hub/backend/api_requests/api_manager.dart';
import 'package:hub/flutter_flow/nav/nav.dart';
import 'package:hub/shared/helpers/base_storage.dart';
import 'package:hub/shared/helpers/storage_helper.dart';
+import 'package:hub/shared/utils/device_util.dart';
import 'package:hub/shared/utils/dialog_util.dart';
import '../../../backend/api_requests/api_calls.dart';
@@ -20,12 +23,20 @@ class LocalizationService {
try {
final GetLocalsCall callback = PhpGroup.getLocalsCall;
var response = await callback.call();
- final bool isError = response.jsonBody['error'];
+ final bool? isError = response.jsonBody['error'];
- if (isError) {
+ if (isError == true) {
_handleError(context, response.jsonBody['error_msg']);
return;
}
+ if (response.jsonBody == null) {
+ final String errorMsg = FFLocalizations.of(context).getVariableText(
+ enText: 'Verify your connection',
+ ptText: 'Verifique sua conexão',
+ );
+ DialogUtil.error(context, errorMsg).whenComplete(() => selectLocal(context, response));
+ return;
+ }
final List locals = response.jsonBody['locais'] ?? [];
final bool isEmpty = locals.isEmpty;
@@ -49,13 +60,21 @@ class LocalizationService {
try {
final GetLocalsCall callback = PhpGroup.getLocalsCall;
final ApiCallResponse response = await callback.call();
- final bool isError = response.jsonBody['error'];
+ final bool? isError = response.jsonBody['error'];
- if (isError) {
+ if (isError == true) {
final String errorMsg = response.jsonBody['error_msg'];
_handleError(context, errorMsg);
return false;
}
+ if (response.jsonBody == null) {
+ final String errorMsg = FFLocalizations.of(context).getVariableText(
+ enText: 'Verify your connection',
+ ptText: 'Verifique sua conexão',
+ );
+ DialogUtil.error(context, errorMsg).whenComplete(() => selectLocal(context, response));
+ return false;
+ }
final List locals = response.jsonBody['locais'].toList() ?? [];
_logLocalsStatus(locals);
@@ -81,7 +100,7 @@ class LocalizationService {
return await _handleEnabled(context, locals[0]);
} else if (isUnselected) {
log('() => isUnselected');
- return await selectLocal(context);
+ return await selectLocal(context, response);
} else if (isSelected) {
log('() => isSelected');
return await processData(context);
@@ -94,7 +113,7 @@ class LocalizationService {
if (!isUnique && isPending) log('() => not unique and pending');
if (!isUnique && isBlocked) log('() => not unique and blocked');
log('() => else');
- return await selectLocal(context);
+ return await selectLocal(context, response);
}
} catch (e, s) {
log('() => stack: $s');
@@ -104,7 +123,7 @@ class LocalizationService {
enText: 'Error getting locals, verify your connection',
ptText: 'Erro ao obter locais, verifique sua conexão',
);
- DialogUtil.error(context, errorMsg).whenComplete(() => selectLocal(context));
+ DialogUtil.error(context, errorMsg).whenComplete(() => selectLocal(context, null));
return false;
}
}
@@ -113,11 +132,18 @@ class LocalizationService {
try {
final GetDadosCall callback = PhpGroup.getDadosCall;
var response = await callback.call();
- final bool error = response.jsonBody['error'];
+ final bool? isError = response.jsonBody['error'];
- if (error == true || error == 'true') {
+ if (isError == true || isError == 'true') {
final String errorMsg = response.jsonBody['error_msg'];
- DialogUtil.error(context, errorMsg).whenComplete(() => selectLocal(context));
+ DialogUtil.error(context, errorMsg).whenComplete(() => selectLocal(context, response));
+ return false;
+ } else if (response.jsonBody == null) {
+ final String errorMsg = FFLocalizations.of(context).getVariableText(
+ enText: 'Verify your connection',
+ ptText: 'Verifique sua conexão',
+ );
+ DialogUtil.error(context, errorMsg).whenComplete(() => selectLocal(context, response));
return false;
} else {
await _updateStorageUtil(response.jsonBody);
@@ -130,12 +156,12 @@ class LocalizationService {
enText: 'Error getting data, verify your connection',
ptText: 'Erro ao obter dados, verifique sua conexão',
);
- DialogUtil.error(context, errorMsg).whenComplete(() => selectLocal(context));
+ DialogUtil.error(context, errorMsg).whenComplete(() => selectLocal(context, null));
return false;
}
}
- static Future selectLocal(BuildContext context) async {
+ static Future selectLocal(BuildContext context, ApiCallResponse? response) async {
return await showModalBottomSheet(
isScrollControlled: true,
backgroundColor: Colors.transparent,
@@ -148,7 +174,7 @@ class LocalizationService {
canPop: false,
child: Padding(
padding: MediaQuery.viewInsetsOf(context),
- child: const BottomArrowLinkedLocalsComponentWidget(),
+ child: BottomArrowLinkedLocalsComponentWidget(response: response),
),
),
).then((_) async => await processData(context));
@@ -204,6 +230,7 @@ class LocalizationService {
final bool isAuthenticated = userUUID.isNotEmpty && devUUID.isNotEmpty;
final bool isDevLinked = !errorMsg.contains('Esse dispositivo nao pertence a esse usuario');
log('() => isLinked: $errorMsg');
+ log('() => isLinked: $errorMsg');
if (!isAuthenticated) {
errorMsg = FFLocalizations.of(context).getVariableText(
ptText: 'Erro ao obter credenciais de autenticação',
@@ -221,7 +248,7 @@ class LocalizationService {
await DialogUtil.warning(context, errorMsg);
return;
}
- await DialogUtil.error(context, errorMsg).whenComplete(() async => await selectLocal(context));
+ await DialogUtil.error(context, errorMsg).whenComplete(() async => await selectLocal(context, null));
}
static Future _handleUnavailable(BuildContext context, List locals) async {
@@ -310,3 +337,4 @@ class LocalizationService {
await StorageHelper().set(SQLiteStorageKey.userName.value, jsonBody['visitado']['VDO_NOME'], Storage.SQLiteStorage);
}
}
+
diff --git a/lib/shared/utils/device_util.dart b/lib/shared/utils/device_util.dart
index 8d52fcc2..844a3c16 100644
--- a/lib/shared/utils/device_util.dart
+++ b/lib/shared/utils/device_util.dart
@@ -2,42 +2,73 @@ import 'dart:io';
import 'package:device_info_plus/device_info_plus.dart';
+import 'package:flutter/services.dart';
+
class DeviceUtil {
+ static const MethodChannel _channel = MethodChannel("com.freaccess.hub/getAndroidId");
+
+ static Future getAndroidId() async {
+ try {
+ final String? androidId = await _channel.invokeMethod('getAndroidId');
+
+ return androidId;
+ } on PlatformException catch (e) {
+ print("Failed to get Android ID: '${e.message}'.");
+
+ return null;
+ }
+ }
+
static Future getDevUUID() async {
var deviceInfo = DeviceInfoPlugin();
+
if (Platform.isIOS) {
- // import 'dart:io'
var iosDeviceInfo = await deviceInfo.iosInfo;
- return iosDeviceInfo.identifierForVendor; // unique ID on iOS
+ return iosDeviceInfo.identifierForVendor;
} else if (Platform.isAndroid) {
- var androidDeviceInfo = await deviceInfo.androidInfo;
- return androidDeviceInfo.id; // unique ID on Android
+ try {
+ final String? secureAndroidId = await getAndroidId();
+ return secureAndroidId;
+ } catch (e) {
+ final build = await deviceInfo.androidInfo;
+ return build.id;
+ }
}
+
return null;
}
static Future getSerialNumber() async {
var deviceInfo = DeviceInfoPlugin();
+
if (Platform.isIOS) {
// import 'dart:io'
+
var iosDeviceInfo = await deviceInfo.iosInfo;
+
return iosDeviceInfo.identifierForVendor; // unique ID on iOS
} else if (Platform.isAndroid) {
var androidDeviceInfo = await deviceInfo.androidInfo;
+
return androidDeviceInfo.serialNumber; // unique ID on Android
}
+
return null;
}
static Future getDeviceOSVersion() async {
var deviceInfo = DeviceInfoPlugin();
+
if (Platform.isIOS) {
var iosDeviceInfo = await deviceInfo.iosInfo;
+
return iosDeviceInfo.systemVersion; // unique ID on iOS. e.g. 14.5
} else if (Platform.isAndroid) {
var androidDeviceInfo = await deviceInfo.androidInfo;
+
return androidDeviceInfo.version.release; // unique ID on Android. e.g . 11
}
+
return null;
}
}