Skip to content

Commit

Permalink
Add more type safety for android
Browse files Browse the repository at this point in the history
  • Loading branch information
gdelataillade committed May 17, 2024
1 parent 4590911 commit d222abf
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 63 deletions.
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ final alarmSettings = AlarmSettings(
fadeDuration: 3.0,
notificationTitle: 'This is the title',
notificationBody: 'This is the body',
enableNotificationOnKill: true,
enableNotificationOnKill: Platform.isIOS,
);
```

Expand Down Expand Up @@ -138,6 +138,16 @@ While periodic alarms can be implemented on Android, this is not feasible for iO

Related issue [here](https://github.com/gdelataillade/alarm/issues/47#issuecomment-1820896276).

### Why does my app crash on iOS?

Crashes such as `EXC_BAD_ACCESS KERN_INVALID_ADDRESS` occur if `Alarm.set` and `Alarm.stop` methods are called concurrently, as they both modify shared resources. To prevent this, ensure each method call is completed before starting the next by using the `await` keyword in Dart:
```dart
await Alarm.set
await Alarm.stop
```
This approach ensures safe and exclusive access to shared resources, preventing crashes.


### Why was my app rejected by the App Store for guideline issues?

The rejection may relate to plugin's background audio functionality, essential for alarm apps. Clarify in your submission that background activity is crucial for your alarm app to notify users effectively. Ensure compliance with Apple's guidelines on background processes.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,44 +42,41 @@ class AlarmService : Service() {
return START_NOT_STICKY
}

val action = intent?.action
val id = intent?.getIntExtra("id", 0) ?: 0

if (action == "STOP_ALARM" && id != -1) {
val action = intent.action
val id = intent.getIntExtra("id", 0)
if (action == "STOP_ALARM" && id != 0) {
stopAlarm(id)
return START_NOT_STICKY
}

val assetAudioPath = intent?.getStringExtra("assetAudioPath")
val loopAudio = intent?.getBooleanExtra("loopAudio", true)
val vibrate = intent?.getBooleanExtra("vibrate", true)
val volume = intent?.getDoubleExtra("volume", -1.0) ?: -1.0
val fadeDuration = intent?.getDoubleExtra("fadeDuration", 0.0)
val notificationTitle = intent?.getStringExtra("notificationTitle")
val notificationBody = intent?.getStringExtra("notificationBody")
val fullScreenIntent = intent?.getBooleanExtra("fullScreenIntent", true)
showSystemUI = intent?.getBooleanExtra("showSystemUI", true) ?: true
val assetAudioPath = intent.getStringExtra("assetAudioPath") ?: return START_NOT_STICKY // Fallback if null
val loopAudio = intent.getBooleanExtra("loopAudio", true)
val vibrate = intent.getBooleanExtra("vibrate", true)
val volume = intent.getDoubleExtra("volume", -1.0)
val fadeDuration = intent.getDoubleExtra("fadeDuration", 0.0)
val notificationTitle = intent.getStringExtra("notificationTitle") ?: "Default Title" // Default if null
val notificationBody = intent.getStringExtra("notificationBody") ?: "Default Body" // Default if null
val fullScreenIntent = intent.getBooleanExtra("fullScreenIntent", true)

// Handling notification
val notificationHandler = NotificationHandler(this)
val appIntent = applicationContext.packageManager.getLaunchIntentForPackage(applicationContext.packageName)
val pendingIntent = PendingIntent.getActivity(this, id, appIntent, PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT)
val notification = notificationHandler.buildNotification(notificationTitle, notificationBody, fullScreenIntent, pendingIntent)

val intent = applicationContext.packageManager.getLaunchIntentForPackage(applicationContext.packageName)
val pendingIntent = PendingIntent.getActivity(this, id!!, intent, PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT)

val notification = notificationHandler.buildNotification(notificationTitle!!, notificationBody!!, fullScreenIntent!!, pendingIntent)

// Starting foreground service safely
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
startForeground(id, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK)
} else {
startForeground(id, notification)
}
} catch (e: ForegroundServiceStartNotAllowedException) {
// Specific handling for ForegroundServiceStartNotAllowedException
Log.e("AlarmService", "Foreground service start not allowed", e)
return START_NOT_STICKY // Return if cannot start foreground service
} catch (e: SecurityException) {
Log.e("AlarmService", "Security exception in starting foreground service", e)
} catch (e: Exception) {
Log.e("AlarmService", "Error in starting foreground service", e)
return START_NOT_STICKY // Return on security exception
}

AlarmPlugin.eventSink?.success(mapOf("id" to id))
Expand Down Expand Up @@ -116,13 +113,17 @@ class AlarmService : Service() {

fun stopAlarm(id: Int) {
try {
ringingAlarmIds = audioService?.getPlayingMediaPlayersIds()!!
val playingIds = audioService?.getPlayingMediaPlayersIds() ?: listOf()
ringingAlarmIds = playingIds

// Safely call methods on 'volumeService' and 'audioService'
volumeService?.restorePreviousVolume(showSystemUI)
volumeService?.abandonAudioFocus()

audioService?.stopAudio(id)
if (audioService?.isMediaPlayerEmpty()!!) {

// Check if media player is empty safely
if (audioService?.isMediaPlayerEmpty() == true) {
vibrationService?.stopVibrating()
stopSelf()
}
Expand Down
6 changes: 4 additions & 2 deletions example/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ android {
applicationId "com.gdelataillade.alarm.alarm_example"
// 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 19
minSdkVersion flutter.minSdkVersion
targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
Expand All @@ -67,4 +67,6 @@ flutter {
source '../..'
}

dependencies {}
dependencies {
implementation 'androidx.multidex:multidex:2.0.1'
}
2 changes: 1 addition & 1 deletion example/lib/screens/edit_alarm.dart
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ class _ExampleAlarmEditScreenState extends State<ExampleAlarmEditScreen> {

AlarmSettings buildAlarmSettings() {
final id = creating
? DateTime.now().millisecondsSinceEpoch % 10000
? DateTime.now().millisecondsSinceEpoch % 10000 + 1
: widget.alarmSettings!.id;

final alarmSettings = AlarmSettings(
Expand Down
72 changes: 36 additions & 36 deletions example/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,10 @@ packages:
dependency: "direct main"
description:
name: cupertino_icons
sha256: d57953e10f9f8327ce64a508a355f0b1ec902193f66288e8cb5070e7c47eeb2d
sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6
url: "https://pub.dev"
source: hosted
version: "1.0.6"
version: "1.0.8"
fake_async:
dependency: transitive
description:
Expand Down Expand Up @@ -107,26 +107,26 @@ packages:
dependency: transitive
description:
name: leak_tracker
sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa"
sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a"
url: "https://pub.dev"
source: hosted
version: "10.0.0"
version: "10.0.4"
leak_tracker_flutter_testing:
dependency: transitive
description:
name: leak_tracker_flutter_testing
sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0
sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8"
url: "https://pub.dev"
source: hosted
version: "2.0.1"
version: "3.0.3"
leak_tracker_testing:
dependency: transitive
description:
name: leak_tracker_testing
sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47
sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
url: "https://pub.dev"
source: hosted
version: "2.0.1"
version: "3.0.1"
matcher:
dependency: transitive
description:
Expand All @@ -147,10 +147,10 @@ packages:
dependency: transitive
description:
name: meta
sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04
sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
url: "https://pub.dev"
source: hosted
version: "1.11.0"
version: "1.12.0"
path:
dependency: transitive
description:
Expand Down Expand Up @@ -187,26 +187,26 @@ packages:
dependency: "direct main"
description:
name: permission_handler
sha256: "74e962b7fad7ff75959161bb2c0ad8fe7f2568ee82621c9c2660b751146bfe44"
sha256: "18bf33f7fefbd812f37e72091a15575e72d5318854877e0e4035a24ac1113ecb"
url: "https://pub.dev"
source: hosted
version: "11.3.0"
version: "11.3.1"
permission_handler_android:
dependency: transitive
description:
name: permission_handler_android
sha256: "1acac6bae58144b442f11e66621c062aead9c99841093c38f5bcdcc24c1c3474"
sha256: "8bb852cd759488893805c3161d0b2b5db55db52f773dbb014420b304055ba2c5"
url: "https://pub.dev"
source: hosted
version: "12.0.5"
version: "12.0.6"
permission_handler_apple:
dependency: transitive
description:
name: permission_handler_apple
sha256: bdafc6db74253abb63907f4e357302e6bb786ab41465e8635f362ee71fd8707b
sha256: e9ad66020b89ff1b63908f247c2c6f931c6e62699b756ef8b3c4569350cd8662
url: "https://pub.dev"
source: hosted
version: "9.4.0"
version: "9.4.4"
permission_handler_html:
dependency: transitive
description:
Expand All @@ -219,10 +219,10 @@ packages:
dependency: transitive
description:
name: permission_handler_platform_interface
sha256: "23dfba8447c076ab5be3dee9ceb66aad345c4a648f0cac292c77b1eb0e800b78"
sha256: "48d4fcf201a1dad93ee869ab0d4101d084f49136ec82a8a06ed9cfeacab9fd20"
url: "https://pub.dev"
source: hosted
version: "4.2.0"
version: "4.2.1"
permission_handler_windows:
dependency: transitive
description:
Expand Down Expand Up @@ -251,26 +251,26 @@ packages:
dependency: transitive
description:
name: shared_preferences
sha256: "81429e4481e1ccfb51ede496e916348668fd0921627779233bd24cc3ff6abd02"
sha256: d3bbe5553a986e83980916ded2f0b435ef2e1893dfaa29d5a7a790d0eca12180
url: "https://pub.dev"
source: hosted
version: "2.2.2"
version: "2.2.3"
shared_preferences_android:
dependency: transitive
description:
name: shared_preferences_android
sha256: "8568a389334b6e83415b6aae55378e158fbc2314e074983362d20c562780fb06"
sha256: "1ee8bf911094a1b592de7ab29add6f826a7331fb854273d55918693d5364a1f2"
url: "https://pub.dev"
source: hosted
version: "2.2.1"
version: "2.2.2"
shared_preferences_foundation:
dependency: transitive
description:
name: shared_preferences_foundation
sha256: "7708d83064f38060c7b39db12aefe449cb8cdc031d6062280087bc4cdb988f5c"
sha256: "0a8a893bf4fd1152f93fec03a415d11c27c74454d96e2318a7ac38dd18683ab7"
url: "https://pub.dev"
source: hosted
version: "2.3.5"
version: "2.4.0"
shared_preferences_linux:
dependency: transitive
description:
Expand All @@ -291,10 +291,10 @@ packages:
dependency: transitive
description:
name: shared_preferences_web
sha256: "7b15ffb9387ea3e237bb7a66b8a23d2147663d391cafc5c8f37b2e7b4bde5d21"
sha256: "9aee1089b36bd2aafe06582b7d7817fd317ef05fc30e6ba14bff247d0933042a"
url: "https://pub.dev"
source: hosted
version: "2.2.2"
version: "2.3.0"
shared_preferences_windows:
dependency: transitive
description:
Expand Down Expand Up @@ -352,10 +352,10 @@ packages:
dependency: transitive
description:
name: test_api
sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b"
sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f"
url: "https://pub.dev"
source: hosted
version: "0.6.1"
version: "0.7.0"
vector_math:
dependency: transitive
description:
Expand All @@ -376,26 +376,26 @@ packages:
dependency: transitive
description:
name: vm_service
sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957
sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec"
url: "https://pub.dev"
source: hosted
version: "13.0.0"
version: "14.2.1"
web:
dependency: transitive
description:
name: web
sha256: "4188706108906f002b3a293509234588823c8c979dc83304e229ff400c996b05"
sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27"
url: "https://pub.dev"
source: hosted
version: "0.4.2"
version: "0.5.1"
win32:
dependency: transitive
description:
name: win32
sha256: "464f5674532865248444b4c3daca12bd9bf2d7c47f759ce2617986e7229494a8"
sha256: "0eaf06e3446824099858367950a813472af675116bf63f008a4c2a75ae13e9cb"
url: "https://pub.dev"
source: hosted
version: "5.2.0"
version: "5.5.0"
xdg_directories:
dependency: transitive
description:
Expand All @@ -405,5 +405,5 @@ packages:
source: hosted
version: "1.0.4"
sdks:
dart: ">=3.3.0-279.1.beta <4.0.0"
flutter: ">=3.16.0"
dart: ">=3.3.0 <4.0.0"
flutter: ">=3.19.0"

0 comments on commit d222abf

Please sign in to comment.