Showing
3 changed files
with
99 additions
and
25 deletions
| @@ -921,9 +921,13 @@ class TodayController extends GetxController with WidgetsBindingObserver { | @@ -921,9 +921,13 @@ class TodayController extends GetxController with WidgetsBindingObserver { | ||
| 921 | // changeDate(today); | 921 | // changeDate(today); |
| 922 | checkAddFriendVisible(); | 922 | checkAddFriendVisible(); |
| 923 | checkHrvAdBannerVisible(); | 923 | checkHrvAdBannerVisible(); |
| 924 | + final isSelectedToday = DateUtils.isSameDay( | ||
| 925 | + DateUtils.dateOnly(selectedDate.value), | ||
| 926 | + DateUtils.dateOnly(DateTime.now()), | ||
| 927 | + ); | ||
| 924 | checkHealthDataAuthCardVisible( | 928 | checkHealthDataAuthCardVisible( |
| 925 | isPullToRefresh: isPullToRefresh, | 929 | isPullToRefresh: isPullToRefresh, |
| 926 | - shouldCaculateAndUpload: isOhos(), | 930 | + shouldCaculateAndUpload: isOhos() && isSelectedToday, |
| 927 | ); | 931 | ); |
| 928 | checkNotificationAuthorizationBannerVisible(); | 932 | checkNotificationAuthorizationBannerVisible(); |
| 929 | // await loadDataForDate(selectedDate.value); | 933 | // await loadDataForDate(selectedDate.value); |
| @@ -210,17 +210,6 @@ class OHOSHealthRawDataCoreService { | @@ -210,17 +210,6 @@ class OHOSHealthRawDataCoreService { | ||
| 210 | } | 210 | } |
| 211 | 211 | ||
| 212 | final userId = _userId; | 212 | final userId = _userId; |
| 213 | - final hasAuthorization = await _hasHealthReadAuthorization(); | ||
| 214 | - if (!hasAuthorization) { | ||
| 215 | - _logInfo('skip calculate without OHOS health privacy authorization'); | ||
| 216 | - return HealthRawStressCalculationResult( | ||
| 217 | - userId: userId, | ||
| 218 | - hrvStressPoints: const <HealthRawHrvStressPoint>[], | ||
| 219 | - realtimeStressPoints: const <HealthRawRealtimeStressPoint>[], | ||
| 220 | - dailyStressPoints: const <HealthRawDailyStressPoint>[], | ||
| 221 | - sleepResults: const <HealthRawSleepResult>[], | ||
| 222 | - ); | ||
| 223 | - } | ||
| 224 | await _localStore.ensureReadable(userId); | 213 | await _localStore.ensureReadable(userId); |
| 225 | final effectiveEndTime = | 214 | final effectiveEndTime = |
| 226 | endTime ?? DateTime.now().millisecondsSinceEpoch ~/ 1000; | 215 | endTime ?? DateTime.now().millisecondsSinceEpoch ~/ 1000; |
| @@ -233,10 +222,19 @@ class OHOSHealthRawDataCoreService { | @@ -233,10 +222,19 @@ class OHOSHealthRawDataCoreService { | ||
| 233 | if (effectiveEndTime < requestedStartTime) { | 222 | if (effectiveEndTime < requestedStartTime) { |
| 234 | throw ArgumentError.value(endTime, 'endTime'); | 223 | throw ArgumentError.value(endTime, 'endTime'); |
| 235 | } | 224 | } |
| 236 | - final syncResults = await _syncCalculationRawDataIfNeeded( | ||
| 237 | - startTime: requestedStartTime, | ||
| 238 | - endTime: effectiveEndTime, | ||
| 239 | - ); | 225 | + final hasAuthorization = await _hasHealthReadAuthorization(); |
| 226 | + final syncResults = hasAuthorization | ||
| 227 | + ? await _syncCalculationRawDataIfNeeded( | ||
| 228 | + startTime: requestedStartTime, | ||
| 229 | + endTime: effectiveEndTime, | ||
| 230 | + ) | ||
| 231 | + : const <OhosHealthRawDataSyncResult>[]; | ||
| 232 | + if (!hasAuthorization) { | ||
| 233 | + _logInfo( | ||
| 234 | + 'skip OHOS raw data sync without health privacy authorization; ' | ||
| 235 | + 'continue calculate and upload from local database', | ||
| 236 | + ); | ||
| 237 | + } | ||
| 240 | _logInfo( | 238 | _logInfo( |
| 241 | 'calculate_sync_finish startTime=$requestedStartTime ' | 239 | 'calculate_sync_finish startTime=$requestedStartTime ' |
| 242 | 'endTime=$effectiveEndTime syncResults=$syncResults', | 240 | 'endTime=$effectiveEndTime syncResults=$syncResults', |
| @@ -495,9 +493,6 @@ class OHOSHealthRawDataCoreService { | @@ -495,9 +493,6 @@ class OHOSHealthRawDataCoreService { | ||
| 495 | required int endTime, | 493 | required int endTime, |
| 496 | int readChunkDays = defaultReadChunkDays, | 494 | int readChunkDays = defaultReadChunkDays, |
| 497 | }) async { | 495 | }) async { |
| 498 | - if (!await _hasHealthReadAuthorization()) { | ||
| 499 | - return const <HealthKitRawDataPoint>[]; | ||
| 500 | - } | ||
| 501 | return _fetchRawDataInChunks( | 496 | return _fetchRawDataInChunks( |
| 502 | dataType, | 497 | dataType, |
| 503 | startTime, | 498 | startTime, |
| @@ -511,9 +506,6 @@ class OHOSHealthRawDataCoreService { | @@ -511,9 +506,6 @@ class OHOSHealthRawDataCoreService { | ||
| 511 | required int endTime, | 506 | required int endTime, |
| 512 | int readChunkDays = defaultReadChunkDays, | 507 | int readChunkDays = defaultReadChunkDays, |
| 513 | }) async { | 508 | }) async { |
| 514 | - if (!await _hasHealthReadAuthorization()) { | ||
| 515 | - return const <HealthKitRawDataPoint>[]; | ||
| 516 | - } | ||
| 517 | return _fetchSleepIntervalsInChunks( | 509 | return _fetchSleepIntervalsInChunks( |
| 518 | startTime, | 510 | startTime, |
| 519 | endTime, | 511 | endTime, |
| @@ -525,9 +517,6 @@ class OHOSHealthRawDataCoreService { | @@ -525,9 +517,6 @@ class OHOSHealthRawDataCoreService { | ||
| 525 | required int startTime, | 517 | required int startTime, |
| 526 | required int endTime, | 518 | required int endTime, |
| 527 | }) async { | 519 | }) async { |
| 528 | - if (!await _hasHealthReadAuthorization()) { | ||
| 529 | - return const <HealthKitRawActivityDataPoint>[]; | ||
| 530 | - } | ||
| 531 | final points = await _rawDataSource.getRawActivityData(startTime, endTime); | 520 | final points = await _rawDataSource.getRawActivityData(startTime, endTime); |
| 532 | return points | 521 | return points |
| 533 | .where((e) => e.endTime >= startTime && e.endTime <= endTime) | 522 | .where((e) => e.endTime >= startTime && e.endTime <= endTime) |
| @@ -581,6 +570,7 @@ class OHOSHealthRawDataCoreService { | @@ -581,6 +570,7 @@ class OHOSHealthRawDataCoreService { | ||
| 581 | if (rawDataSource is! OhosHealthRawDataSource) { | 570 | if (rawDataSource is! OhosHealthRawDataSource) { |
| 582 | return const <OhosHealthRawDataSyncResult>[]; | 571 | return const <OhosHealthRawDataSyncResult>[]; |
| 583 | } | 572 | } |
| 573 | + await rawDataSource.getActivityGoal(refresh: true); | ||
| 584 | return rawDataSource.syncCalculationRawData( | 574 | return rawDataSource.syncCalculationRawData( |
| 585 | startTime: startTime, | 575 | startTime: startTime, |
| 586 | endTime: endTime, | 576 | endTime: endTime, |
| 1 | import 'dart:io'; | 1 | import 'dart:io'; |
| 2 | 2 | ||
| 3 | import 'package:doublefeel_flutter/core/services/raw_data_service/health_raw_data_core_service.dart'; | 3 | import 'package:doublefeel_flutter/core/services/raw_data_service/health_raw_data_core_service.dart'; |
| 4 | +import 'package:doublefeel_flutter/core/services/raw_data_service/health_raw_data_source.dart'; | ||
| 4 | import 'package:doublefeel_flutter/core/services/raw_data_service/platform_ios/apple_health_raw_data_core_service.dart'; | 5 | import 'package:doublefeel_flutter/core/services/raw_data_service/platform_ios/apple_health_raw_data_core_service.dart'; |
| 5 | import 'package:doublefeel_flutter/core/services/raw_data_service/platform_ohos/ohos_health_raw_data_core_service.dart'; | 6 | import 'package:doublefeel_flutter/core/services/raw_data_service/platform_ohos/ohos_health_raw_data_core_service.dart'; |
| 7 | +import 'package:doublefeel_flutter/data/models/health/health_v2_models.dart'; | ||
| 8 | +import 'package:doublefeel_flutter/pigeon/health_kit_raw_data_api.g.dart'; | ||
| 6 | import 'package:flutter/foundation.dart'; | 9 | import 'package:flutter/foundation.dart'; |
| 7 | import 'package:flutter_test/flutter_test.dart'; | 10 | import 'package:flutter_test/flutter_test.dart'; |
| 8 | 11 | ||
| @@ -57,6 +60,29 @@ void main() { | @@ -57,6 +60,29 @@ void main() { | ||
| 57 | '${tempDir.path}/ohos_hrv_result_$userId.sqlite', | 60 | '${tempDir.path}/ohos_hrv_result_$userId.sqlite', |
| 58 | ); | 61 | ); |
| 59 | }); | 62 | }); |
| 63 | + | ||
| 64 | + test('OHOS local raw queries do not check remote authorization', () async { | ||
| 65 | + var authCheckCount = 0; | ||
| 66 | + final service = OHOSHealthRawDataCoreService( | ||
| 67 | + rawDataSource: _FakeHealthRawDataSource(), | ||
| 68 | + userIdProvider: () => 1, | ||
| 69 | + uploadResultsAfterCalculation: false, | ||
| 70 | + healthReadAuthorizationChecker: () async { | ||
| 71 | + authCheckCount += 1; | ||
| 72 | + return false; | ||
| 73 | + }, | ||
| 74 | + ); | ||
| 75 | + | ||
| 76 | + final points = await service.queryRawDataPoints( | ||
| 77 | + dataType: 2, | ||
| 78 | + startTime: 100, | ||
| 79 | + endTime: 200, | ||
| 80 | + ); | ||
| 81 | + | ||
| 82 | + expect(authCheckCount, 0); | ||
| 83 | + expect(points, hasLength(1)); | ||
| 84 | + expect(points.single.endTime, 123); | ||
| 85 | + }); | ||
| 60 | } | 86 | } |
| 61 | 87 | ||
| 62 | class _FakeAppleHealthRawDataCoreService extends AppleHealthRawDataCoreService { | 88 | class _FakeAppleHealthRawDataCoreService extends AppleHealthRawDataCoreService { |
| @@ -98,3 +124,57 @@ class _FakeOhosHealthRawDataCoreService extends OHOSHealthRawDataCoreService { | @@ -98,3 +124,57 @@ class _FakeOhosHealthRawDataCoreService extends OHOSHealthRawDataCoreService { | ||
| 98 | return false; | 124 | return false; |
| 99 | } | 125 | } |
| 100 | } | 126 | } |
| 127 | + | ||
| 128 | +class _FakeHealthRawDataSource implements HealthRawDataSource { | ||
| 129 | + @override | ||
| 130 | + Future<V2ActivityTarget?> getActivityGoal({bool refresh = true}) async { | ||
| 131 | + return null; | ||
| 132 | + } | ||
| 133 | + | ||
| 134 | + @override | ||
| 135 | + Future<List<HealthKitRawActivityDataPoint>> getRawActivityData( | ||
| 136 | + int startTime, | ||
| 137 | + int endTime, | ||
| 138 | + ) async { | ||
| 139 | + return [ | ||
| 140 | + HealthKitRawActivityDataPoint(endTime: 123, activeEnergyBurned: 10), | ||
| 141 | + ]; | ||
| 142 | + } | ||
| 143 | + | ||
| 144 | + @override | ||
| 145 | + Future<List<HealthKitRawDataPoint>> getRawData( | ||
| 146 | + int dataType, | ||
| 147 | + int startTime, | ||
| 148 | + int endTime, | ||
| 149 | + ) async { | ||
| 150 | + return [ | ||
| 151 | + HealthKitRawDataPoint( | ||
| 152 | + dataType: dataType, | ||
| 153 | + startTime: 123, | ||
| 154 | + endTime: 123, | ||
| 155 | + value: 72, | ||
| 156 | + ), | ||
| 157 | + ]; | ||
| 158 | + } | ||
| 159 | + | ||
| 160 | + @override | ||
| 161 | + Future<List<HealthKitRawSleepDataPoint>> getRawSleepData( | ||
| 162 | + int startTime, | ||
| 163 | + int endTime, | ||
| 164 | + ) async { | ||
| 165 | + return const <HealthKitRawSleepDataPoint>[]; | ||
| 166 | + } | ||
| 167 | + | ||
| 168 | + @override | ||
| 169 | + Future<List<HealthKitRawWorkoutDataPoint>> getRawWorkoutData( | ||
| 170 | + int startTime, | ||
| 171 | + int endTime, | ||
| 172 | + ) async { | ||
| 173 | + return const <HealthKitRawWorkoutDataPoint>[]; | ||
| 174 | + } | ||
| 175 | + | ||
| 176 | + @override | ||
| 177 | + Future<bool> hasHealthData() async { | ||
| 178 | + return true; | ||
| 179 | + } | ||
| 180 | +} |
-
Please register or login to post a comment