Skip to content

Commit f7fec4e

Browse files
committed
feat(android): add native storage permission check and blocking UI
- Add MANAGE_EXTERNAL_STORAGE permission to AndroidManifest - Create native blocking UI in activity_main.xml (hides WebView until granted) - Implement permission check logic in MainActivity.kt - Add explanatory text about why file access is needed for web-based app
1 parent 15c1ab3 commit f7fec4e

3 files changed

Lines changed: 104 additions & 1 deletion

File tree

app/src/main/AndroidManifest.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
tools:ignore="QueryAllPackagesPermission"
66
xmlns:tools="http://schemas.android.com/tools" />
77
<uses-permission android:name="android.permission.INTERNET" />
8+
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage" />
89
<uses-permission android:name="moe.shizuku.manager.permission.API_V23" />
910

1011
<application

app/src/main/java/com/appcontrolx/ui/MainActivity.kt

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,24 @@
11
package com.appcontrolx.ui
22

33
import android.annotation.SuppressLint
4+
import android.content.Intent
45
import android.graphics.Color
6+
import android.net.Uri
7+
import android.os.Build
58
import android.os.Bundle
9+
import android.os.Environment
10+
import android.provider.Settings
611
import android.view.View
712
import android.webkit.WebChromeClient
813
import android.webkit.WebSettings
914
import android.webkit.WebView
1015
import android.webkit.WebViewClient
16+
import android.widget.Button
17+
import android.widget.LinearLayout
1118
import androidx.activity.OnBackPressedCallback
19+
import androidx.activity.result.contract.ActivityResultContracts
1220
import androidx.appcompat.app.AppCompatActivity
21+
import com.appcontrolx.R
1322
import com.appcontrolx.bridge.NativeBridge
1423
import com.appcontrolx.databinding.ActivityMainBinding
1524
import dagger.hilt.android.AndroidEntryPoint
@@ -23,15 +32,72 @@ class MainActivity : AppCompatActivity() {
2332
@Inject
2433
lateinit var nativeBridge: NativeBridge
2534

35+
private val storagePermissionLauncher = registerForActivityResult(
36+
ActivityResultContracts.StartActivityForResult()
37+
) {
38+
checkAndSetup()
39+
}
40+
2641
override fun onCreate(savedInstanceState: Bundle?) {
2742
super.onCreate(savedInstanceState)
2843
binding = ActivityMainBinding.inflate(layoutInflater)
2944
setContentView(binding.root)
3045

31-
setupWebView()
46+
setupPermissionButton()
47+
checkAndSetup()
3248
setupBackHandler()
3349
}
3450

51+
private fun setupPermissionButton() {
52+
findViewById<Button>(R.id.btn_grant_permission).setOnClickListener {
53+
requestStoragePermission()
54+
}
55+
}
56+
57+
private fun checkAndSetup() {
58+
if (hasStoragePermission()) {
59+
showWebView()
60+
setupWebView()
61+
} else {
62+
showPermissionLayout()
63+
}
64+
}
65+
66+
private fun hasStoragePermission(): Boolean {
67+
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
68+
Environment.isExternalStorageManager()
69+
} else {
70+
true // For older versions, standard permissions flow applies, assuming granted for simplicity here or handled elsewhere if needed
71+
}
72+
}
73+
74+
private fun requestStoragePermission() {
75+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
76+
try {
77+
val intent = Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION)
78+
intent.addCategory("android.intent.category.DEFAULT")
79+
intent.data = Uri.parse(String.format("package:%s", applicationContext.packageName))
80+
storagePermissionLauncher.launch(intent)
81+
} catch (e: Exception) {
82+
val intent = Intent()
83+
intent.action = Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION
84+
storagePermissionLauncher.launch(intent)
85+
}
86+
}
87+
}
88+
89+
private fun showWebView() {
90+
binding.webView.visibility = View.VISIBLE
91+
binding.progressBar.visibility = View.VISIBLE // Will be hidden by onPageFinished
92+
findViewById<LinearLayout>(R.id.permission_layout).visibility = View.GONE
93+
}
94+
95+
private fun showPermissionLayout() {
96+
binding.webView.visibility = View.GONE
97+
binding.progressBar.visibility = View.GONE
98+
findViewById<LinearLayout>(R.id.permission_layout).visibility = View.VISIBLE
99+
}
100+
35101
@SuppressLint("SetJavaScriptEnabled")
36102
private fun setupWebView() {
37103
binding.webView.apply {

app/src/main/res/layout/activity_main.xml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,40 @@
1717
android:indeterminateTint="@color/primary"
1818
android:visibility="gone" />
1919

20+
<LinearLayout
21+
android:id="@+id/permission_layout"
22+
android:layout_width="match_parent"
23+
android:layout_height="match_parent"
24+
android:orientation="vertical"
25+
android:gravity="center"
26+
android:padding="24dp"
27+
android:background="@color/background"
28+
android:visibility="gone">
29+
30+
<TextView
31+
android:layout_width="wrap_content"
32+
android:layout_height="wrap_content"
33+
android:text="Storage Permission Required"
34+
android:textSize="24sp"
35+
android:textStyle="bold"
36+
android:textColor="@color/on_background"
37+
android:layout_marginBottom="16dp" />
38+
39+
<TextView
40+
android:layout_width="wrap_content"
41+
android:layout_height="wrap_content"
42+
android:text="This app is built on web technologies and requires full file access to load local resources and function correctly.\n\nWithout this permission, the app cannot access its core files due to Android's storage restrictions."
43+
android:textSize="16sp"
44+
android:textColor="@color/on_surface_variant"
45+
android:textAlignment="center"
46+
android:layout_marginBottom="32dp" />
47+
48+
<Button
49+
android:id="@+id/btn_grant_permission"
50+
android:layout_width="wrap_content"
51+
android:layout_height="wrap_content"
52+
android:text="Grant Permission" />
53+
54+
</LinearLayout>
55+
2056
</FrameLayout>

0 commit comments

Comments
 (0)