Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
eb744ac
bugfix: fix data corruption in notification done action missing categ…
orbitronhd Apr 5, 2026
3fe22a1
bugfix: fix alarm ring screen race condition, data corruption, snooze…
orbitronhd Apr 5, 2026
7fdf89f
bugfix: store alarm ringing subscription to prevent GC and add permis…
orbitronhd Apr 5, 2026
e234624
bugfix: add missing Android permissions and alarm service declarations
orbitronhd Apr 5, 2026
140738d
bugfix: add multiDexEnabled for large dependency set compatibility
orbitronhd Apr 5, 2026
0df2b3b
feature: add Alarms and Reminders permission card to onboarding
orbitronhd Apr 5, 2026
ce50f6c
feature: fork alarm package to use STREAM_ALARM instead of STREAM_MUSIC
orbitronhd Apr 5, 2026
0ca3917
feature: add native Android alarm subsystem with AlarmManager, Foregr…
orbitronhd Apr 6, 2026
6d3971a
feature: register alarm components in AndroidManifest and configure M…
orbitronhd Apr 6, 2026
491190b
task: set minSdk to 31 to target Android 12 and above exclusively
orbitronhd Apr 6, 2026
73ef992
feature: rewrite alarm_service and alarm_ring_service to use native p…
orbitronhd Apr 6, 2026
8b2de59
task: remove forked alarm package in favour of native Android impleme…
orbitronhd Apr 6, 2026
e9411fe
task: remove alarm package dependency from pubspec and clean analysis…
orbitronhd Apr 6, 2026
b6ce6c9
task: update file_structure.md with native alarm system section
orbitronhd Apr 6, 2026
ac88f37
task: add secrets and keystore exclusions to .gitignore for open-sour…
orbitronhd Apr 6, 2026
b3ef2fc
task: no-op touch on about_page.dart (cursor navigation artifact)
orbitronhd Apr 6, 2026
1f94ed0
task: run dart format
orbitronhd Apr 6, 2026
737412e
task: fix for dart analyze
orbitronhd Apr 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions app/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,11 @@ app.*.map.json
/android/app/debug
/android/app/profile
/android/app/release

# Secrets and keys
*.jks
*.keystore
key.properties
google-services.json
.env
.env.*
5 changes: 5 additions & 0 deletions app/analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
# packages, and plugins designed to encourage good coding practices.
include: package:flutter_lints/flutter.yaml

analyzer:
exclude:
- "**/*.g.dart"
- "lib/generated_plugin_registrant.dart"

linter:
# The lint rules applied to this project can be customized in the
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
Expand Down
5 changes: 3 additions & 2 deletions app/android/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,11 @@ android {
applicationId = "org.orbitronhd.dose"
// You can update the following values to match your application needs.
// For more information, see: https://flutter.dev/to/review-gradle-config.
minSdk = flutter.minSdkVersion
minSdk = 31
targetSdk = flutter.targetSdkVersion
versionCode = flutter.versionCode
versionName = flutter.versionName
multiDexEnabled = true
}

buildTypes {
Expand All @@ -46,4 +47,4 @@ flutter {

dependencies {
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.5")
}
}
37 changes: 31 additions & 6 deletions app/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,27 +1,52 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<uses-permission android:name="android.permission.USE_EXACT_ALARM" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK"/>
<uses-permission android:name="android.permission.USE_EXACT_ALARM"/>
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />

<application
android:label="Dose"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">


<service
android:name=".alarm.AlarmForegroundService"
android:exported="false"
android:foregroundServiceType="mediaPlayback" />

<receiver
android:name=".alarm.AlarmReceiver"
android:exported="false" />

<receiver
android:name=".alarm.BootReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
</intent-filter>
</receiver>
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:taskAffinity=""
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:showWhenLocked="true"
android:turnScreenOn="true"
android:windowSoftInputMode="adjustResize">
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,24 @@
package org.orbitronhd.dose

import android.content.Intent
import android.os.Build
import android.os.Bundle
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import org.orbitronhd.dose.alarm.DoseAlarmPlugin
import org.orbitronhd.dose.alarm.AlarmForegroundService

class MainActivity : FlutterActivity()
class MainActivity : FlutterActivity() {
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
DoseAlarmPlugin.register(flutterEngine, this)
}

override fun onCreate(savedInstanceState: Bundle?) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
setShowWhenLocked(true)
setTurnScreenOn(true)
}
super.onCreate(savedInstanceState)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package org.orbitronhd.dose.alarm

import org.json.JSONObject

data class AlarmData(
val id: Int,
val triggerAtMs: Long,
val title: String,
val body: String,
val loopAudio: Boolean,
val vibrate: Boolean
) {
fun toJson(): JSONObject {
val json = JSONObject()
json.put("id", id)
json.put("triggerAtMs", triggerAtMs)
json.put("title", title)
json.put("body", body)
json.put("loopAudio", loopAudio)
json.put("vibrate", vibrate)
return json
}

companion object {
fun fromJson(jsonStr: String): AlarmData {
val json = JSONObject(jsonStr)
return AlarmData(
id = json.getInt("id"),
triggerAtMs = json.getLong("triggerAtMs"),
title = json.getString("title"),
body = json.getString("body"),
loopAudio = json.getBoolean("loopAudio"),
vibrate = json.getBoolean("vibrate")
)
}

fun fromJson(json: JSONObject): AlarmData {
return AlarmData(
id = json.getInt("id"),
triggerAtMs = json.getLong("triggerAtMs"),
title = json.getString("title"),
body = json.getString("body"),
loopAudio = json.getBoolean("loopAudio"),
vibrate = json.getBoolean("vibrate")
)
}
}
}
Loading
Loading