Skip to content

Commit 345706f

Browse files
committed
feat: Added accessibility permission
1 parent cd68fdc commit 345706f

9 files changed

Lines changed: 138 additions & 32 deletions

File tree

app/src/androidMain/AndroidManifest.xml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,17 @@
3535
</activity>
3636
<service android:name=".MainService"
3737
android:foregroundServiceType="specialUse"/>
38+
<service
39+
android:name=".MainAccessibilityService"
40+
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
41+
android:exported="false">
42+
<intent-filter>
43+
<action android:name="android.accessibilityservice.AccessibilityService"/>
44+
</intent-filter>
45+
<meta-data
46+
android:name="android.accessibilityservice"
47+
android:resource="@xml/accessibility_service"/>
48+
</service>
3849
<receiver android:name=".receiver.BootCompleteBroadcastReceiver" android:exported="true">
3950
<intent-filter>
4051
<action android:name="android.intent.action.BOOT_COMPLETED"/>
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package net.lsafer.edgeseek.app
2+
3+
import android.accessibilityservice.AccessibilityService
4+
import android.view.accessibility.AccessibilityEvent
5+
import kotlinx.coroutines.flow.MutableStateFlow
6+
7+
class MainAccessibilityService : AccessibilityService() {
8+
companion object {
9+
val aliveState = MutableStateFlow(false)
10+
}
11+
12+
override fun onServiceConnected() {
13+
super.onServiceConnected()
14+
aliveState.value = true
15+
}
16+
17+
override fun onDestroy() {
18+
super.onDestroy()
19+
aliveState.value = false
20+
}
21+
22+
override fun onAccessibilityEvent(event: AccessibilityEvent?) {
23+
// See https://github.com/LSafer/edgeseek/tree/ebeb6df678a4a1ff02e9ea24dccef12d2e6d4086
24+
}
25+
26+
override fun onInterrupt() {
27+
}
28+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package net.lsafer.edgeseek.app.components.page.permissions
2+
3+
import androidx.compose.foundation.layout.Column
4+
import androidx.compose.foundation.layout.Spacer
5+
import androidx.compose.foundation.layout.height
6+
import androidx.compose.foundation.rememberScrollState
7+
import androidx.compose.foundation.verticalScroll
8+
import androidx.compose.runtime.Composable
9+
import androidx.compose.ui.Modifier
10+
import androidx.compose.ui.unit.dp
11+
import net.lsafer.edgeseek.app.Local
12+
import net.lsafer.edgeseek.app.components.lib.ListDivider
13+
import net.lsafer.edgeseek.app.components.lib.ListHeader
14+
import net.lsafer.edgeseek.app.components.lib.ListSectionTitle
15+
import net.lsafer.edgeseek.app.l10n.strings
16+
17+
@Composable
18+
actual fun PermissionsPageContent(
19+
local: Local,
20+
modifier: Modifier,
21+
) {
22+
Column(
23+
Modifier
24+
.verticalScroll(rememberScrollState())
25+
.then(modifier)
26+
) {
27+
ListHeader(title = strings.stmt.page_permissions_heading)
28+
ListSectionTitle(title = strings.label.mandatory)
29+
30+
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.TIRAMISU) {
31+
PermissionsPage_ListItem_allow_restricted_permissions()
32+
}
33+
34+
PermissionsPage_ListItem_display_over_other_apps()
35+
PermissionsPage_ListItem_write_system_settings()
36+
37+
ListDivider()
38+
ListSectionTitle(title = strings.label.additional)
39+
PermissionsPage_ListItem_ignore_battery_optimizations()
40+
PermissionsPage_ListItem_accessibility_service()
41+
42+
Spacer(Modifier.height(50.dp))
43+
}
44+
}

app/src/commonMain/kotlin/components/page/permissions/items.kt renamed to app/src/androidMain/kotlin/components/page/permissions/items.kt

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,14 @@ import androidx.compose.material.icons.Icons
1212
import androidx.compose.material.icons.filled.Settings
1313
import androidx.compose.material3.*
1414
import androidx.compose.runtime.Composable
15+
import androidx.compose.runtime.collectAsState
16+
import androidx.compose.runtime.getValue
1517
import androidx.compose.runtime.remember
1618
import androidx.compose.ui.Modifier
1719
import androidx.compose.ui.platform.LocalContext
1820
import androidx.compose.ui.unit.dp
1921
import androidx.lifecycle.compose.LocalLifecycleOwner
22+
import net.lsafer.edgeseek.app.MainAccessibilityService
2023
import net.lsafer.edgeseek.app.components.lib.SwitchPreferenceListItem
2124
import net.lsafer.edgeseek.app.l10n.strings
2225
import net.lsafer.edgeseek.app.util.observeAsState
@@ -138,3 +141,25 @@ fun PermissionsPage_ListItem_ignore_battery_optimizations(modifier: Modifier = M
138141
modifier = modifier,
139142
)
140143
}
144+
145+
@Composable
146+
fun PermissionsPage_ListItem_accessibility_service(modifier: Modifier = Modifier) {
147+
val context = LocalContext.current
148+
149+
val isChecked by MainAccessibilityService.aliveState.collectAsState(false)
150+
151+
val handleOnChange = { _: Boolean ->
152+
val intent = Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS)
153+
// intent.data = Uri.parse("package:${context.packageName}")
154+
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
155+
context.startActivity(intent)
156+
}
157+
158+
SwitchPreferenceListItem(
159+
value = isChecked,
160+
onChange = handleOnChange,
161+
headline = strings.stmt.accessibility_service_headline,
162+
supporting = strings.stmt.accessibility_service_supporting,
163+
modifier = modifier,
164+
)
165+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
11
<resources>
22
<string name="app_name">Edge Seek</string>
3+
4+
<string name="accessibility_service_description">
5+
The application uses the accessibility service for black-listing applications.
6+
7+
Additionally, some Oppo/OnePlus devices require this permission for Controlling audio in the background.
8+
</string>
39
</resources>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!-- These options MUST be specified here in order for the events to be received on first start in Android 4.1.1 -->
3+
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
4+
android:accessibilityEventTypes="typeWindowStateChanged"
5+
android:accessibilityFeedbackType="feedbackGeneric"
6+
android:accessibilityFlags="flagIncludeNotImportantViews"
7+
android:description="@string/accessibility_service_description"/>
Lines changed: 6 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,14 @@
11
package net.lsafer.edgeseek.app.components.page.permissions
22

3-
import androidx.compose.foundation.layout.*
4-
import androidx.compose.foundation.rememberScrollState
5-
import androidx.compose.foundation.verticalScroll
3+
import androidx.compose.foundation.layout.navigationBarsPadding
4+
import androidx.compose.foundation.layout.padding
5+
import androidx.compose.foundation.layout.statusBarsPadding
66
import androidx.compose.material3.Scaffold
77
import androidx.compose.material3.SnackbarHost
88
import androidx.compose.runtime.Composable
99
import androidx.compose.ui.Modifier
10-
import androidx.compose.ui.unit.dp
1110
import net.lsafer.edgeseek.app.Local
1211
import net.lsafer.edgeseek.app.UniRoute
13-
import net.lsafer.edgeseek.app.components.lib.ListDivider
14-
import net.lsafer.edgeseek.app.components.lib.ListHeader
15-
import net.lsafer.edgeseek.app.components.lib.ListSectionTitle
16-
import net.lsafer.edgeseek.app.l10n.strings
1712

1813
@Composable
1914
fun PermissionsPage(
@@ -34,30 +29,9 @@ fun PermissionsPage(
3429
}
3530
}
3631

32+
@Suppress("EXPECT_AND_ACTUAL_IN_THE_SAME_MODULE")
3733
@Composable
38-
fun PermissionsPageContent(
34+
expect fun PermissionsPageContent(
3935
local: Local,
4036
modifier: Modifier = Modifier,
41-
) {
42-
Column(
43-
Modifier
44-
.verticalScroll(rememberScrollState())
45-
.then(modifier)
46-
) {
47-
ListHeader(title = strings.stmt.page_permissions_heading)
48-
ListSectionTitle(title = strings.label.mandatory)
49-
50-
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.TIRAMISU) {
51-
PermissionsPage_ListItem_allow_restricted_permissions()
52-
}
53-
54-
PermissionsPage_ListItem_display_over_other_apps()
55-
PermissionsPage_ListItem_write_system_settings()
56-
57-
ListDivider()
58-
ListSectionTitle(title = strings.label.additional)
59-
PermissionsPage_ListItem_ignore_battery_optimizations()
60-
61-
Spacer(Modifier.height(50.dp))
62-
}
63-
}
37+
)

app/src/commonMain/kotlin/l10n/Strings.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,12 @@ data class Strings(
9292
val ignore_battery_optimizations_supporting: String =
9393
"Make this application free from the system battery optimizations.",
9494

95+
val accessibility_service_headline: String =
96+
"Accessibility Service",
97+
val accessibility_service_supporting: String =
98+
"Allows the app to enforce a per-application whitelist/blacklist. " +
99+
"Additionally, some Oppo/OnePlus devices require this permission for Controlling audio in the background.",
100+
95101
// App
96102
val app_activation_headline: String = "Activation",
97103
val app_activation_supporting: String = "Toggle to activate or deactivate the application",

app/src/commonMain/kotlin/l10n/strings/ar.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,11 @@ val Strings_ar = Strings(
7676
ignore_battery_optimizations_headline = "تجاهل تحسينات البطارية",
7777
ignore_battery_optimizations_supporting = "اجعل هذا التطبيق خاليًا من تحسينات بطارية النظام.",
7878

79+
accessibility_service_headline = "خدمات تسهيل الوصول",
80+
accessibility_service_supporting =
81+
"التطبيق يستخدم صلاحيات تسهيل الوصول ليستطيع التوقف عن العمل في التطبيقات المحددة " +
82+
"إضافة إلى ذلك, بعض أجهزة OnePlus/Oppo تحتاج صلاحية تسهيل الوصول لتعديل مستوى الصوت في الخلفية",
83+
7984
app_activation_headline = "التفعيل",
8085
app_activation_supporting = "إختر لتفعيل أو تعطيل التطبيق",
8186

0 commit comments

Comments
 (0)