Compare commits
2 Commits
8eeed78084
...
f67ab0f40c
| Author | SHA1 | Date | |
|---|---|---|---|
| f67ab0f40c | |||
| 6b1d4b8cea |
@@ -1,12 +1,23 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<!-- Bluetooth permissions for Android 12 (API 31) and higher -->
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" />
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
|
||||||
|
|
||||||
|
<!-- Legacy Bluetooth permissions for Android 11 (API 30) and lower -->
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
|
||||||
|
|
||||||
|
<!-- Location permissions (required for Bluetooth scanning on older Android versions) -->
|
||||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
|
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:label="teste_projeto_turma"
|
android:label="runvisionpro_app"
|
||||||
android:name="${applicationName}"
|
android:name="${applicationName}"
|
||||||
android:icon="@mipmap/ic_launcher">
|
android:icon="@mipmap/ic_launcher">
|
||||||
<activity
|
<activity
|
||||||
@@ -18,10 +29,6 @@
|
|||||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
||||||
android:hardwareAccelerated="true"
|
android:hardwareAccelerated="true"
|
||||||
android:windowSoftInputMode="adjustResize">
|
android:windowSoftInputMode="adjustResize">
|
||||||
<!-- Specifies an Android theme to apply to this Activity as soon as
|
|
||||||
the Android process has started. This theme is visible to the user
|
|
||||||
while the Flutter UI initializes. After that, this theme continues
|
|
||||||
to determine the Window background behind the Flutter UI. -->
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="io.flutter.embedding.android.NormalTheme"
|
android:name="io.flutter.embedding.android.NormalTheme"
|
||||||
android:resource="@style/NormalTheme"
|
android:resource="@style/NormalTheme"
|
||||||
@@ -31,21 +38,13 @@
|
|||||||
<category android:name="android.intent.category.LAUNCHER"/>
|
<category android:name="android.intent.category.LAUNCHER"/>
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<!-- Don't delete the meta-data below.
|
|
||||||
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="flutterEmbedding"
|
android:name="flutterEmbedding"
|
||||||
android:value="2" />
|
android:value="2" />
|
||||||
|
|
||||||
<!-- TODO: Replace with your actual Google Maps API Key -->
|
|
||||||
<meta-data android:name="com.google.android.geo.API_KEY"
|
<meta-data android:name="com.google.android.geo.API_KEY"
|
||||||
android:value="AIzaSyCk84rxmF044cxKLABf55rEKHDqOcyoV5k"/>
|
android:value="AIzaSyCk84rxmF044cxKLABf55rEKHDqOcyoV5k"/>
|
||||||
</application>
|
</application>
|
||||||
<!-- Required to query activities that can process text, see:
|
|
||||||
https://developer.android.com/training/package-visibility and
|
|
||||||
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
|
|
||||||
|
|
||||||
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
|
|
||||||
<queries>
|
<queries>
|
||||||
<intent>
|
<intent>
|
||||||
<action android:name="android.intent.action.PROCESS_TEXT"/>
|
<action android:name="android.intent.action.PROCESS_TEXT"/>
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ class BluetoothConnectionScreen extends StatefulWidget {
|
|||||||
class _BluetoothConnectionScreenState extends State<BluetoothConnectionScreen> {
|
class _BluetoothConnectionScreenState extends State<BluetoothConnectionScreen> {
|
||||||
List<ScanResult> _scanResults = [];
|
List<ScanResult> _scanResults = [];
|
||||||
bool _isScanning = false;
|
bool _isScanning = false;
|
||||||
BluetoothDevice? _connectedDevice; // Track connected device
|
BluetoothDevice? _connectedDevice;
|
||||||
late StreamSubscription<List<ScanResult>> _scanResultsSubscription;
|
late StreamSubscription<List<ScanResult>> _scanResultsSubscription;
|
||||||
late StreamSubscription<bool> _isScanningSubscription;
|
late StreamSubscription<bool> _isScanningSubscription;
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ class _BluetoothConnectionScreenState extends State<BluetoothConnectionScreen> {
|
|||||||
_scanResultsSubscription = FlutterBluePlus.scanResults.listen((results) {
|
_scanResultsSubscription = FlutterBluePlus.scanResults.listen((results) {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
setState(() {
|
setState(() {
|
||||||
// FILTRO: Mantém apenas dispositivos que possuem um nome identificado
|
// Filtra os dispositivos para mostrar apenas aqueles que possuem um nome identificado
|
||||||
_scanResults = results.where((r) => r.device.platformName.isNotEmpty).toList();
|
_scanResults = results.where((r) => r.device.platformName.isNotEmpty).toList();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -54,16 +54,30 @@ class _BluetoothConnectionScreenState extends State<BluetoothConnectionScreen> {
|
|||||||
Map<Permission, PermissionStatus> statuses = await [
|
Map<Permission, PermissionStatus> statuses = await [
|
||||||
Permission.bluetoothScan,
|
Permission.bluetoothScan,
|
||||||
Permission.bluetoothConnect,
|
Permission.bluetoothConnect,
|
||||||
|
Permission.bluetoothAdvertise,
|
||||||
Permission.location,
|
Permission.location,
|
||||||
].request();
|
].request();
|
||||||
|
|
||||||
if (statuses[Permission.bluetoothScan]!.isGranted &&
|
bool allGranted = true;
|
||||||
statuses[Permission.bluetoothConnect]!.isGranted) {
|
if (statuses[Permission.bluetoothScan]?.isDenied ?? true) allGranted = false;
|
||||||
|
if (statuses[Permission.bluetoothConnect]?.isDenied ?? true) allGranted = false;
|
||||||
|
|
||||||
|
final bool scanPermanentlyDenied = statuses[Permission.bluetoothScan]?.isPermanentlyDenied ?? false;
|
||||||
|
final bool connectPermanentlyDenied = statuses[Permission.bluetoothConnect]?.isPermanentlyDenied ?? false;
|
||||||
|
|
||||||
|
if (scanPermanentlyDenied || connectPermanentlyDenied) {
|
||||||
|
if (mounted) {
|
||||||
|
_showSettingsDialog();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allGranted) {
|
||||||
_startScan();
|
_startScan();
|
||||||
} else {
|
} else {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(
|
const SnackBar(
|
||||||
content: Text(AppStrings.permissionsDenied),
|
content: Text(AppStrings.permissionsDenied),
|
||||||
behavior: SnackBarBehavior.floating,
|
behavior: SnackBarBehavior.floating,
|
||||||
),
|
),
|
||||||
@@ -75,12 +89,35 @@ class _BluetoothConnectionScreenState extends State<BluetoothConnectionScreen> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _showSettingsDialog() {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => AlertDialog(
|
||||||
|
title: const Text("Permissões Necessárias"),
|
||||||
|
content: const Text("As permissões de Bluetooth foram negadas permanentemente. Por favor, habilite-as nas configurações do sistema para continuar."),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.pop(context),
|
||||||
|
child: const Text("CANCELAR"),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
openAppSettings();
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
child: const Text("CONFIGURAÇÕES"),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> _startScan() async {
|
Future<void> _startScan() async {
|
||||||
try {
|
try {
|
||||||
if (await FlutterBluePlus.adapterState.first != BluetoothAdapterState.on) {
|
if (await FlutterBluePlus.adapterState.first != BluetoothAdapterState.on) {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(
|
const SnackBar(
|
||||||
content: Text(AppStrings.turnOnBluetooth),
|
content: Text(AppStrings.turnOnBluetooth),
|
||||||
behavior: SnackBarBehavior.floating,
|
behavior: SnackBarBehavior.floating,
|
||||||
),
|
),
|
||||||
@@ -89,7 +126,9 @@ class _BluetoothConnectionScreenState extends State<BluetoothConnectionScreen> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await FlutterBluePlus.startScan(timeout: const Duration(seconds: 15));
|
await FlutterBluePlus.startScan(
|
||||||
|
timeout: const Duration(seconds: 15),
|
||||||
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
@@ -135,7 +174,7 @@ class _BluetoothConnectionScreenState extends State<BluetoothConnectionScreen> {
|
|||||||
});
|
});
|
||||||
FlutterBluePlus.stopScan();
|
FlutterBluePlus.stopScan();
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(
|
const SnackBar(
|
||||||
content: Text(AppStrings.connectedSuccess),
|
content: Text(AppStrings.connectedSuccess),
|
||||||
backgroundColor: AppColors.success,
|
backgroundColor: AppColors.success,
|
||||||
behavior: SnackBarBehavior.floating,
|
behavior: SnackBarBehavior.floating,
|
||||||
@@ -190,7 +229,6 @@ class _BluetoothConnectionScreenState extends State<BluetoothConnectionScreen> {
|
|||||||
Column(
|
Column(
|
||||||
children: [
|
children: [
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
// Header Card
|
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 25),
|
padding: const EdgeInsets.symmetric(horizontal: 25),
|
||||||
child: Container(
|
child: Container(
|
||||||
@@ -282,7 +320,6 @@ class _BluetoothConnectionScreenState extends State<BluetoothConnectionScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 30),
|
const SizedBox(height: 30),
|
||||||
// Device List
|
|
||||||
Expanded(
|
Expanded(
|
||||||
child: ListView.builder(
|
child: ListView.builder(
|
||||||
itemCount: _connectedDevice != null ? 1 : _scanResults.length,
|
itemCount: _connectedDevice != null ? 1 : _scanResults.length,
|
||||||
|
|||||||
16
pubspec.lock
16
pubspec.lock
@@ -37,10 +37,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: characters
|
name: characters
|
||||||
sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803
|
sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.4.0"
|
version: "1.4.1"
|
||||||
clock:
|
clock:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -388,18 +388,18 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: matcher
|
name: matcher
|
||||||
sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2
|
sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.12.17"
|
version: "0.12.19"
|
||||||
material_color_utilities:
|
material_color_utilities:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: material_color_utilities
|
name: material_color_utilities
|
||||||
sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
|
sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.11.1"
|
version: "0.13.0"
|
||||||
meta:
|
meta:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -577,10 +577,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: test_api
|
name: test_api
|
||||||
sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55
|
sha256: "8161c84903fd860b26bfdefb7963b3f0b68fee7adea0f59ef805ecca346f0c7a"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.7.7"
|
version: "0.7.10"
|
||||||
typed_data:
|
typed_data:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
Reference in New Issue
Block a user