android sdk upgraded to 36, 16kb page size support added.

main_production_upgrade
Sikander Saleem 2 weeks ago
parent 7fc1f9177d
commit b94d5d1fbd

4
.gitignore vendored

@ -53,3 +53,7 @@ android/gradle.properties
/android/app/profile
/android/app/release
/android/gradle/wrapper/gradle-wrapper.properties
# Build files - should not be committed
android/app/build/
android/build/
build/

@ -1,92 +0,0 @@
plugins {
id "com.android.application"
id "kotlin-android"
id "dev.flutter.flutter-gradle-plugin"
id "com.google.gms.google-services"
}
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
apply plugin: "com.huawei.agconnect"
android {
namespace 'com.example.test_sa'
// ndkVersion flutter.ndkVersion
ndkVersion = "27.0.12077973"
compileOptions {
coreLibraryDesugaringEnabled true
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = "17" // Must match the compileOptions target
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.hmg.atoms"
// You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration.
minSdkVersion 21
targetSdkVersion 35
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}
signingConfigs {
release {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
storePassword keystoreProperties['storePassword']
}
}
buildTypes {
debug {
signingConfig signingConfigs.debug
}
// release {
// signingConfig signingConfigs.debug
// }
release {
minifyEnabled true
shrinkResources true
signingConfig signingConfigs.release
}
}
}
flutter {
source '../..'
}
dependencies {
implementation 'com.huawei.agconnect:agconnect-core:1.5.2.300'
implementation 'com.huawei.hms:push:6.7.0.300'
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.3'
}

@ -0,0 +1,110 @@
import java.util.Properties
import java.io.FileInputStream
plugins {
id("com.android.application")
id("kotlin-android")
id("dev.flutter.flutter-gradle-plugin")
id("com.google.gms.google-services")
id("com.huawei.agconnect")
}
val localProperties = Properties()
val localPropertiesFile = rootProject.file("local.properties")
if (localPropertiesFile.exists()) {
localProperties.load(FileInputStream(localPropertiesFile))
}
val flutterVersionCode = localProperties.getProperty("flutter.versionCode") ?: "1"
val flutterVersionName = localProperties.getProperty("flutter.versionName") ?: "1.0"
val keystoreProperties = Properties()
val keystorePropertiesFile = rootProject.file("key.properties")
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(FileInputStream(keystorePropertiesFile))
}
android {
namespace = "com.example.test_sa"
ndkVersion = "28.2.13676358"
compileSdk = 36
compileOptions {
isCoreLibraryDesugaringEnabled = true
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = "17"
}
defaultConfig {
applicationId = "com.hmg.atoms"
minSdk = flutter.minSdkVersion
targetSdk = 36
versionCode = flutterVersionCode.toInt()
versionName = flutterVersionName
// 16KB page size support - ensure all ABIs are included
ndk {
abiFilters.addAll(listOf("armeabi-v7a", "arm64-v8a", "x86", "x86_64"))
}
// Additional 16KB page size optimization
manifestPlaceholders["16kb_page_size_compatible"] = "true"
}
signingConfigs {
create("release") {
keyAlias = keystoreProperties["keyAlias"] as String?
keyPassword = keystoreProperties["keyPassword"] as String?
storeFile = keystoreProperties["storeFile"]?.let { file(it as String) }
storePassword = keystoreProperties["storePassword"] as String?
}
}
buildTypes {
debug {
signingConfig = signingConfigs.getByName("debug")
}
release {
isMinifyEnabled = true
isShrinkResources = true
signingConfig = signingConfigs.getByName("release")
}
}
// 16KB page size support for Google Play Store (August 2025 requirement)
// AGP 8.1+ uses packaging.jniLibs instead of the deprecated gradle.properties flag
packaging {
jniLibs {
useLegacyPackaging = false
// Ensure proper extraction and alignment for 16KB page size
excludes.add("**/libunity.so")
}
resources {
excludes += setOf(
"META-INF/DEPENDENCIES",
"META-INF/LICENSE",
"META-INF/LICENSE.txt",
"META-INF/license.txt",
"META-INF/NOTICE",
"META-INF/NOTICE.txt",
"META-INF/notice.txt",
"META-INF/*.kotlin_module"
)
}
}
}
flutter {
source = "../.."
}
dependencies {
implementation("com.huawei.agconnect:agconnect-core:1.5.2.300")
implementation("com.huawei.hms:push:6.7.0.300")
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.0.3")
}

@ -42,6 +42,12 @@
android:showWhenLocked="true"
android:turnScreenOn="true"
android:usesCleartextTraffic="true">
<!-- 16KB page size support - Required for modern Android devices -->
<property
android:name="android.app.16kb_page_size_compatible"
android:value="true" />
<activity
android:name=".MainActivity"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"

@ -1,63 +0,0 @@
buildscript {
ext.kotlin_version = '1.9.25'
repositories {
google()
mavenCentral()
maven { url "https://jitpack.io" }
maven { url 'https://developer.huawei.com/repo/' }
}
dependencies {
classpath "com.android.tools.build:gradle:8.7.0"
classpath 'com.huawei.agconnect:agcp:1.9.1.304'
}
}
configurations.all {
resolutionStrategy.force 'androidx.appcompat:appcompat:1.3.0'
}
allprojects {
repositories {
google()
mavenCentral()
maven { url 'https://developer.huawei.com/repo/' }
}
}
rootProject.buildDir = '../build'
subprojects {
afterEvaluate { project ->
if (project.plugins.hasPlugin("com.android.application") ||
project.plugins.hasPlugin("com.android.library")) {
project.android {
compileSdkVersion 34
}
}
}
}
//subprojects {
// project.buildDir = "${rootProject.buildDir}/${project.name}"
// project.evaluationDependsOn(':app')
//}
//rootProject.buildDir = File("../build")
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(":app")
}
//subprojects {
// project.buildDir = "${rootProject.buildDir}/${project.name}"
//}
//subprojects {
// project.evaluationDependsOn(':app')
//}
tasks.register("clean", Delete) {
delete rootProject.buildDir
}

@ -0,0 +1,51 @@
buildscript {
repositories {
google()
mavenCentral()
maven { url = uri("https://jitpack.io") }
maven { url = uri("https://developer.huawei.com/repo/") }
}
dependencies {
classpath("com.android.tools.build:gradle:8.9.1")
classpath("com.huawei.agconnect:agcp:1.9.1.304")
}
}
configurations.all {
resolutionStrategy.force("androidx.appcompat:appcompat:1.3.0")
}
allprojects {
repositories {
google()
mavenCentral()
maven { url = uri("https://developer.huawei.com/repo/") }
}
}
rootProject.buildDir = file("../build")
subprojects {
afterEvaluate {
if (plugins.hasPlugin("com.android.application") ||
plugins.hasPlugin("com.android.library")) {
extensions.configure<com.android.build.gradle.BaseExtension> {
compileSdkVersion(36)
}
}
}
}
subprojects {
project.buildDir = file("${rootProject.buildDir}/${project.name}")
}
subprojects {
project.evaluationDependsOn(":app")
}
tasks.register<Delete>("clean") {
delete(rootProject.buildDir)
}

@ -1,6 +1,6 @@
#Thu Oct 24 09:39:31 AST 2024
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

@ -1,39 +0,0 @@
//include ':app'
//
//def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
//def properties = new Properties()
//
//assert localPropertiesFile.exists()
//localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
//
//def flutterSdkPath = properties.getProperty("flutter.sdk")
//assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
//apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
//
pluginManagement {
def flutterSdkPath = {
def properties = new Properties()
file("local.properties").withInputStream { properties.load(it) }
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
return flutterSdkPath
}()
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "8.7.0" apply false
id "org.jetbrains.kotlin.android" version "1.9.25" apply false // Replace {kotlinVersion} with your version, e.g., "1.7.10"
id "com.google.gms.google-services" version "4.3.13" apply false // Replace {kotlinVersion} with your version, e.g., "1.7.10"
}
include ":app"

@ -0,0 +1,27 @@
pluginManagement {
val flutterSdkPath: String = run {
val properties = java.util.Properties()
file("local.properties").inputStream().use { properties.load(it) }
val path = properties.getProperty("flutter.sdk")
require(path != null) { "flutter.sdk not set in local.properties" }
path
}
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
plugins {
id("dev.flutter.flutter-plugin-loader") version "1.0.0"
id("com.android.application") version "8.9.1" apply false
id("org.jetbrains.kotlin.android") version "2.1.0" apply false
id("com.google.gms.google-services") version "4.4.2" apply false
}
include(":app")

@ -1,4 +1,4 @@
arb-dir: lib/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart
untranslated-messages-file: localization_error.txt
untranslated-messages-file: localization_error.txt

@ -1,4 +1,6 @@
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:localization/localization.dart';
import '../../l10n/app_localizations.dart';
class HttpStatusManger {
static String getStatusMessage({

@ -3,7 +3,7 @@
//
// import 'package:flutter/material.dart';
// import 'package:flutter/services.dart';
// import 'package:flutter_gen/gen_l10n/app_localizations.dart';
// import 'package:localization/localization.dart';
//
// class AppLocalization {
// AppLocalization(this.locale);

@ -2,7 +2,7 @@ import 'dart:convert';
import 'dart:developer';
import 'package:flutter/cupertino.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:localization/localization.dart';
import 'package:http/http.dart';
import 'package:test_sa/controllers/api_routes/api_manager.dart';
import 'package:test_sa/controllers/api_routes/http_status_manger.dart';
@ -13,6 +13,7 @@ import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/models/user.dart';
import 'package:test_sa/modules/asset_delivery_module/models/technical_inpection_asset_model.dart';
import '../../../l10n/app_localizations.dart';
import '../../../models/device/asset.dart';
class AssetProvider extends ChangeNotifier {

@ -1,5 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:localization/localization.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
@ -7,6 +7,7 @@ import 'package:test_sa/new_views/swipe_module/dialoge/confirm_dialog.dart';
import 'package:test_sa/new_views/swipe_module/dialoge/info_dialog.dart';
import '../controllers/providers/settings/setting_provider.dart';
import '../l10n/app_localizations.dart';
extension BuildContextExtension on BuildContext {
AppLocalizations get translation => AppLocalizations.of(this)!;

@ -20,7 +20,6 @@ import 'package:google_api_availability/google_api_availability.dart';
// import 'package:mohem_flutter_app/widgets/dialogs/confirm_dialog.dart';
// import 'package:mohem_flutter_app/widgets/loading_dialog.dart';
import 'package:nfc_manager/nfc_manager.dart';
import 'package:nfc_manager/platform_tags.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart';
import 'package:test_sa/views/widgets/dialogs/confirm_dialog.dart';
@ -418,17 +417,40 @@ class Utils {
// }
static void readNFc({required Function(String) onRead}) {
NfcManager.instance.startSession(onDiscovered: (NfcTag tag) async {
MifareUltralight f;
if (Platform.isAndroid) {
f = MifareUltralight(tag: tag, identifier: tag.data["nfca"]["identifier"], type: 2, maxTransceiveLength: 252, timeout: 22);
} else {
f = MifareUltralight(tag: tag, identifier: tag.data["mifare"]["identifier"], type: 2, maxTransceiveLength: 252, timeout: 22);
NfcManager.instance.startSession(
onDiscovered: (NfcTag tag) async {
String identifier = '';
try {
final dynamic tagDynamic = tag;
final Map<String, dynamic> tagData = Map<String, dynamic>.from(tagDynamic.data as Map);
if (Platform.isAndroid) {
if (tagData.containsKey('nfca')) {
final nfcaData = tagData['nfca'] as Map<dynamic, dynamic>;
if (nfcaData.containsKey('identifier')) {
final List<int> idBytes = List<int>.from(nfcaData['identifier'] as List);
identifier = idBytes.map((e) => e.toRadixString(16).padLeft(2, '0')).join('');
}
}
} else {
if (tagData.containsKey('mifare')) {
final mifareData = tagData['mifare'] as Map<dynamic, dynamic>;
if (mifareData.containsKey('identifier')) {
final List<int> idBytes = List<int>.from(mifareData['identifier'] as List);
identifier = idBytes.map((e) => e.toRadixString(16).padLeft(2, '0')).join('');
}
}
}
} catch (e) {
print('Error reading NFC: $e');
}
String identifier = f.identifier.map((e) => e.toRadixString(16).padLeft(2, '0')).join('');
NfcManager.instance.stopSession();
onRead(identifier);
}).catchError((err) {
},
pollingOptions: {NfcPollingOption.iso14443},
).catchError((err) {
print(err);
});
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -4,9 +4,8 @@ import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_timezone/flutter_timezone.dart';
import 'package:localization/localization.dart';
import 'package:flutter_timezone/flutter_timezone.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/all_requests_provider.dart';
import 'package:test_sa/controllers/providers/api/comments_provider.dart';
@ -121,6 +120,7 @@ import 'controllers/providers/api/gas_refill_comments.dart';
import 'controllers/providers/api/user_provider.dart';
import 'controllers/providers/settings/setting_provider.dart';
import 'dashboard_latest/dashboard_provider.dart';
import 'l10n/app_localizations.dart';
import 'modules/demo_module/demo_document_lookup_provider.dart';
import 'modules/incident_module/create_incident_request_page.dart';
import 'modules/incident_module/incident_lookup_provider.dart';

@ -3,13 +3,12 @@ import 'dart:io';
import 'package:flutter/material.dart';
import 'package:nfc_manager/nfc_manager.dart';
import 'package:nfc_manager/platform_tags.dart';
import 'package:test_sa/dashboard_latest/dashboard_view.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/views/app_style/sizing.dart';
void showNfcReader(BuildContext context, {Function(String nfcId)? onNcfScan}) {
void showNfcReader(BuildContext context, {Function(String?)? onNcfScan}) {
showModalBottomSheet(
context: context,
enableDrag: false,
@ -27,9 +26,9 @@ void showNfcReader(BuildContext context, {Function(String nfcId)? onNcfScan}) {
}
class NfcLayout extends StatefulWidget {
Function(String nfcId)? onNcfScan;
final Function(String? nfcId)? onNcfScan;
NfcLayout({this.onNcfScan});
const NfcLayout({super.key, required this.onNcfScan});
@override
_NfcLayoutState createState() => _NfcLayoutState();
@ -44,14 +43,35 @@ class _NfcLayoutState extends State<NfcLayout> {
void initState() {
super.initState();
NfcManager.instance.startSession(onDiscovered: (NfcTag tag) async {
var f;
if (Platform.isAndroid) {
f = MifareUltralight(tag: tag, identifier: tag.data["nfca"]["identifier"], type: 2, maxTransceiveLength: 252, timeout: 22);
} else {
f = MifareUltralight(tag: tag, identifier: tag.data["mifare"]["identifier"], type: 2, maxTransceiveLength: 252, timeout: 22);
NfcManager.instance.startSession(
onDiscovered: (NfcTag tag) async {
String? identifier;
try {
final dynamic tagDynamic = tag;
final Map<String, dynamic> tagData = Map<String, dynamic>.from(tagDynamic.data as Map);
if (Platform.isAndroid) {
if (tagData.containsKey('nfca')) {
final nfcaData = tagData['nfca'] as Map<dynamic, dynamic>;
if (nfcaData.containsKey('identifier')) {
final List<int> idBytes = List<int>.from(nfcaData['identifier'] as List);
identifier = idBytes.map((e) => e.toRadixString(16).padLeft(2, '0')).join('');
}
}
} else {
if (tagData.containsKey('mifare')) {
final mifareData = tagData['mifare'] as Map<dynamic, dynamic>;
if (mifareData.containsKey('identifier')) {
final List<int> idBytes = List<int>.from(mifareData['identifier'] as List);
identifier = idBytes.map((e) => e.toRadixString(16).padLeft(2, '0')).join('');
}
}
}
} catch (e) {
print('Error reading NFC tag: $e');
}
String identifier = f.identifier.map((e) => e.toRadixString(16).padLeft(2, '0')).join('');
nfcId = identifier;
setState(() {
@ -62,15 +82,11 @@ class _NfcLayoutState extends State<NfcLayout> {
Future.delayed(const Duration(seconds: 1), () {
NfcManager.instance.stopSession();
Navigator.pop(context);
// if (Platform.isAndroid) {
// Navigator.pop(context);
// } else {
// Navigator.pop(context);
// Navigator.pop(context);
// }
widget.onNcfScan!(nfcId!);
});
}).catchError((err) {
},
pollingOptions: {NfcPollingOption.iso14443},
).catchError((err) {
print(err);
});
}

@ -10,7 +10,6 @@ import 'package:google_api_availability/google_api_availability.dart';
import 'package:huawei_location/huawei_location.dart';
import 'package:intl/intl.dart';
import 'package:nfc_manager/nfc_manager.dart';
import 'package:nfc_manager/platform_tags.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
@ -303,7 +302,7 @@ class SwipeGeneralUtils {
await _processNfcAttendance(nfcId, latitude, longitude, context);
});
} else {
showNfcReader(context, onNcfScan: (String nfcId) async {
showNfcReader(context, onNcfScan: (String? nfcId) async {
await _processNfcAttendance(nfcId ?? '', latitude, longitude, context);
});
}
@ -451,17 +450,40 @@ class SwipeGeneralUtils {
}
void readNFc({Function(String)? onRead}) {
NfcManager.instance.startSession(onDiscovered: (NfcTag tag) async {
MifareUltralight f;
if (Platform.isAndroid) {
f = MifareUltralight(tag: tag, identifier: tag.data["nfca"]["identifier"], type: 2, maxTransceiveLength: 252, timeout: 22);
} else {
f = MifareUltralight(tag: tag, identifier: tag.data["mifare"]["identifier"], type: 2, maxTransceiveLength: 252, timeout: 22);
NfcManager.instance.startSession(
onDiscovered: (NfcTag tag) async {
String identifier = '';
try {
final dynamic tagDynamic = tag;
final Map<String, dynamic> tagData = Map<String, dynamic>.from(tagDynamic.data as Map);
if (Platform.isAndroid) {
if (tagData.containsKey('nfca')) {
final nfcaData = tagData['nfca'] as Map<dynamic, dynamic>;
if (nfcaData.containsKey('identifier')) {
final List<int> idBytes = List<int>.from(nfcaData['identifier'] as List);
identifier = idBytes.map((e) => e.toRadixString(16).padLeft(2, '0')).join('');
}
}
} else {
if (tagData.containsKey('mifare')) {
final mifareData = tagData['mifare'] as Map<dynamic, dynamic>;
if (mifareData.containsKey('identifier')) {
final List<int> idBytes = List<int>.from(mifareData['identifier'] as List);
identifier = idBytes.map((e) => e.toRadixString(16).padLeft(2, '0')).join('');
}
}
}
} catch (e) {
print('Error reading NFC: $e');
}
String identifier = f.identifier.map((e) => e.toRadixString(16).padLeft(2, '0')).join('');
NfcManager.instance.stopSession();
onRead!(identifier);
}).catchError((err) {
},
pollingOptions: {NfcPollingOption.iso14443},
).catchError((err) {
print(err);
});
}

@ -3,7 +3,6 @@ import 'dart:io';
import 'package:flutter/material.dart';
import 'package:nfc_manager/nfc_manager.dart';
import 'package:nfc_manager/platform_tags.dart';
void showNfcReader(BuildContext context, {required Function(String? nfcId) onNcfScan}) {
showModalBottomSheet(
@ -23,9 +22,9 @@ void showNfcReader(BuildContext context, {required Function(String? nfcId) onNcf
}
class NfcLayout extends StatefulWidget {
Function(String? nfcId) onNcfScan;
final Function(String? nfcId) onNcfScan;
NfcLayout({required this.onNcfScan});
const NfcLayout({super.key, required this.onNcfScan});
@override
_NfcLayoutState createState() => _NfcLayoutState();
@ -40,33 +39,79 @@ class _NfcLayoutState extends State<NfcLayout> {
void initState() {
super.initState();
NfcManager.instance.startSession(onDiscovered: (NfcTag tag) async {
var f;
if (Platform.isAndroid) {
f = MifareUltralight(tag: tag, identifier: tag.data["nfca"]["identifier"], type: 2, maxTransceiveLength: 252, timeout: 22);
} else {
f = MifareUltralight(tag: tag, identifier: tag.data["mifare"]["identifier"], type: 2, maxTransceiveLength: 252, timeout: 22);
}
String identifier = f.identifier.map((e) => e.toRadixString(16).padLeft(2, '0')).join('');
nfcId = identifier;
setState(() {
_reading = true;
mainWidget = doneNfc();
});
Future.delayed(const Duration(seconds: 1), () {
NfcManager.instance.stopSession();
Navigator.pop(context);
// if (Platform.isAndroid) {
// Navigator.pop(context);
// } else {
// Navigator.pop(context);
// Navigator.pop(context);
// }
widget.onNcfScan(nfcId);
});
}).catchError((err) {
NfcManager.instance.startSession(
onDiscovered: (NfcTag tag) async {
String? identifier;
// Access tag identifier from the tag data
// In nfc_manager 4.1.1, access data via dynamic cast to bypass protected member
try {
final dynamic tagDynamic = tag;
final Map<String, dynamic> tagData = Map<String, dynamic>.from(tagDynamic.data as Map);
if (Platform.isAndroid) {
// For Android, try NfcA technology first
if (tagData.containsKey('nfca')) {
final nfcaData = tagData['nfca'] as Map<dynamic, dynamic>;
if (nfcaData.containsKey('identifier')) {
final List<int> idBytes = List<int>.from(nfcaData['identifier'] as List);
identifier = idBytes.map((e) => e.toRadixString(16).padLeft(2, '0')).join('');
}
}
// Fallback to other technologies if NfcA is not available
if (identifier == null && tagData.containsKey('nfcb')) {
final nfcbData = tagData['nfcb'] as Map<dynamic, dynamic>;
if (nfcbData.containsKey('identifier')) {
final List<int> idBytes = List<int>.from(nfcbData['identifier'] as List);
identifier = idBytes.map((e) => e.toRadixString(16).padLeft(2, '0')).join('');
}
}
} else {
// For iOS, try MiFare technology
if (tagData.containsKey('mifare')) {
final mifareData = tagData['mifare'] as Map<dynamic, dynamic>;
if (mifareData.containsKey('identifier')) {
final List<int> idBytes = List<int>.from(mifareData['identifier'] as List);
identifier = idBytes.map((e) => e.toRadixString(16).padLeft(2, '0')).join('');
}
}
// Fallback to iso15693 for iOS
if (identifier == null && tagData.containsKey('iso15693')) {
final iso15693Data = tagData['iso15693'] as Map<dynamic, dynamic>;
if (iso15693Data.containsKey('identifier')) {
final List<int> idBytes = List<int>.from(iso15693Data['identifier'] as List);
identifier = idBytes.map((e) => e.toRadixString(16).padLeft(2, '0')).join('');
}
}
}
// Universal fallback: try Ndef if available
if (identifier == null && tagData.containsKey('ndef')) {
final ndefData = tagData['ndef'] as Map<dynamic, dynamic>;
if (ndefData.containsKey('identifier')) {
final List<int> idBytes = List<int>.from(ndefData['identifier'] as List);
identifier = idBytes.map((e) => e.toRadixString(16).padLeft(2, '0')).join('');
}
}
} catch (e) {
print('Error reading NFC tag: $e');
}
nfcId = identifier;
setState(() {
_reading = true;
mainWidget = doneNfc();
});
Future.delayed(const Duration(seconds: 1), () {
NfcManager.instance.stopSession();
Navigator.pop(context);
widget.onNcfScan(nfcId);
});
},
pollingOptions: {NfcPollingOption.iso14443},
).catchError((err) {
print(err);
});
}
@ -96,7 +141,6 @@ class _NfcLayoutState extends State<NfcLayout> {
SizedBox(
height: 30,
),
Image.asset(
"assets/images/nfc_dummy.png",
height: MediaQuery.of(context).size.width / 3,
@ -159,7 +203,7 @@ class _NfcLayoutState extends State<NfcLayout> {
),
Image.asset(
// "assets/icons/nfc/ic_done.png",
"assets/images/done_dummy.jpeg",
"assets/images/done_dummy.jpeg",
height: MediaQuery.of(context).size.width / 3,
width: double.infinity,
),

@ -40,9 +40,7 @@ class _RecordSoundState extends State<TextSpeechRecordWidget> {
bool _recorderIsOpened = false;
bool _recording = false;
final bool _played = false;
String? _record;
Artboard? _rive;
Timer? _timer;
late TextEditingController _timeController;
late TextEditingController _commentController;
@ -78,31 +76,6 @@ class _RecordSoundState extends State<TextSpeechRecordWidget> {
node.unfocus();
_recorderIsOpened = true;
_settingProvider = Provider.of(context,listen: false);
// RecordMp3.instance.start(recordFilePath, (type) {
// // record fail callback
// });
// _myRecorder.openRecorder().then((value) {
// _recorderIsOpened = true;
// setState(() {});
// });
// Load the animation file from the bundle, note that you could also
// download this. The RiveFile just expects a list of bytes.
rootBundle.load('assets/rives/recording.riv').then(
(data) async {
// Load the RiveFile from the binary data.
final file = RiveFile.import(data);
// The artboard is the root of the animation and gets drawn in the
// Rive widget.
final artboard = file.mainArtboard;
// Add a controller to play back a known animation on the main/default
// artboard.We store a reference to it so we can toggle playback.
artboard.addController(SimpleAnimation('recording'));
_rive = artboard;
setState(() {});
},
);
}
@override
@ -131,7 +104,7 @@ class _RecordSoundState extends State<TextSpeechRecordWidget> {
String duration = Duration(seconds: timer.tick).toString();
duration = duration.substring(duration.indexOf(":") + 1, duration.indexOf("."));
String recordTime = ((timer.tick ?? 0) / 60).toStringAsFixed(2).replaceFirst(".", ":");
String recordTime = (timer.tick / 60).toStringAsFixed(2).replaceFirst(".", ":");
// print("recordTime:$recordTime");
if (recordTime.length == 4 || recordTime.length == 7) {
recordTime = "0$recordTime";
@ -139,7 +112,6 @@ class _RecordSoundState extends State<TextSpeechRecordWidget> {
_timeController.text = duration;
});
});
_rive?.addController(SimpleAnimation('recording'));
if (!_recorderIsOpened) {
// await _myRecorder.openRecorder();
_recorderIsOpened = true;
@ -198,21 +170,14 @@ class _RecordSoundState extends State<TextSpeechRecordWidget> {
_cancelRecording() async {
if (!_recording) return;
RecordMp3.instance.stop();
// String path = await _myRecorder.stopRecorder();
// _myRecorder.deleteRecord(fileName: path);
_rive?.addController(SimpleAnimation('delete'));
// rebuild();
_recording = false;
await Future.delayed(const Duration(seconds: 1));
await Future.delayed(const Duration(milliseconds: 300));
if (!_recording) setState(() {});
// _message.memoryAudio.;
}
@override
Widget build(BuildContext context) {
if (node.hasFocus && widget.enabled) node.unfocus();
_settingProvider ??= Provider.of<SettingProvider>(context);
return Column(
mainAxisSize: MainAxisSize.min,
children: [

@ -7,7 +7,6 @@ import 'package:fluttertoast/fluttertoast.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:record_mp3_plus/record_mp3_plus.dart';
import 'package:rive/rive.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
@ -33,9 +32,7 @@ class _RecordSoundState extends State<RecordSound> {
bool _recorderIsOpened = false;
bool _recording = false;
final bool _played = false;
String? _record;
late Artboard _rive;
Timer? _timer;
late TextEditingController _timeController;
@ -52,31 +49,6 @@ class _RecordSoundState extends State<RecordSound> {
_timeController = TextEditingController();
node.unfocus();
_recorderIsOpened = true;
// RecordMp3.instance.start(recordFilePath, (type) {
// // record fail callback
// });
// _myRecorder.openRecorder().then((value) {
// _recorderIsOpened = true;
// setState(() {});
// });
// Load the animation file from the bundle, note that you could also
// download this. The RiveFile just expects a list of bytes.
rootBundle.load('assets/rives/recording.riv').then(
(data) async {
// Load the RiveFile from the binary data.
final file = RiveFile.import(data);
// The artboard is the root of the animation and gets drawn in the
// Rive widget.
final artboard = file.mainArtboard;
// Add a controller to play back a known animation on the main/default
// artboard.We store a reference to it so we can toggle playback.
artboard.addController(SimpleAnimation('recording'));
_rive = artboard;
setState(() {});
},
);
}
@override
@ -113,7 +85,6 @@ class _RecordSoundState extends State<RecordSound> {
_timeController.text = duration;
});
});
_rive.addController(SimpleAnimation('recording'));
if (!_recorderIsOpened) {
// await _myRecorder.openRecorder();
_recorderIsOpened = true;
@ -150,15 +121,9 @@ class _RecordSoundState extends State<RecordSound> {
_cancelRecording() async {
if (!_recording) return;
RecordMp3.instance.stop();
// String path = await _myRecorder.stopRecorder();
// _myRecorder.deleteRecord(fileName: path);
_rive.addController(SimpleAnimation('delete'));
// rebuild();
_recording = false;
await Future.delayed(const Duration(seconds: 1));
await Future.delayed(const Duration(milliseconds: 300));
if (!_recording) setState(() {});
// _message.memoryAudio.;
}
@override

File diff suppressed because it is too large Load Diff

@ -37,46 +37,52 @@ dependencies:
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.5
font_awesome_flutter: ^10.2.1
http: ^1.2.2
provider: ^6.0.3
shared_preferences: ^2.0.15
fluttertoast: ^8.0.9
image_picker: ^1.1.2
url_launcher: ^6.1.6
flutter_launcher_icons: ^0.13.1
package_info_plus: ^8.3.0
font_awesome_flutter: ^10.12.0
http: ^1.6.0
provider: ^6.1.5+1
shared_preferences: ^2.5.4
fluttertoast: ^9.0.0
image_picker: ^1.2.1
url_launcher: ^6.3.2
flutter_launcher_icons: ^0.14.4
package_info_plus: ^8.3.1
share_plus: ^10.1.4
flutter_local_notifications: ^17.2.2
cached_network_image: ^3.2.2
carousel_slider: ^5.0.0
intl: ^0.19.0
flutter_local_notifications: ^17.2.4
cached_network_image: ^3.4.1
carousel_slider: ^5.1.2
intl: ^0.20.2
flutter_typeahead: ^5.2.0
speech_to_text: ^7.0.0
firebase_core: ^3.4.1
firebase_messaging: ^15.1.1
qr_code_scanner_plus: ^2.0.12
flutter_sound: ^9.3.1
permission_handler: ^11.3.1
rive: ^0.13.13
another_flushbar:
pinput:
audioplayers: ^6.1.0
flare_flutter: ^3.0.2
signature: ^5.3.0
flutter_svg: ^2.0.10+1
file_picker: ^8.1.2
record_mp3_plus: any
path_provider: ^2.1.0
open_file: ^3.3.2
speech_to_text: ^7.3.0
firebase_core: ^3.15.2
firebase_messaging: ^15.2.10
qr_code_scanner_plus: ^2.1.1
flutter_sound: ^9.30.0
permission_handler: ^11.4.0
rive: ^0.14.4
another_flushbar: ^1.12.32
pinput: ^6.0.2
audioplayers: ^6.6.0
flare_flutter:
git:
url: https://github.com/mbfakourii/Flare-Flutter.git
path: flare_flutter
ref: remove_hashValues
signature: ^5.5.0
flutter_svg: ^2.2.3
file_picker: ^8.3.7
record_mp3_plus: ^1.4.1
path_provider: ^2.1.5
open_file: ^3.5.11
localization: ^2.1.0
dotted_border: ^2.1.0
lottie: ^3.1.2
lottie: ^3.3.2
shimmer: ^3.0.0
date_picker_timeline: ^1.2.6
flutter_advanced_switch: ^3.0.1
table_calendar: ^3.0.8
image_cropper: ^8.0.2
image_cropper: ^8.1.0
flutter_timezone: ^3.0.1
device_calendar: ^4.3.3
pie_chart: ^5.4.0
@ -85,32 +91,28 @@ dependencies:
# buttons_tabbar: ^1.1.2
flutter_custom_month_picker: ^0.1.3
local_auth: ^2.3.0
google_api_availability: ^5.0.0
huawei_push: ^6.13.0+300
huawei_location: ^6.14.2+301
google_api_availability: ^5.0.1
huawei_push: ^6.14.0+300
huawei_location: ^6.16.0+300
geolocator: ^9.0.2
nfc_manager: ^3.2.0
wifi_iot: ^0.3.19+1
just_audio: ^0.9.30
safe_device: ^1.2.1
nfc_manager: ^4.1.1
wifi_iot: ^0.3.19+2
just_audio: ^0.9.46
safe_device: ^1.3.8
toggle_switch: ^2.3.0
clipboard: ^2.0.2
clipboard: ^3.0.14
tree_view_flutter: ^1.0.2
audio_waveforms: ^1.3.0
signalr_netcore: ^1.4.4
ellipsized_text: ^1.2.0
ellipsized_text: ^2.0.0
local_auth_darwin: any
local_auth_darwin: ^1.4.0
dev_dependencies:
flutter_test:
sdk: flutter
dependency_overrides:
sqflite_android: 2.4.1
win32: ^5.5.4
# The "flutter_lints" package below contains a set of recommended lints to
# encourage good coding practices. The lint set provided by the package is
# activated in the `analysis_options.yaml` file located at the root of your
# package. See that file for information about deactivating specific lint
# rules and activating additional ones.
flutter_lints: ^2.0.0
flutter_icons:

Loading…
Cancel
Save