feat(android): Cockpit-App und Android-Agent per MDM ausrollen
Beide Apps lesen ihre Verbindungsdaten aus der App-Konfiguration des MDM (Android Managed Configuration). Sind host und token gesetzt, verbindet sich die App ohne QR-Code; die MDM-Werte haben Vorrang vor der Eingabe am Geraet. - Cockpit (com.ariacockpit): host, token, port, tls; natives Modul MdmConfig, gelesen beim Start in rvs.loadConfig() - Agent (de.hackersoft.ariaagent): zusaetzlich name, control, reply_mode; gelesen beim App-Start und nach dem Booten - README: Abschnitt "Ausrollen per MDM" mit Screenshots unter docs/images/mdm/ Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -37,6 +37,11 @@
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.AppCompat.DayNight">
|
||||
|
||||
<!-- MDM-Ausrollen: welche Werte ein MDM mitgeben kann -->
|
||||
<meta-data
|
||||
android:name="android.content.APP_RESTRICTIONS"
|
||||
android:resource="@xml/app_restrictions" />
|
||||
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true"
|
||||
|
||||
@@ -8,6 +8,7 @@ import android.content.Intent
|
||||
class BootReceiver : BroadcastReceiver() {
|
||||
override fun onReceive(ctx: Context, intent: Intent) {
|
||||
if (intent.action == Intent.ACTION_BOOT_COMPLETED) {
|
||||
MdmConfig.apply(ctx) // vom MDM geaenderte Werte uebernehmen
|
||||
if (AgentConfig.load(ctx).isValid()) {
|
||||
AgentService.start(ctx)
|
||||
}
|
||||
|
||||
@@ -134,7 +134,15 @@ class MainActivity : AppCompatActivity() {
|
||||
// Fern-Einrichtung (z.B. Fire TV, wo QR-Scan und Tippen wegfallen): der
|
||||
// Satellit startet die App per ADB mit den Zugangsdaten als Extras.
|
||||
// Hat das geklappt, ist die UI schon befuellt — sonst normal laden.
|
||||
if (!applyProvisioning(intent)) loadIntoUi(AgentConfig.load(this))
|
||||
if (!applyProvisioning(intent)) {
|
||||
// Per MDM ausgerollt? Dann Werte uebernehmen und gleich verbinden.
|
||||
val mdm = MdmConfig.apply(this)
|
||||
if (mdm != null) {
|
||||
AgentService.start(this)
|
||||
toast("Vom MDM eingerichtet: ${mdm.host} — Agent gestartet")
|
||||
}
|
||||
loadIntoUi(mdm ?: AgentConfig.load(this))
|
||||
}
|
||||
|
||||
// Fire TV: kein Touchscreen — der QR-Scan ist dort sinnlos (keine Kamera),
|
||||
// und der erste Fokus muss gesetzt sein, damit die Fernbedienung greift.
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
package de.hackersoft.ariaagent
|
||||
|
||||
import android.content.Context
|
||||
import android.content.RestrictionsManager
|
||||
|
||||
/**
|
||||
* Einrichtung per MDM ("Managed Configuration" / App-Restrictions).
|
||||
*
|
||||
* Das MDM schreibt Schluessel/Werte fuer de.hackersoft.ariaagent; welche es
|
||||
* gibt, steht in res/xml/app_restrictions.xml. Sind host UND token gesetzt,
|
||||
* uebernimmt der Agent sie — vom MDM gesetzte Werte haben Vorrang vor der
|
||||
* Eingabe am Geraet, nicht gesetzte Schluessel lassen den alten Wert stehen.
|
||||
*
|
||||
* Gelesen wird beim App-Start und nach dem Booten.
|
||||
*/
|
||||
object MdmConfig {
|
||||
|
||||
/** Gibt die neue Konfiguration zurueck, wenn das MDM etwas geaendert hat, sonst null. */
|
||||
fun apply(ctx: Context): AgentConfig? {
|
||||
val b = try {
|
||||
(ctx.getSystemService(Context.RESTRICTIONS_SERVICE) as RestrictionsManager)
|
||||
.applicationRestrictions
|
||||
} catch (_: Exception) { return null }
|
||||
|
||||
val host = b.getString("host")?.trim().orEmpty()
|
||||
val token = b.getString("token")?.trim().orEmpty()
|
||||
if (host.isEmpty() || token.isEmpty()) return null
|
||||
|
||||
val old = AgentConfig.load(ctx)
|
||||
val cfg = old.copy(
|
||||
host = host,
|
||||
token = token,
|
||||
port = if (b.containsKey("port")) b.getInt("port").takeIf { it > 0 } ?: 443 else old.port,
|
||||
tls = if (b.containsKey("tls")) b.getBoolean("tls") else old.tls,
|
||||
name = b.getString("name")?.trim().takeUnless { it.isNullOrEmpty() } ?: old.name,
|
||||
controlEnabled = if (b.containsKey("control")) b.getBoolean("control") else old.controlEnabled,
|
||||
replyMode = b.getString("reply_mode")?.trim()
|
||||
?.takeIf { it == "overlay" || it == "speech" } ?: old.replyMode,
|
||||
)
|
||||
if (cfg == old) return null
|
||||
cfg.save(ctx)
|
||||
return cfg
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Texte fuer die MDM-Werte (res/xml/app_restrictions.xml) -->
|
||||
<resources>
|
||||
<string name="mdm_host_title" translatable="false">RVS-Host</string>
|
||||
<string name="mdm_host_description" translatable="false">Hostname des RVS, z.B. aria-rvs.example.de</string>
|
||||
<string name="mdm_port_title" translatable="false">RVS-Port</string>
|
||||
<string name="mdm_tls_title" translatable="false">TLS verwenden</string>
|
||||
<string name="mdm_token_title" translatable="false">Token</string>
|
||||
<string name="mdm_token_description" translatable="false">Derselbe Token wie im QR-Code</string>
|
||||
<string name="mdm_name_title" translatable="false">Geraetename</string>
|
||||
<string name="mdm_name_description" translatable="false">So erscheint das Geraet in der Diagnostic (leer = Modellname)</string>
|
||||
<string name="mdm_control_title" translatable="false">Steuern erlauben</string>
|
||||
<string name="mdm_reply_mode_title" translatable="false">Antwort als</string>
|
||||
<string name="mdm_reply_mode_description" translatable="false">overlay (Einblendung) oder speech (Sprache)</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Werte, die ein MDM beim Ausrollen mitgeben kann (Managed Configuration).
|
||||
Sind host UND token gesetzt, verbindet sich der Agent damit — ohne QR-Code. -->
|
||||
<restrictions xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<restriction
|
||||
android:key="host"
|
||||
android:title="@string/mdm_host_title"
|
||||
android:description="@string/mdm_host_description"
|
||||
android:restrictionType="string" />
|
||||
<restriction
|
||||
android:key="port"
|
||||
android:title="@string/mdm_port_title"
|
||||
android:defaultValue="443"
|
||||
android:restrictionType="integer" />
|
||||
<restriction
|
||||
android:key="tls"
|
||||
android:title="@string/mdm_tls_title"
|
||||
android:defaultValue="true"
|
||||
android:restrictionType="bool" />
|
||||
<restriction
|
||||
android:key="token"
|
||||
android:title="@string/mdm_token_title"
|
||||
android:description="@string/mdm_token_description"
|
||||
android:restrictionType="string" />
|
||||
<restriction
|
||||
android:key="name"
|
||||
android:title="@string/mdm_name_title"
|
||||
android:description="@string/mdm_name_description"
|
||||
android:restrictionType="string" />
|
||||
<restriction
|
||||
android:key="control"
|
||||
android:title="@string/mdm_control_title"
|
||||
android:defaultValue="false"
|
||||
android:restrictionType="bool" />
|
||||
<restriction
|
||||
android:key="reply_mode"
|
||||
android:title="@string/mdm_reply_mode_title"
|
||||
android:description="@string/mdm_reply_mode_description"
|
||||
android:defaultValue="overlay"
|
||||
android:restrictionType="string" />
|
||||
</restrictions>
|
||||
Reference in New Issue
Block a user