mirror of
https://github.com/screentinker/screentinker.git
synced 2026-08-13 13:53:12 -06:00
Open our own permissions screen from the in-service Settings menu
The Permissions entry showed a ✓/✗ read-out and then handed off to Android's App Info page. The
screen we actually built for this — a row per permission with its live state and a Manage button
that stays visible once granted — was only reachable during first-run setup, so an installer who
wanted to review or revoke something on a running panel had to re-pair to see it.
Manage Permissions is now the primary action and opens SetupActivity in review mode. Android's App
Info page stays as the secondary, because notification access and some OEM toggles are only
reachable there.
Review mode exists because three things in SetupActivity assume first-run, and every one of them
had to be exempted or this silently did nothing:
- proceedToNext() goes unconditionally to ProvisioningActivity. Without the exemption the button
an installer was told to press would send a paired, playing screen to the pairing page.
- onCreate returns early when setup_complete is set — and every device that can reach this menu
has it set, so the screen closed before it drew and the menu entry looked broken.
- updateStatuses() re-labels the continue button on every refresh, silently overwriting the label
set in onCreate. The label had to move to where it actually sticks.
Review mode also hides the first-run skip hint, does not re-stamp setup_complete, and returns to
playback rather than continuing anywhere.
Verified on an Android 12 emulator, both directions:
in service BACK x2 -> PIN -> Settings -> Permissions -> MANAGE PERMISSIONS -> our screen with
every row and its state -> DONE -> back to playback, no ProvisioningActivity launch,
widget rendering resumed
first run full uninstall + fresh install -> SetupActivity, button reads CONTINUE ANYWAY, skip
hint present, no DONE label, continue lands on ProvisioningActivity, pairing completes
and playback starts
That second run is the one that mattered: both early-exit guards are inverted conditions, and a
mistake in either would have broken onboarding for every new install.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uaeo9MvzKoyXuN6ZsbhtkL
This commit is contained in:
parent
ff7bfb2ded
commit
fca36c242a
|
|
@ -1243,7 +1243,17 @@ class MainActivity : AppCompatActivity() {
|
|||
AlertDialog.Builder(this)
|
||||
.setTitle(getString(R.string.settings_permissions))
|
||||
.setMessage(lines)
|
||||
.setPositiveButton(getString(R.string.settings_perm_open)) { _, _ ->
|
||||
// Primary action opens OUR permissions screen — the one with a row per permission and
|
||||
// a Manage button that stays visible once granted, so an installer can review or revoke
|
||||
// what was given. Android's App Info page is still offered as the secondary, because a
|
||||
// few things (notification access, some OEM toggles) are only reachable there.
|
||||
.setPositiveButton(getString(R.string.settings_perm_manage)) { _, _ ->
|
||||
startActivity(Intent(this, SetupActivity::class.java).apply {
|
||||
// Review mode: leaving must return to playback, NOT restart pairing.
|
||||
putExtra(SetupActivity.EXTRA_MANAGE_ONLY, true)
|
||||
})
|
||||
}
|
||||
.setNeutralButton(getString(R.string.settings_perm_open)) { _, _ ->
|
||||
val intent = Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
|
||||
data = android.net.Uri.parse("package:$packageName")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,13 +40,29 @@ class SetupActivity : AppCompatActivity() {
|
|||
private lateinit var enableWriteSettingsBtn: Button
|
||||
private lateinit var continueBtn: Button
|
||||
|
||||
/**
|
||||
* Opened from the in-service Settings menu to REVIEW permissions, not as first-run setup.
|
||||
*
|
||||
* The difference matters: proceedToNext() always goes to ProvisioningActivity, so without this
|
||||
* a paired, playing screen would be sent to the pairing page by the button it was told to press.
|
||||
* In manage mode the screen simply returns to the player.
|
||||
*/
|
||||
private val manageOnly: Boolean get() = intent?.getBooleanExtra(EXTRA_MANAGE_ONLY, false) == true
|
||||
|
||||
companion object {
|
||||
const val EXTRA_MANAGE_ONLY = "EXTRA_MANAGE_ONLY"
|
||||
}
|
||||
|
||||
@SuppressLint("BatteryLife")
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
// Skip setup if already completed
|
||||
// Skip setup if already completed — but NOT when we were opened deliberately to review
|
||||
// permissions from the in-service Settings menu. That is the whole point of manage mode:
|
||||
// every device that can reach it has setup_complete set, so without this exemption the
|
||||
// screen closes before it draws and the menu entry appears to do nothing.
|
||||
val prefs = getSharedPreferences("remote_display", MODE_PRIVATE)
|
||||
if (prefs.getBoolean("setup_complete", false)) {
|
||||
if (!manageOnly && prefs.getBoolean("setup_complete", false)) {
|
||||
proceedToNext()
|
||||
return
|
||||
}
|
||||
|
|
@ -56,7 +72,7 @@ class SetupActivity : AppCompatActivity() {
|
|||
// moot — so skip the entire manual first-run wizard. Accessibility stays optional (it can't
|
||||
// be auto-enabled). Guarded on ownership, so a NORMAL install still gets the full wizard.
|
||||
val ownerPolicy = com.remotedisplay.player.admin.STPolicy(this)
|
||||
if (ownerPolicy.isDeviceOwner()) {
|
||||
if (!manageOnly && ownerPolicy.isDeviceOwner()) {
|
||||
ownerPolicy.applyOnboardingPolicy()
|
||||
prefs.edit().putBoolean("setup_complete", true).apply()
|
||||
// Remote control needs the accessibility service, and it's the one thing no policy can
|
||||
|
|
@ -218,8 +234,15 @@ class SetupActivity : AppCompatActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
if (manageOnly) {
|
||||
// "Continue anyway" and the skip hint are first-run language; here the only action is
|
||||
// to go back to what was already playing.
|
||||
continueBtn.text = getString(R.string.settings_perm_done)
|
||||
findViewById<TextView>(R.id.skipText).visibility = View.GONE
|
||||
}
|
||||
|
||||
continueBtn.setOnClickListener {
|
||||
prefs.edit().putBoolean("setup_complete", true).apply()
|
||||
if (!manageOnly) prefs.edit().putBoolean("setup_complete", true).apply()
|
||||
proceedToNext()
|
||||
}
|
||||
|
||||
|
|
@ -334,7 +357,14 @@ class SetupActivity : AppCompatActivity() {
|
|||
|
||||
// Update continue button text
|
||||
val allGood = accessibilityEnabled && canInstall
|
||||
continueBtn.text = if (allGood) "Continue to Setup" else "Continue Anyway"
|
||||
// updateStatuses() runs after onCreate's setup and re-labels this button every time, so the
|
||||
// manage-mode label has to be honoured HERE too — setting it once earlier was silently
|
||||
// overwritten. In review mode there is nothing to continue TO; the only action is going back.
|
||||
continueBtn.text = when {
|
||||
manageOnly -> getString(R.string.settings_perm_done)
|
||||
allGood -> "Continue to Setup"
|
||||
else -> "Continue Anyway"
|
||||
}
|
||||
}
|
||||
|
||||
/** Either location permission is enough for the SSID; coarse suffices below Android 10. */
|
||||
|
|
@ -398,6 +428,8 @@ class SetupActivity : AppCompatActivity() {
|
|||
}
|
||||
|
||||
private fun proceedToNext() {
|
||||
// Reviewing permissions on a live screen must never restart pairing — just go back.
|
||||
if (manageOnly) { finish(); return }
|
||||
startActivity(Intent(this, ProvisioningActivity::class.java))
|
||||
finish()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@
|
|||
<string name="settings_perm_notifications">Notifications</string>
|
||||
<string name="settings_perm_hint">Tap \"Open\" to manage permissions in system settings</string>
|
||||
<string name="settings_perm_open">Open settings</string>
|
||||
<string name="settings_perm_done">Done</string>
|
||||
<string name="settings_perm_manage">Manage permissions</string>
|
||||
<string name="device_blocked_status">This screen has been blocked in the dashboard</string>
|
||||
<string name="device_unpaired_status">This screen was unpaired — waiting to be re-paired</string>
|
||||
</resources>
|
||||
|
|
|
|||
Loading…
Reference in a new issue