Skip to content

Commit 2144288

Browse files
Pause build and wait for directory access (with timeout)
1 parent c2839a3 commit 2144288

File tree

4 files changed

+80
-9
lines changed

4 files changed

+80
-9
lines changed

app/src/main/java/org/godotengine/godot_gradle_build_environment/BuildEnvironment.kt

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ class BuildEnvironment(
4545

4646
private var currentProcess: Process? = null
4747

48+
private val accessLock = Object()
49+
@Volatile private var grantedTreeUri: Uri? = null
50+
4851
private fun getDefaultEnv(): List<String> {
4952
return try {
5053
File(rootfs, "env").readLines()
@@ -349,11 +352,17 @@ class BuildEnvironment(
349352
} else {
350353
outputHandler(OUTPUT_STDERR, "Unable to setup project: $projectPath is not accessible. Please give GABE app access to this directory.")
351354
showDirectoryAccessNotification(projectPath)
352-
return 255
355+
val uri = waitForDirectoryAccess(2 * 60 * 1000) // 2 minutes should be ideal?
356+
if (uri == null) {
357+
outputHandler(OUTPUT_STDERR, "Directory access not granted in time. Build canceled.")
358+
return 255
359+
}
360+
projectTreeUri = uri
361+
outputHandler(OUTPUT_STDOUT, "Access granted for $projectPath. Starting Gradle build...")
353362
}
354363

355364
try {
356-
outputHandler(OUTPUT_INFO, "> Importing project via SAF...")
365+
outputHandler(OUTPUT_INFO, "> Importing project files...")
357366
SafProjectImporter.importAndroidProject(context, projectTreeUri, workDir)
358367
} catch (e: Exception) {
359368
outputHandler(OUTPUT_STDERR, "Unable to setup project: ${e.message}")
@@ -436,6 +445,28 @@ class BuildEnvironment(
436445
}
437446
}
438447

448+
fun waitForDirectoryAccess(timeoutMs: Long): Uri? {
449+
val endTime = System.currentTimeMillis() + timeoutMs
450+
451+
synchronized(accessLock) {
452+
while (grantedTreeUri == null) {
453+
val remaining = endTime - System.currentTimeMillis()
454+
if (remaining <= 0) {
455+
return null
456+
}
457+
accessLock.wait(remaining)
458+
}
459+
return grantedTreeUri
460+
}
461+
}
462+
463+
fun onDirectoryAccessGranted(uri: Uri) {
464+
synchronized(accessLock) {
465+
grantedTreeUri = uri
466+
accessLock.notifyAll()
467+
}
468+
}
469+
439470
private fun showDirectoryAccessNotification(projectPath: String) {
440471
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
441472
return

app/src/main/java/org/godotengine/godot_gradle_build_environment/BuildEnvironmentService.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import android.os.Message
1111
import android.os.Messenger
1212
import android.os.RemoteException
1313
import android.util.Log
14+
import androidx.core.net.toUri
1415
import java.util.concurrent.LinkedBlockingQueue
1516

1617
class BuildEnvironmentService : Service() {
@@ -26,6 +27,8 @@ class BuildEnvironmentService : Service() {
2627
const val MSG_CLEAN_GLOBAL_CACHE = 6
2728
const val MSG_INSTALL_ROOTFS = 7
2829
const val MSG_DELETE_ROOTFS = 8
30+
31+
const val MSG_RESUME_PENDING_BUILD = 9
2932
}
3033

3134
private lateinit var mMessenger: Messenger
@@ -62,6 +65,12 @@ class BuildEnvironmentService : Service() {
6265
MSG_CLEAN_GLOBAL_CACHE -> queueWork(WorkItem(copy, msg.arg1))
6366
MSG_INSTALL_ROOTFS -> queueWork(WorkItem(copy, msg.arg1))
6467
MSG_DELETE_ROOTFS -> queueWork(WorkItem(copy, msg.arg1))
68+
MSG_RESUME_PENDING_BUILD -> {
69+
val uri = msg.data.getString("tree_uri")?.toUri()
70+
if (uri != null) {
71+
mBuildEnvironment.onDirectoryAccessGranted(uri)
72+
}
73+
}
6574
}
6675
}
6776
}

app/src/main/java/org/godotengine/godot_gradle_build_environment/MainActivity.kt

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,18 @@ package org.godotengine.godot_gradle_build_environment
33
import android.Manifest
44
import android.app.NotificationChannel
55
import android.app.NotificationManager
6+
import android.content.ComponentName
7+
import android.content.Context
68
import android.content.Intent
9+
import android.content.ServiceConnection
710
import android.content.pm.PackageManager
811
import android.net.Uri
912
import android.os.Build
1013
import android.os.Bundle
1114
import android.os.Environment
12-
import android.provider.DocumentsContract
13-
import android.provider.Settings
15+
import android.os.IBinder
16+
import android.os.Message
17+
import android.os.Messenger
1418
import android.util.Log
1519
import android.widget.Toast
1620
import androidx.activity.ComponentActivity
@@ -43,7 +47,15 @@ class MainActivity : ComponentActivity() {
4347
} else {
4448
Log.e(TAG, "Failed to add project: tempProjectPath is null. This should never happen under normal conditions. Please report this issue.")
4549
}
50+
51+
val msg = Message.obtain(null, BuildEnvironmentService.MSG_RESUME_PENDING_BUILD)
52+
msg.data = Bundle().apply {
53+
putString("tree_uri", uri.toString())
54+
}
55+
serviceMessenger?.send(msg)
4656
}
57+
58+
finish()
4759
}
4860

4961
private val notificationPermissionLauncher =
@@ -55,6 +67,17 @@ class MainActivity : ComponentActivity() {
5567
}
5668
}
5769

70+
private var serviceMessenger: Messenger? = null
71+
72+
private val connection = object : ServiceConnection {
73+
override fun onServiceConnected(name: ComponentName?, binder: IBinder?) {
74+
serviceMessenger = Messenger(binder)
75+
}
76+
override fun onServiceDisconnected(name: ComponentName?) {
77+
serviceMessenger = null
78+
}
79+
}
80+
5881
override fun onCreate(savedInstanceState: Bundle?) {
5982
super.onCreate(savedInstanceState)
6083
enableEdgeToEdge()
@@ -94,6 +117,19 @@ class MainActivity : ComponentActivity() {
94117
}
95118
}
96119

120+
override fun onStart() {
121+
super.onStart()
122+
val intent = Intent("org.godotengine.action.BUILD_PROVIDER").apply {
123+
setPackage(packageName)
124+
}
125+
bindService(intent, connection, Context.BIND_AUTO_CREATE)
126+
}
127+
128+
override fun onStop() {
129+
super.onStop()
130+
unbindService(connection)
131+
}
132+
97133
override fun onNewIntent(intent: Intent) {
98134
super.onNewIntent(intent)
99135
handleIntent(intent)

app/src/main/java/org/godotengine/godot_gradle_build_environment/screens/ProjectsScreen.kt

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,13 @@ import android.content.ComponentName
44
import android.content.Context
55
import android.content.Intent
66
import android.content.ServiceConnection
7-
import android.net.Uri
87
import android.os.Bundle
98
import android.os.Handler
109
import android.os.IBinder
1110
import android.os.Looper
1211
import android.os.Message
1312
import android.os.Messenger
1413
import android.util.Log
15-
import androidx.activity.compose.rememberLauncherForActivityResult
16-
import androidx.activity.result.contract.ActivityResultContracts
1714
import androidx.compose.foundation.layout.Arrangement
1815
import androidx.compose.foundation.layout.Column
1916
import androidx.compose.foundation.layout.Row
@@ -25,7 +22,6 @@ import androidx.compose.foundation.layout.size
2522
import androidx.compose.foundation.layout.width
2623
import androidx.compose.foundation.lazy.LazyColumn
2724
import androidx.compose.foundation.lazy.items
28-
import androidx.compose.material3.Button
2925
import androidx.compose.material3.Card
3026
import androidx.compose.material3.CardDefaults
3127
import androidx.compose.material3.CircularProgressIndicator
@@ -57,7 +53,6 @@ import org.godotengine.godot_gradle_build_environment.CachedProject
5753
import org.godotengine.godot_gradle_build_environment.FileUtils
5854
import org.godotengine.godot_gradle_build_environment.ProjectInfo
5955
import org.godotengine.godot_gradle_build_environment.R
60-
import androidx.core.content.edit
6156

6257
@Composable
6358
fun ProjectsScreen(modifier: Modifier = Modifier) {

0 commit comments

Comments
 (0)