Bei der Bereitstellung über QR auf einem neuen Android-Gerät stimmt die APK-Prüfsumme des Geräteadministrators nicht übeAndroid

Forum für diejenigen, die für Android programmieren
Anonymous
 Bei der Bereitstellung über QR auf einem neuen Android-Gerät stimmt die APK-Prüfsumme des Geräteadministrators nicht übe

Post by Anonymous »

Ich versuche, mithilfe eines QR-Codes eine Android-Geräteverwaltungs-App auf einem völlig neuen Gerät bereitzustellen. Zuvor ist mir ein Fehler wegen fehlender Komponenten aufgefallen, aber jetzt schlägt die App mit einem Prüfsummenfehler fehl.
Setup:
-Ich erstelle ein Release-APK mit Gradle in GitHub Actions mit einem Release-Keystore.
-Der Workflow kopiert das APK über SCP auf einen Server.
-SHA256 des APK in GitHub Aktionen:

Code: Select all

78b718df0e56ce5c6f3673c4a2ce277dc83d001544234cf6b00648709828048c
-SHA256 des vom Server heruntergeladenen APK:

Code: Select all

78b718df0e56ce5c6f3673c4a2ce277dc83d001544234cf6b00648709828048c
Bereitstellung von JSON:

Code: Select all

{
"android.app.extra.PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME": "com.example.kios_app/.KioskDeviceAdminReceiver",
"android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION": "http://example.com/downloads/app-release.apk",
"android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM": "78b718df0e56ce5c6f3673c4a2ce277dc83d001544234cf6b00648709828048c",
"android.app.extra.PROVISIONING_ADMIN_EXTRAS_BUNDLE": {"server_url": "http://example.com/api"},
"android.app.extra.PROVISIONING_SKIP_ENCRYPTION": true,
"android.app.extra.PROVISIONING_WIFI_SSID": "MySSID",
"android.app.extra.PROVISIONING_WIFI_PASSWORD": "MyPassword",
"android.app.extra.PROVISIONING_WIFI_SECURITY_TYPE": "WPA"
}
Manifest-Snippet:

Code: Select all















































android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
android:value="deviceManagement" />
















KioskDeviceAdminReceiver-Klasse:

Code: Select all

package com.example.kios_app

import android.app.admin.DeviceAdminReceiver
import android.app.admin.DevicePolicyManager
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.UserManager
import android.provider.Settings
import android.util.Log

class KioskDeviceAdminReceiver : DeviceAdminReceiver() {

companion object {
private const val TAG = "KioskDeviceAdmin"
const val REQUEST_CODE_ENABLE_ADMIN = 1001

fun getComponentName(context: Context): ComponentName =
ComponentName(context.applicationContext, KioskDeviceAdminReceiver::class.java)
}

override fun onEnabled(context: Context, intent: Intent) {
super.onEnabled(context, intent)
Log.d(TAG, "Device Admin Enabled")

setupDevicePolicies(context)
}

override fun onReceive(context: Context, intent: Intent) {
super.onReceive(context, intent)
Log.d(TAG, "onReceive: ${intent.action}")

when (intent.action) {
ACTION_DEVICE_ADMIN_ENABLED -> {
Log.d(TAG, "Device admin enabled")
setupDevicePolicies(context)
}
ACTION_PROFILE_PROVISIONING_COMPLETE ->  {
Log.d(TAG, "Profile provisioning complete")
completeDeviceOwnerSetup(context)
}
}
}

override fun onProfileProvisioningComplete(context: Context, intent: Intent) {
super.onProfileProvisioningComplete(context, intent)
Log.d(TAG, "🎯 Profile Provisioning Complete - Device Owner mode activated")

completeDeviceOwnerSetup(context)
}

private fun setupDevicePolicies(context: Context) {
try {
val dpm = context.getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager
val admin = getComponentName(context)

dpm.setLockTaskPackages(admin, arrayOf(context.packageName))

if (dpm.isDeviceOwnerApp(context.packageName)) {
setupDeviceOwnerPolicies(dpm, admin, context)
Log.d(TAG, "🚀 Device Owner policies applied")
} else {
Log.d(TAG, "ℹ️ Regular Device Admin mode")
}

} catch (e: Exception) {
Log.e(TAG, "Error setting up device policies", e)
}
}

private fun completeDeviceOwnerSetup(context: Context) {
try {
val dpm = context.getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager

if (dpm.isDeviceOwnerApp(context.packageName)) {
Log.d(TAG, "Device Owner confirmed")

val intent = Intent(context, MainActivity::class.java).apply {
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
}
context.startActivity(intent)
} else {
Log.w(TAG, "Not Device Owner after provisioning")
}

} catch (e: Exception) {
Log.e(TAG, "Error completing device owner setup", e)
}
}

private fun setupDeviceOwnerPolicies(dpm: DevicePolicyManager, admin: ComponentName, context: Context) {
try {
dpm.setPasswordMinimumLength(admin, 0)
dpm.setPasswordQuality(admin, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED)

dpm.setSecureSetting(admin, Settings.Secure.INSTALL_NON_MARKET_APPS, "1")

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
dpm.addUserRestriction(admin, UserManager.DISALLOW_SAFE_BOOT)
dpm.addUserRestriction(admin, UserManager.DISALLOW_FACTORY_RESET)
dpm.addUserRestriction(admin, UserManager.DISALLOW_ADD_USER)
dpm.addUserRestriction(admin, UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA)
}

try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
dpm.setStatusBarDisabled(admin, true)
}
} catch (e: Exception) {
Log.w(TAG, "Cannot disable status bar: ${e.message}")
}

dpm.addUserRestriction(admin, UserManager.DISALLOW_SYSTEM_ERROR_DIALOGS)

Log.d(TAG, "Device Owner policies setup complete")

} catch (e: Exception) {
Log.e(TAG, "Error setting device owner policies", e)
}
}

override fun onDisableRequested(context: Context, intent: Intent): CharSequence {
return "Disabling device administration will take it out of kiosk mode."
}

override fun onDisabled(context: Context, intent:  Intent) {
super.onDisabled(context, intent)
Log.w(TAG, "Device Admin Disabled")
}
}
Beobachtungen / Versuche:
-APK auf dem Server ist identisch mit dem lokal erstellten (SHA256 stimmt überein).
-Download mit curl -L inklusive Zeitstempel zur Umgehung des Cachings erzeugt immer noch die gleiche Prüfsumme.
-APK ist mit dem Release-Keystore signiert.
-Gerät schlägt fehl Bereitstellung mit Prüfsummenkonflikt.
Fragen:
  • Warum beschwert sich das Gerät über einen Prüfsummenkonflikt, obwohl SHA256 übereinstimmt?
  • Könnte dies durch HTTP-Caching, Signierung oder QR-Bereitstellungsmetadaten verursacht werden?
  • Wie kann ich das Gerät sicherstellen Akzeptiert das APK für die Bereitstellung ohne Prüfsummenfehler?
Umgebung:
-Android 13/14-Gerät
-Gradle 8.13
-GitHub Actions Runner: ubuntu-latest
-Nginx, das das APK bereitstellt

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post