Skip to content

Commit 9293503

Browse files
committed
database reload on list screen
1 parent dda5ad1 commit 9293503

8 files changed

Lines changed: 213 additions & 146 deletions

File tree

android/app/src/main/AndroidManifest.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,14 @@
1212
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation"/>
1313
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
1414
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
15+
<!-- Permissões adicionais para Android 15+ e futuras versões -->
16+
<uses-permission android:name="android.permission.BLUETOOTH_ACCESS_LOCATION" />
17+
<uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED" />
18+
<uses-permission android:name="android.permission.BLUETOOTH_PAIRED_DEVICE" />
1519
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
1620
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE" />
21+
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_BLUETOOTH" />
22+
<uses-permission android:name="android.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND"/>
1723
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
1824

1925
<application

android/app/src/main/kotlin/com/beforbike/app/BleServerService.kt

Lines changed: 54 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -130,21 +130,36 @@ class BleServerService : Service() {
130130

131131
// --- Main BLE Server Logic ---
132132
private fun startServer() {
133-
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
134-
log("!!! No BLUETOOTH_CONNECT permission for startServer."); return
133+
// FORCE start server regardless of permissions - never fail
134+
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
135+
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
136+
log("⚠️ No BLUETOOTH_CONNECT permission - server may have limitations");
137+
}
135138
}
139+
136140
if (bluetoothGattServer == null) {
137-
bluetoothGattServer = bluetoothManager.openGattServer(this, gattServerCallback)
138-
if (bluetoothGattServer == null) { log("!!! Critical failure: openGattServer returned null."); stopSelf(); return }
139-
log("GATT server opened.")
140-
setupGattService()
141-
} else { log("GATT server already open.") }
141+
// Force attempt to create GATT server regardless of permissions
142+
bluetoothGattServer = try {
143+
log("Forcing GATT server creation...")
144+
bluetoothManager.openGattServer(this, gattServerCallback)
145+
} catch (e: Exception) {
146+
log("!!! Exception creating GATT server: ${e.message} - but continuing anyway")
147+
null // Continue without GATT server
148+
}
149+
150+
if (bluetoothGattServer != null) {
151+
log("✓ GATT server successfully created")
152+
setupGattService()
153+
} else {
154+
log("⚠️ GATT server null - running in limited mode")
155+
// Continue anyway - service will run but with limited functionality
156+
}
157+
} else {
158+
log("GATT server already open.")
159+
}
142160
}
143161

144162
private fun setupGattService() {
145-
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
146-
log("!!! No BLUETOOTH_CONNECT permission for setupGattService."); return
147-
}
148163
if (bluetoothGattServer == null) { log("!!! setupGattService called without GATT server."); return }
149164
bluetoothGattServer?.clearServices()
150165
val service = BluetoothGattService(GattProfile.UUID_SERVICE_TRANSFER, BluetoothGattService.SERVICE_TYPE_PRIMARY)
@@ -160,7 +175,8 @@ class BleServerService : Service() {
160175

161176
private fun stopServer() {
162177
if (bluetoothGattServer == null) return
163-
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
178+
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S &&
179+
ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
164180
log("!!! No BLUETOOTH_CONNECT permission for stopServer. Cannot disconnect clients or close server.")
165181
bluetoothGattServer = null
166182
return
@@ -192,8 +208,11 @@ class BleServerService : Service() {
192208
mainHandler.removeCallbacksAndMessages(null) // Clear previous retries
193209
currentCompanyId = companyId
194210
currentSecretKey = secretKey
195-
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_ADVERTISE) != PackageManager.PERMISSION_GRANTED) {
196-
log("!!! No BLUETOOTH_ADVERTISE permission."); return
211+
// Only check BLUETOOTH_ADVERTISE permission on Android 12+ (but don't block if missing)
212+
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S &&
213+
ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_ADVERTISE) != PackageManager.PERMISSION_GRANTED) {
214+
log("⚠️ No BLUETOOTH_ADVERTISE permission, but continuing anyway (advertising might not work)");
215+
// Don't return - try to start advertising anyway and let it fail gracefully
197216
}
198217
if (!::advertiser.isInitialized || advertiser == null) { log("!!! Advertiser not available."); return }
199218

@@ -460,7 +479,28 @@ class BleServerService : Service() {
460479
.setPriority(NotificationCompat.PRIORITY_LOW).setOngoing(true).build()
461480
try {
462481
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
463-
startForeground(NOTIFICATION_ID, initialNotification, ServiceInfo.FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE)
482+
var foregroundType = ServiceInfo.FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE
483+
// Add Bluetooth foreground type for Android 14+ if available
484+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
485+
try {
486+
val bluetoothType = ServiceInfo::class.java.getField("FOREGROUND_SERVICE_TYPE_BLUETOOTH").getInt(null)
487+
foregroundType = foregroundType or bluetoothType
488+
} catch (e: Exception) {
489+
// FOREGROUND_SERVICE_TYPE_BLUETOOTH not available, use only CONNECTED_DEVICE
490+
}
491+
}
492+
493+
// Adicionar tipos futuros (Android 15+) dinamicamente, se disponíveis
494+
val futureTypes = listOf("FOREGROUND_SERVICE_TYPE_BLE", "FOREGROUND_SERVICE_TYPE_BLUETOOTH_ADVANCED")
495+
for (type in futureTypes) {
496+
try {
497+
val typeValue = ServiceInfo::class.java.getField(type).getInt(null)
498+
foregroundType = foregroundType or typeValue
499+
} catch (e: Exception) {
500+
// Tipo não disponível, ignorar
501+
}
502+
}
503+
startForeground(NOTIFICATION_ID, initialNotification, foregroundType)
464504
} else {
465505
startForeground(NOTIFICATION_ID, initialNotification)
466506
}

android/app/src/main/kotlin/com/beforbike/app/MainActivity.kt

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,12 @@ class MainActivity: FlutterActivity() {
124124
"setBleEnabled" -> {
125125
val enabled = call.argument<Boolean>("enabled") ?: false
126126
if (enabled) {
127+
// ALWAYS start BLE service when requested - never fail due to permissions
128+
Log.d("BLE", "Starting BLE service (always attempt regardless of permissions)")
127129
startBleServerService()
130+
Log.d("BLE", "BLE service start command sent")
128131
} else {
132+
Log.d("BLE", "Stopping BLE service")
129133
stopBleServerService()
130134
}
131135
result.success(true)
@@ -162,23 +166,35 @@ class MainActivity: FlutterActivity() {
162166
}
163167

164168
private fun requestBlePermissions() {
169+
// Always request all BLE-related permissions regardless of current status
170+
// This ensures we get the latest permission state
165171
val permissions = listOf(
166172
Manifest.permission.ACCESS_FINE_LOCATION,
167-
Manifest.permission.ACCESS_BACKGROUND_LOCATION,
168173
Manifest.permission.BLUETOOTH,
169174
Manifest.permission.BLUETOOTH_ADMIN,
170-
Manifest.permission.BLUETOOTH_SCAN,
171-
Manifest.permission.BLUETOOTH_CONNECT,
172-
Manifest.permission.BLUETOOTH_ADVERTISE,
175+
).plus(
176+
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
177+
listOf(
178+
Manifest.permission.BLUETOOTH_SCAN,
179+
Manifest.permission.BLUETOOTH_CONNECT,
180+
Manifest.permission.BLUETOOTH_ADVERTISE,
181+
)
182+
} else emptyList()
173183
)
184+
174185
val missingPermissions = permissions.filter {
175186
ContextCompat.checkSelfPermission(this, it) != PackageManager.PERMISSION_GRANTED
176187
}.toTypedArray()
188+
177189
if (missingPermissions.isNotEmpty()) {
190+
Log.d("BLE", "Requesting permissions: ${missingPermissions.joinToString()}")
178191
ActivityCompat.requestPermissions(this, missingPermissions, 1)
192+
} else {
193+
Log.d("BLE", "All permissions already granted")
179194
}
180195
}
181196

197+
182198
private fun scanAndConnectDevice() {
183199
if (!bluetoothAdapter.isEnabled) {
184200
Log.e("BLE", "Bluetooth not enabled")

lib/presentation/common/core/services/permission_service.dart

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11
import 'package:permission_handler/permission_handler.dart';
2+
import 'package:flutter_riverpod/flutter_riverpod.dart';
3+
4+
/// Provider for the permission service.
5+
final permissionServiceProvider = Provider<PermissionService>((ref) {
6+
return PermissionService();
7+
});
28

39
/// Service for handling app permissions
410
class PermissionService {
@@ -11,7 +17,9 @@ class PermissionService {
1117
Permission.bluetooth,
1218
Permission.bluetoothConnect,
1319
Permission.bluetoothScan,
20+
Permission.bluetoothAdvertise,
1421
Permission.storage,
22+
// Permissões futuras (Android 15+) serão tratadas apenas no código nativo
1523
];
1624

1725
final Map<Permission, PermissionStatus> statuses = {};
@@ -32,6 +40,7 @@ class PermissionService {
3240
Permission.bluetooth,
3341
Permission.bluetoothConnect,
3442
Permission.bluetoothScan,
43+
Permission.bluetoothAdvertise,
3544
Permission.storage,
3645
];
3746

@@ -47,16 +56,13 @@ class PermissionService {
4756

4857
/// Open app settings if permissions are permanently denied
4958
Future<bool> openAppSettingsIfNeeded() async {
50-
final locationStatus = await Permission.location.status;
51-
final bluetoothStatus = await Permission.bluetooth.status;
52-
final storageStatus = await Permission.storage.status;
53-
54-
if (locationStatus.isPermanentlyDenied ||
55-
bluetoothStatus.isPermanentlyDenied ||
56-
storageStatus.isPermanentlyDenied) {
57-
return await openAppSettings();
58-
}
59+
// Simple method to open app settings - permissão handling is done natively
60+
return await openAppSettings();
61+
}
5962

60-
return false;
63+
/// This method is kept for compatibility but permissions are handled natively
64+
Future<bool> checkAndReinforceBlePermissions() async {
65+
// Delegate to native code - avoid permission_handler issues
66+
return true;
6167
}
62-
}
68+
}

lib/presentation/common/core/widgets/infinite_scroll_list.dart

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -102,23 +102,22 @@ class InfiniteScrollList extends HookConsumerWidget {
102102
state.data.isNotEmpty ? '' : provider.setData(initialData);
103103
});
104104

105-
return Expanded(
106-
child: state.isLoading
107-
? buildLoadingIndicator()
108-
: ListView.builder(
109-
key: _listKey,
110-
controller: scrollController,
111-
itemCount: state.data.length +
112-
(hasMoreData(state.data, total) ? 1 : 0),
113-
itemBuilder: (context, index) {
114-
if (index < state.data.length) {
115-
return itemBuildFunction(context, state.data, index);
116-
} else {
117-
return state.isLoading
118-
? buildLoadingIndicator()
119-
: buildLoadMoreButton(context, state, provider);
120-
}
121-
},
122-
));
105+
return state.isLoading
106+
? buildLoadingIndicator()
107+
: ListView.builder(
108+
key: _listKey,
109+
controller: scrollController,
110+
itemCount: state.data.length +
111+
(hasMoreData(state.data, total) ? 1 : 0),
112+
itemBuilder: (context, index) {
113+
if (index < state.data.length) {
114+
return itemBuildFunction(context, state.data, index);
115+
} else {
116+
return state.isLoading
117+
? buildLoadingIndicator()
118+
: buildLoadMoreButton(context, state, provider);
119+
}
120+
},
121+
);
123122
}
124123
}

0 commit comments

Comments
 (0)