expo-app-blocker 0.1.57 → 0.1.59
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -21,14 +21,22 @@ class AppBlockerService : Service() {
|
|
|
21
21
|
private val handler = Handler(Looper.getMainLooper())
|
|
22
22
|
private var lastForegroundPackage: String? = null
|
|
23
23
|
private lateinit var overlayManager: OverlayManager
|
|
24
|
+
@Volatile private var paused = false
|
|
25
|
+
|
|
26
|
+
private val resumeRunnable = Runnable {
|
|
27
|
+
Log.d(TAG, "Temporary unlock expired, resuming blocking")
|
|
28
|
+
paused = false
|
|
29
|
+
}
|
|
24
30
|
|
|
25
31
|
private val pollRunnable = object : Runnable {
|
|
26
32
|
override fun run() {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
33
|
+
if (!paused) {
|
|
34
|
+
val foregroundPackage = getCurrentForegroundPackage()
|
|
35
|
+
if (foregroundPackage != null && foregroundPackage != lastForegroundPackage) {
|
|
36
|
+
Log.d(TAG, "Foreground changed: $foregroundPackage")
|
|
37
|
+
lastForegroundPackage = foregroundPackage
|
|
38
|
+
handleForegroundChange(foregroundPackage)
|
|
39
|
+
}
|
|
32
40
|
}
|
|
33
41
|
handler.postDelayed(this, POLL_INTERVAL_MS)
|
|
34
42
|
}
|
|
@@ -115,7 +123,17 @@ class AppBlockerService : Service() {
|
|
|
115
123
|
}
|
|
116
124
|
|
|
117
125
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
|
118
|
-
|
|
126
|
+
val action = intent?.action
|
|
127
|
+
if (action == ACTION_TEMPORARY_UNLOCK) {
|
|
128
|
+
val minutes = intent.getIntExtra(EXTRA_DURATION_MINUTES, 0)
|
|
129
|
+
if (minutes > 0) {
|
|
130
|
+
Log.d(TAG, "Temporary unlock for $minutes minutes")
|
|
131
|
+
handler.removeCallbacks(resumeRunnable)
|
|
132
|
+
paused = true
|
|
133
|
+
overlayManager.hide()
|
|
134
|
+
handler.postDelayed(resumeRunnable, minutes * 60_000L)
|
|
135
|
+
}
|
|
136
|
+
}
|
|
119
137
|
return START_STICKY
|
|
120
138
|
}
|
|
121
139
|
|
|
@@ -181,6 +199,8 @@ class AppBlockerService : Service() {
|
|
|
181
199
|
private const val BLOCKED_NOTIFICATION_ID = 9002
|
|
182
200
|
private const val POLL_INTERVAL_MS = 500L
|
|
183
201
|
private const val LOOKBACK_WINDOW_MS = 10_000L
|
|
202
|
+
private const val ACTION_TEMPORARY_UNLOCK = "expo.modules.appblocker.TEMPORARY_UNLOCK"
|
|
203
|
+
private const val EXTRA_DURATION_MINUTES = "duration_minutes"
|
|
184
204
|
|
|
185
205
|
fun start(context: Context) {
|
|
186
206
|
val intent = Intent(context, AppBlockerService::class.java)
|
|
@@ -195,5 +215,17 @@ class AppBlockerService : Service() {
|
|
|
195
215
|
val intent = Intent(context, AppBlockerService::class.java)
|
|
196
216
|
context.stopService(intent)
|
|
197
217
|
}
|
|
218
|
+
|
|
219
|
+
fun temporaryUnlock(context: Context, durationMinutes: Int) {
|
|
220
|
+
val intent = Intent(context, AppBlockerService::class.java).apply {
|
|
221
|
+
action = ACTION_TEMPORARY_UNLOCK
|
|
222
|
+
putExtra(EXTRA_DURATION_MINUTES, durationMinutes)
|
|
223
|
+
}
|
|
224
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
225
|
+
context.startForegroundService(intent)
|
|
226
|
+
} else {
|
|
227
|
+
context.startService(intent)
|
|
228
|
+
}
|
|
229
|
+
}
|
|
198
230
|
}
|
|
199
231
|
}
|
|
@@ -113,6 +113,11 @@ class ExpoAppBlockerModule : Module() {
|
|
|
113
113
|
Log.d(TAG, "stopMonitoring called")
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
+
Function("temporaryUnlockAndroid") { durationMinutes: Int ->
|
|
117
|
+
AppBlockerService.temporaryUnlock(context, durationMinutes)
|
|
118
|
+
Log.d(TAG, "temporaryUnlockAndroid: $durationMinutes minutes")
|
|
119
|
+
}
|
|
120
|
+
|
|
116
121
|
AsyncFunction("getInstalledApps") {
|
|
117
122
|
val pm = context.packageManager
|
|
118
123
|
val intent = Intent(Intent.ACTION_MAIN).apply {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-app-blocker",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.59",
|
|
4
4
|
"description": "Expo module for cross-platform app blocking. Android: UsageStatsManager + Overlay. iOS: Screen Time API (FamilyControls + ManagedSettings + DeviceActivity).",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"types": "src/index.ts",
|
package/src/index.ts
CHANGED
|
@@ -169,8 +169,9 @@ export function isAppBlocked(bundleIdentifier: string): boolean {
|
|
|
169
169
|
// ──────────────────────────────────────────────────────────────────────────────
|
|
170
170
|
|
|
171
171
|
export async function temporaryUnlock(durationMinutes: number = 15): Promise<TemporaryUnlockResult> {
|
|
172
|
-
if (Platform.OS
|
|
173
|
-
|
|
172
|
+
if (Platform.OS === "android") {
|
|
173
|
+
NativeModule.temporaryUnlockAndroid(Math.max(1, Math.round(durationMinutes)));
|
|
174
|
+
return { unlocked: true, expiresAt: Date.now() + durationMinutes * 60_000 };
|
|
174
175
|
}
|
|
175
176
|
return NativeModule.temporaryUnlock(durationMinutes);
|
|
176
177
|
}
|