Skip to content

Commit e31e4ea

Browse files
committed
Only start when the shutter button is clicked and show notification timer
1 parent 9e0f9dd commit e31e4ea

File tree

2 files changed

+61
-40
lines changed

2 files changed

+61
-40
lines changed

app/src/main/java/com/kylecorry/intervalometer/infrastructure/services/IntervalometerService.kt

+59-39
Original file line numberDiff line numberDiff line change
@@ -8,40 +8,67 @@ import android.content.Context
88
import android.content.Intent
99
import android.content.IntentFilter
1010
import android.os.Build
11-
import android.provider.Settings
1211
import android.view.accessibility.AccessibilityEvent
1312
import android.view.accessibility.AccessibilityNodeInfo
1413
import com.kylecorry.andromeda.notify.Notify
1514
import com.kylecorry.andromeda.preferences.SharedPreferences
1615
import com.kylecorry.intervalometer.R
16+
import com.kylecorry.intervalometer.ui.MainActivity
1717
import com.kylecorry.luna.timer.CoroutineTimer
1818

1919
class IntervalometerService : AccessibilityService() {
2020

2121
private val prefs by lazy { SharedPreferences(this) }
22+
private val knownShutterButtons = listOf(
23+
"com.android.camera:id/shutter_button",
24+
"com.android.camera2:id/shutter_button",
25+
"com.google.android.GoogleCamera:id/shutter_button"
26+
)
2227

2328
private var stopReceiver = object : BroadcastReceiver() {
2429
override fun onReceive(context: Context?, intent: Intent?) {
25-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
26-
disableSelf()
27-
} else {
28-
// Open accessibility settings
29-
startActivity(Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS))
30-
}
31-
30+
timer.stop()
31+
Notify.cancel(this@IntervalometerService, 2)
3232
}
3333
}
34+
35+
private var secondsUntilNextPhoto = 0L
3436

3537
private val timer = CoroutineTimer {
36-
clickShutterButton()
38+
// Trigger a notification with the remaining time
39+
secondsUntilNextPhoto--
40+
Notify.cancel(this, 2)
41+
Notify.send(
42+
this,
43+
2,
44+
Notify.alert(
45+
this,
46+
"intervalometer",
47+
secondsUntilNextPhoto.toString(),
48+
null,
49+
R.drawable.bubble,
50+
group = "alerts"
51+
)
52+
)
53+
if (secondsUntilNextPhoto <= 0) {
54+
Notify.cancel(this, 2)
55+
clickShutterButton()
56+
secondsUntilNextPhoto = prefs.getLong("interval") ?: 0
57+
}
3758
}
3859

3960
override fun onAccessibilityEvent(event: AccessibilityEvent?) {
40-
println(event?.packageName)
61+
// Start the timer when a shutter button is clicked
62+
if (!timer.isRunning() && knownShutterButtons.contains(
63+
event?.source?.viewIdResourceName ?: ""
64+
)
65+
) {
66+
restartTimer()
67+
}
4168
}
4269

4370
override fun onInterrupt() {
44-
println("Interrupted")
71+
// Do nothing
4572
}
4673

4774
@SuppressLint("UnspecifiedRegisterReceiverFlag")
@@ -58,61 +85,51 @@ class IntervalometerService : AccessibilityService() {
5885
registerReceiver(stopReceiver, IntentFilter("com.kylecorry.intervalometer.STOP"))
5986
}
6087

61-
val stopIntent = Intent("com.kylecorry.intervalometer.STOP")
62-
val stopPendingIntent = PendingIntent.getBroadcast(
63-
this,
64-
0,
65-
stopIntent,
66-
PendingIntent.FLAG_IMMUTABLE
67-
)
68-
6988
Notify.send(
7089
this,
7190
1,
7291
Notify.persistent(
7392
this, "intervalometer", "Intervalometer", null, R.drawable.bubble,
7493
actions = listOf(
75-
Notify.action("Stop", stopPendingIntent, R.drawable.ic_info),
94+
Notify.action(
95+
"Stop", PendingIntent.getBroadcast(
96+
this,
97+
0,
98+
Intent("com.kylecorry.intervalometer.STOP"),
99+
PendingIntent.FLAG_IMMUTABLE
100+
), R.drawable.ic_info
101+
),
102+
),
103+
intent = PendingIntent.getActivity(
104+
this,
105+
0,
106+
Intent(this, MainActivity::class.java),
107+
PendingIntent.FLAG_IMMUTABLE
76108
)
77109
),
78110
)
79-
80-
restartTimer()
81-
82-
prefs.onChange.subscribe(this::onPrefsChanged)
83111
}
84112

85113
override fun onDestroy() {
86114
super.onDestroy()
87115
timer.stop()
88116
Notify.cancel(this, 1)
117+
Notify.cancel(this, 2)
89118
unregisterReceiver(stopReceiver)
90-
prefs.onChange.unsubscribe(this::onPrefsChanged)
91-
}
92-
93-
private fun onPrefsChanged(key: String): Boolean {
94-
if (key == "interval") {
95-
restartTimer()
96-
}
97-
return true
98119
}
99120

100121
private fun restartTimer() {
101122
val interval = prefs.getLong("interval") ?: 0
123+
Notify.cancel(this, 2)
102124
if (interval > 0) {
103-
timer.interval(interval * 1000)
125+
secondsUntilNextPhoto = prefs.getLong("interval") ?: 0
126+
timer.interval(1000)
104127
} else {
105128
timer.stop()
106129
}
107130
}
108131

109132
private fun clickShutterButton() {
110-
val knownShutterButtons = listOf(
111-
"com.android.camera:id/shutter_button",
112-
"com.android.camera2:id/shutter_button",
113-
"com.google.android.GoogleCamera:id/shutter_button"
114-
)
115-
116133
val nodeInfo = rootInActiveWindow
117134
for (shutterButton in knownShutterButtons) {
118135
val nodes = nodeInfo?.findAccessibilityNodeInfosByViewId(shutterButton)
@@ -123,5 +140,8 @@ class IntervalometerService : AccessibilityService() {
123140
return
124141
}
125142
}
143+
144+
// If it got this far, no shutter button was found, so stop the timer
145+
timer.stop()
126146
}
127147
}

app/src/main/res/xml/accessibility_service_config.xml

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
33
android:accessibilityFeedbackType="feedbackGeneric"
4-
android:accessibilityFlags="flagDefault"
4+
android:accessibilityEventTypes="typeViewClicked"
5+
android:accessibilityFlags="flagReportViewIds|flagDefault"
56
android:canRetrieveWindowContent="true"
67
android:description="@string/accessibility_service_description"
78
android:notificationTimeout="100"

0 commit comments

Comments
 (0)