(Мы попробовали это на Android 12 и 13 с тем же результатом)
Мы создаем QR-код, используя полезную нагрузку JSON следующего формата:
{
"android.app.extra.PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME": "com.google.android.apps.work.clouddpc/.receivers.CloudDeviceAdminReceiver",
"android.app.extra.PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM": "MY_BASE64_CHECKSUM",
"android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION": "https://play.google.com/managed/downloa ... fier=setup",
"android.app.extra.PROVISIONING_SKIP_EDUCATION_SCREENS" :"true",
"android.app.extra.PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED" :"true",
"android.app.extra.PROVISIONING_ADMIN_EXTRAS_BUNDLE":{
"com.google.android.apps.work.clouddpc.EXTRA_ENROLLMENT_TOKEN": "MY_ENROLLMENT_TOKEN"
}
}
Наш метод генерации 20-значного токена регистрации («AnotherClass.GetEnrollment()») — здесь не подробно описан, поскольку он не имеет значения), является правильным (он работает с afw#setup) .
Мы генерируем контрольную сумму путем:
- получения массива байтов из файла по адресу "https://play.google.com/managed/downloa ... fier=setup"
- кодирование контрольной суммы файла в формате Base64.
«Невозможно настроить устройство», и нам необходимо перезагрузить устройство.< /p>
Наши вопросы:
- Правильен ли этот код?
Правильны ли параметры в полезных данных? В некоторых местах говорится, что используйте «android.app.extra.PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM», в других — «PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM»? - есть ли какие-либо другие параметры, которые мы нужно?
- Другие источники говорят, что нам нужно использовать Инструмент командной строки «keytool» для генерации контрольной суммы. Неужели нам нужно генерировать это на лету на C#, поскольку версия DPC может быть изменена в любое время?
- Если методу 'afw#setup' не нужны эти данные для установки собственного DPC, тогда зачем нам вообще нужно местоположение/контрольная сумма (пробовали опустить их, но это тоже не сработало? ).
PS Когда мы пытаемся добавить сведения о WiFi PROVISIONING_WIFI_SSID /. PROVISIONING_WIFI_PASSWORD / PROVISIONING_WIFI_SECURITY_TYPE = «WPA» устройство просто говорит: «Невозможно подключиться к Wi-Fi»
(SSID/пароль определенно верны и есть с Wi-Fi все в порядке)
However that is another issue - for now, we are more concerned with getting the native DPC installed....
(Результат будет одинаковым независимо от того, включены ли PROVISIONING_SKIP_EDUCATION_SCREENS / android.app.extra.PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED.)
Вот полный список наш код (с закомментированными элементами Wi-Fi). QR-код получается с помощью метода GetQrBitMap.
using Newtonsoft.Json;
using QRCoder; // the Nuget package that actually creates the QR code
using System;
using System.Collections.Specialized;
using System.Configuration;
using System.Drawing;
using System.Net.Http;
using System.Security.Cryptography;
using System.Threading.Tasks;
public class ProvisioningData
{
[JsonProperty("android.app.extra.PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME")]
public string DeviceAdminComponentName { get; set; }
[JsonProperty("android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION")]
public string DeviceAdminPackageDownloadLocation { get; set; }
[JsonProperty("android.app.extra.PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM")]
public string DeviceAdminSignatureChecksum { get; set; }
[JsonProperty("android.app.extra.PROVISIONING_ADMIN_EXTRAS_BUNDLE")]
public AdminExtrasBundle AdminExtrasBundle { get; set; }
[JsonProperty("android.app.extra.PROVISIONING_SKIP_EDUCATION_SCREENS")]
public string SkipEducationScreens { get; set; }
[JsonProperty("android.app.extra.PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED")]
public string LeaveAllSystemAppsEnabled { get; set; }
//[JsonProperty("android.app.extra.PROVISIONING_WIFI_SSID")]
//public string WifiSsid { get; set; }
//[JsonProperty("android.app.extra.PROVISIONING_WIFI_PASSWORD")]
//public string WifiPassword { get; set; }
//[JsonProperty("android.app.extra.PROVISIONING_WIFI_SECURITY_TYPE")]
//public string SecurityType { get; set; }
}
public class AdminExtrasBundle
{
[JsonProperty("com.google.android.apps.work.clouddpc.EXTRA_ENROLLMENT_TOKEN")]
public string EnrollmentToken { get; set; }
}
public class QRHelper
{
private static byte[] DownloadFileBytes(string url)
{
using (HttpClient client = new HttpClient())
{
var response = client.GetAsync(url).Result;
if (!response.IsSuccessStatusCode)
{
throw new Exception($"Failed to download file. Status code: {response.StatusCode}");
}
return response.Content.ReadAsByteArrayAsync().Result;
}
}
private static string CalcChecksum(byte[] fileBytes)
{
using (SHA256 sha256 = SHA256.Create())
{
byte[] hash = sha256.ComputeHash(fileBytes);
// Replaces & Trim() needed because apparently Android Management API I expects the checksum to be in a specific Base64 URL-safe format.
return Convert.ToBase64String(hash).Replace('+', '-').Replace('/', '_').TrimEnd('=');
}
}
private static System.Drawing.Bitmap GenQrImage(string code)
{
QRCodeGenerator qrGenerator = new QRCodeGenerator();
QRCodeData qrCodeData = qrGenerator.CreateQrCode(code, QRCodeGenerator.ECCLevel.Q);
QRCode qrCode = new QRCode(qrCodeData);
return qrCode.GetGraphic(20);
}
private static byte[] ImageToByte(Image img)
{
ImageConverter converter = new ImageConverter();
return (byte[])converter.ConvertTo(img, typeof(byte[]));
}
private static string GetImageAsBase64String(byte[] bin)
{
if (bin != null)
{
return Convert.ToBase64String(bin);
}
else
{
return null;
}
}
public static async Task GetQrBitMap()
{
string code = await AnotherClass.GetEnrollment();
string fileUrl = "https://play.google.com/managed/downloa ... fier=setup";
byte[] fileBytes = DownloadFileBytes(fileUrl);
string checksum = CalcChecksum(fileBytes);
string ssid = "MY_SSID";
string pwd = "MY_PASSWORD";
string securityType = "WPA";
// Create provisioning data using a DTO
var provisioningData = new ProvisioningData
{
DeviceAdminComponentName = "com.google.android.apps.work.clouddpc/.receivers.CloudDpcAdminReceiver",
DeviceAdminSignatureChecksum = checksum,
DeviceAdminPackageDownloadLocation = fileUrl,
SkipEducationScreens = "true",
LeaveAllSystemAppsEnabled = "true",
//WifiSsid = ssid,
//WifiPassword = pwd,
//SecurityType = securityType,
AdminExtrasBundle = new AdminExtrasBundle
{
EnrollmentToken = code
}
};
// Serialize DTO to JSON using Newtonsoft.Json
string jsonData = JsonConvert.SerializeObject(provisioningData, Formatting.None, new JsonSerializerSettings
{
ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver()
});
System.Drawing.Bitmap bmp = GenQrImage(jsonData);
byte[] bytes = ImageToByte(bmp);
string ret = GetImageAsBase64String(bytes);
// see https://stackoverflow.com/questions/301 ... y/30130095 ...
return Tuple.Create("data:image/bmp;base64," + ret, code);
}
}
Подробнее здесь: https://stackoverflow.com/questions/792 ... vice-error
Мобильная версия