מדריך לשילוב EMM

המדריך הזה עוזר לספקי ניהול מכשירים ושירותי מובייל בארגון (EMM) לשלב את ההרשמה ללא מגע במסוף שלהם. בהמשך המאמר מוסבר על הרישום ומוצגות המלצות לשימוש ב-DPC (בקר מדיניות המכשיר) כדי להקצות מכשירים. אם יש לכם DPC, תוכלו ללמוד שיטות מומלצות להקצאת מכשירים ולקבל עצות שיעזרו לכם בפיתוח ובבדיקות.

תכונות לאדמינים ב-IT

אפשר להשתמש ב-API של הלקוח כדי לעזור לאדמינים של IT להגדיר הרשמה דרך הארגון ישירות מהמסוף שלכם. ריכזנו כאן כמה משימות שמנהל IT יכול לבצע במסוף:

  • ליצור, לערוך ולמחוק הגדרות של הרשמה אוטומטית על סמך מדיניות המכשירים הניידים.
  • הגדרת תצורה שמוגדרת כברירת מחדל כדי שה-DPC יקצה הרשאות למכשירים עתידיים שהארגון ירכוש.
  • החלת הגדרות פרטניות על מכשירים או הסרת מכשירים מההרשמה דרך הארגון.

מידע נוסף על הרשמה דרך הארגון זמין בסקירה הכללית.

דרישות מוקדמות

לפני שמוסיפים את ההרשמה דרך הארגון למסוף ה-EMM, צריך לוודא שהפתרון תומך בדברים הבאים:

  • פתרון ה-EMM צריך להקצות מכשיר Android בבעלות החברה בגרסה 8.0 ומעלה (Pixel בגרסה 7.1 ומעלה) במצב ניהול מלא. אפשר להקצות למכשירי Android 10 ומעלה שבבעלות החברה ניהול מלא או פרופיל עבודה.
  • ההרשמה דרך הארגון מורידה ומתקינה באופן אוטומטי DPC, ולכן ה-DPC צריך להיות זמין ב-Google Play. אנחנו מנהלים רשימה של פלטפורמות DPC תואמות שאדמינים ב-IT יכולים להגדיר באמצעות ה-API של הלקוח או הפורטל. כדי להוסיף את ה-DPC שלכם לרשימה, אתם יכולים לשלוח בקשה לשינוי מוצר דרך הקהילה של ספק ה-EMM.
  • כדי להפעיל את ה-API של הלקוח, הלקוחות שלכם צריכים חשבון להרשמה דרך הארגון. מפיץ שותף מגדיר את החשבון לארגון של אדמין IT כשהארגון רוכש את המכשירים.
  • המכשיר חייב להיות תואם ל-Google Mobile Services‏ (GMS), ושירותי Google Play צריכים להיות מופעלים בכל רגע כדי שהרשמה ללא מגע תפעל בצורה תקינה.

שליחת קריאה ל-API

המשתמשים במסוף (באמצעות חשבון Google שלהם) מאשרים את בקשות ה-API שלכם ל-Customer API. התהליך הזה שונה מההרשאה שאתם מבצעים עבור ממשקי API אחרים של EMM. במאמר הרשאה מוסבר איך עושים את זה באפליקציה.

התנאים וההגבלות של הטיפול

המשתמשים שלכם צריכים לאשר את התנאים וההגבלות (ToS) העדכניים לפני שהם קוראים ל-API. אם קריאת ה-API מחזירה קוד סטטוס HTTP 403 Forbidden וגוף התגובה מכיל את הערך TosError, צריך להציג למשתמש בקשה לאשר את התנאים וההגבלות על ידי כניסה לפורטל ההרשמה ללא מגע. בדוגמה הבאה אפשר לראות אחת מהדרכים לעשות את זה:

Java

// Authorize this method call as a user that hasn't yet accepted the ToS.
final String googleApiFormatHttpHeader = "X-GOOG-API-FORMAT-VERSION";
final String googleApiFormatVersion = "2";
final String tosErrorType =
      "type.googleapis.com/google.android.device.provisioning.v1.TosError";

try {
  // Send an API request to list all the DPCs available including the HTTP header
  // X-GOOG-API-FORMAT-VERSION with the value 2. Import the  exception:
  // from googleapiclient.errors import HttpError
  AndroidProvisioningPartner.Customers.Dpcs.List request =
        service.customers().dpcs().list(customerAccount);
  request.getRequestHeaders().put(googleApiFormatHttpHeader, googleApiFormatVersion);
  CustomerListDpcsResponse response = request.execute();
  return response.getDpcs();

} catch (GoogleJsonResponseException e) {
  // Get the error details. In your app, check details exists first.
  ArrayList<Map> details = (ArrayList<Map>) e.getDetails().get("details");
  for (Map detail : details) {
    if (detail.get("@type").equals(tosErrorType)
          && (boolean) detail.get("latestTosAccepted") != true) {
      // Ask the user to accept the ToS. If they agree, open the portal in a browser.
      // ...
    }
  }
  return null;
}

‎.NET

// Authorize this method call as a user that hasn't yet accepted the ToS.
try
{
    var request = service.Customers.Dpcs.List(customerAccount);
    CustomerListDpcsResponse response = request.Execute();
    return response.Dpcs;
}
catch (GoogleApiException e)
{
    foreach (SingleError error in e.Error?.Errors)
    {
        if (error.Message.StartsWith("The user must agree the terms of service"))
        {
            // Ask the user to accept the ToS. If they agree, open the portal in a browser.
            // ...
        }
    }
}

Python

# Authorize this method call as a user that hasn't yet accepted the ToS.
tos_error_type = ('type.googleapis.com/'
                  'google.android.device.provisioning.v1.TosError')
portal_url = 'https://enterprise.google.com/android/zero-touch/customers'

# Send an API request to list all the DPCs available including the HTTP
# header X-GOOG-API-FORMAT-VERSION with the value 2. Import the exception:
# from googleapiclient.errors import HttpError
try:
  request = service.customers().dpcs().list(parent=customer_account)
  request.headers['X-GOOG-API-FORMAT-VERSION'] = '2'
  response = request.execute()
  return response['dpcs']

except HttpError as err:
  # Parse the JSON content of the error. In your app, check ToS exists first.
  error = json.loads(err.content)
  tos_error = error['error']['details'][0]

  # Ask the user to accept the ToS (not shown here). If they agree, then open
  # the portal in a browser.
  if (tos_error['@type'] == tos_error_type
      and tos_error['latestTosAccepted'] is not True):
    if raw_input('Accept the ToS in the zero-touch portal? y|n ') == 'y':
      webbrowser.open(portal_url)

אם לקוח Google API שלכם תומך בשגיאות מפורטות (Java,‏ Python או בקשות HTTP), צריך לכלול בבקשות את כותרת ה-HTTP‏ X-GOOG-API-FORMAT-VERSION עם הערך 2. אם הלקוח שלכם לא תומך בשגיאות מפורטות (‎.NET ואחרים), צריך להתאים את הודעת השגיאה.

אם נעדכן את התנאים וההגבלות בעתיד, האפליקציה שלכם תפנה את המשתמש לאשר מחדש את התנאים וההגבלות החדשים.

אדמינים ב-IT משתמשים בפורטל ההרשמה ללא מגע כדי לנהל את המשתמשים בארגון שלהם – אי אפשר להציע את זה דרך ה-API של הלקוח. אדמינים ב-IT יכולים גם לנהל מכשירים והגדרות באמצעות הפורטל. אם אתם צריכים לקשר לפורטל מהמסוף או מהתיעוד, אתם יכולים להשתמש בכתובת ה-URL הזו:

https://enterprise.google.com/android/zero-touch/customers

כדאי להודיע לאדמינים של מחלקת ה-IT שהם מתבקשים להיכנס באמצעות חשבון Google.

צירוף מכשיר לתוכנית

הרשמה דרך הארגון היא מנגנון לרישום מכשירים, והיא דומה לרישום באמצעות NFC או קוד QR. המסוף צריך לתמוך במכשירים מנוהלים, וה-DPC צריך לפעול במצב של מכשיר מנוהל באופן מלא.

הרשמה דרך הארגון זמינה במכשירים נתמכים שמותקנת בהם מערכת Android מגרסה 8.0 ואילך. אדמינים ב-IT צריכים לרכוש מכשירים נתמכים ממפיץ שותף. המסוף יכול לעקוב אחרי המכשירים של האדמין ב-IT שזמינים להרשמה דרך הארגון, על ידי קריאה ל-customers.devices.list.

כך מתבצעת ההרשמה:

  1. בפעם הראשונה שמפעילים מכשיר (או אחרי איפוס להגדרות המקוריות), הוא מתחבר לשרת של Google כדי להירשם לתוכנית לרישום ללא מגע.
  2. אם האדמין ב-IT החיל הגדרה על המכשיר, ההרשמה דרך הארגון מפעילה את אשף ההגדרה של מכשיר Android בניהול מלא ומבצעת התאמה אישית של המסכים באמצעות מטא-נתונים מההגדרה.
  3. ההרשמה האוטומטית מורידה ומתקינה את ה-DPC שלכם מ-Google Play.
  4. ה-DPC מקבל את כוונת הפעולה ACTION_PROVISION_MANAGED_DEVICE ומקצה את המכשיר.

אם אין חיבור לאינטרנט, הבדיקה מתבצעת כשהחיבור יהיה זמין. מידע נוסף על הקצאת מכשירים באמצעות הרשמה דרך הארגון מופיע בקטע הקצאת הרשאות בהמשך.

הגדרות ברירת מחדל

ההרשמה דרך הארגון עוזרת לאדמינים ב-IT בעיקר כשהם מגדירים תצורת ברירת מחדל שחלה על כל מכשיר חדש שהארגון רוכש. אם לא מוגדרת הגדרת ברירת מחדל, מומלץ להגדיר אותה דרך המסוף. כדי לדעת אם ארגון הגדיר הגדרת ברירת מחדל, אפשר לבדוק את הערך של customers.configurations.isDefault.

בדוגמה הבאה אפשר לראות איך להגדיר תצורה קיימת כברירת מחדל:

Java

// Send minimal data with the request. Just the 2 required fields.
// targetConfiguration is an existing configuration that we want to make the default.
Configuration configuration = new Configuration();
configuration.setIsDefault(true);
configuration.setConfigurationId(targetConfiguration.getConfigurationId());

// Call the API, including the FieldMask to avoid setting other fields to null.
AndroidProvisioningPartner.Customers.Configurations.Patch request = service
      .customers()
      .configurations()
      .patch(targetConfiguration.getName(), configuration);
request.setUpdateMask("isDefault");
Configuration results = request.execute();

‎.NET

// Send minimal data with the request. Just the 2 required fields.
// targetConfiguration is an existing configuration that we want to make the default.
Configuration configuration = new Configuration
{
    IsDefault = true,
    ConfigurationId = targetConfiguration.ConfigurationId,
};

// Call the API, including the FieldMask to avoid setting other fields to null.
var request = service.Customers.Configurations.Patch(configuration,
                                                     targetConfiguration.Name);
request.UpdateMask = "IsDefault";
Configuration results = request.Execute();

Python

# Send minimal data with the request. Just the 2 required fields.
# target_configuration is an existing configuration we'll make the default.
configuration = {
    'isDefault': True,
    'configurationId': target_configuration['configurationId']}

# Call the API, including the FieldMask to avoid setting other fields to null.
response = service.customers().configurations().patch(
    name=target_configuration['name'],
    body=configuration, updateMask='isDefault').execute()

הפניה לבקר DPC

מומלץ להשתמש בשם משאב ה-API‏ customers.dpcs.name כדי לזהות את ה-DPC ולהשתמש בו בהגדרות. שם המשאב מכיל מזהה ייחודי שלא משתנה של ה-DPC. מתקשרים אל customers.dpcs.list כדי לקבל את רשימת כל ה-DPC הנתמכים. שם המשאב כולל גם את מזהה הלקוח, ולכן צריך לסנן את הרשימה באמצעות רכיב הנתיב האחרון כדי למצוא מופע תואם של Dpc. בדוגמה הבאה אפשר לראות איך להתאים את ה-DPC ולשמור אותו לשימוש מאוחר יותר בהגדרה:

Java

// Return a customer Dpc instance for the specified DPC ID.
String myDpcIdentifier = "AH6Gbe4aiS459wlz58L30cqbbXbUa_JR9...xMSWCiYiuHRWeBbu86Yjq";
final int dpcIdIndex = 3;
final String dpcComponentSeparator = "/";
// ...
for (Dpc dpcApp : dpcs) {
    // Because the DPC name is in the format customers/{CUST_ID}/dpcs/{DPC_ID}, check the
    // fourth component matches the DPC ID.
    String dpcId = dpcApp.getName().split(dpcComponentSeparator)[dpcIdIndex];
    if (dpcId.equals(myDpcIdentifier)) {
        System.out.format("My DPC is: %s\n", dpcApp.getDpcName());
        return dpcApp;
    }
}
// Handle the case when the DPC isn't found...

‎.NET

// Return a customer Dpc instance for the specified DPC ID.
var myDpcIdentifer = "AH6Gbe4aiS459wlz58L30cqbbXbUa_JR9...fE9WdHcxMSWCiYiuHRWeBbu86Yjq";
const int dpcIdIndex = 3;
const String dpcComponentSeparator = "/";
// ...
foreach (Dpc dpcApp in dpcs)
{
    // Because the DPC name is in the format customers/{CUST_ID}/dpcs/{DPC_ID}, check the
    // fourth component matches the DPC ID.
    String dpcId = dpcApp.Name.Split(dpcComponentSeparator)[dpcIdIndex];
    if (dpcId.Equals(myDpcIdentifer))
    {
        Console.WriteLine("Matched DPC is: {0}", dpcApp.DpcName);
        return dpcApp;
    }
}
// Handle the case when the DPC isn't found...

Python

# Return a customer Dpc instance for the specified DPC ID.
my_dpc_id = 'AH6Gbe4aiS459wlz58L30cqb...fE9WdHcxMSWCiYiuHRWeBbu86Yjq'
# ...
for dpc_app in dpcs:
  # Because the DPC name is in the format customers/{CUST_ID}/dpcs/{DPC_ID},
  # check the fourth component matches the DPC ID.
  dpc_id = dpc_app['name'].split('/')[3]
  if dpc_id == my_dpc_id:
    return dpc_app

# Handle the case when the DPC isn't found...

אם אתם צריכים להציג את השם של DPC בממשק המשתמש של המסוף, צריך להציג את הערך שמוחזר מ-customers.dpcs.dpcName.

ניהול הקצאות (Provisioning)

נצלו את ההזדמנות כדי לספק חוויית משתמש מעולה להקצאת מכשירים. שם משתמש וסיסמה הם כל מה שצריך כדי להקצות את המכשיר. חשוב לזכור שמשווקים עשויים לשלוח מכשירים ישירות למשתמשים מרוחקים. כוללים את כל ההגדרות האחרות, כמו שרת EMM או יחידה ארגונית, ב-customers.configuration.dpcExtras.

בקטע ה-JSON הבא מוצג חלק מהגדרות לדוגמה:

{
  "android.app.extra.PROVISIONING_LOCALE": "en_GB",
  "android.app.extra.PROVISIONING_TIME_ZONE": "Europe/London",
  "android.app.extra.PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED": true,
  "android.app.extra.PROVISIONING_ADMIN_EXTRAS_BUNDLE": {
    "workflow_type": 3,
    "default_password_quality": 327680,
    "default_min_password_length": 6,
    "company_name": "XYZ Corp",
    "organizational_unit": "sales-uk",
    "management_server": "emm.example.com",
    "detail_tos_url": "https://www.example.com/policies/terms/",
    "allowed_user_domains": "[\"example.com\", \"example.org\", \"example.net\"]"
    }
}

ההרשמה דרך הארגון מתקינה ומפעילה את ה-DPC באמצעות Android Intent. המערכת שולחת את הערכים במאפיין JSON‏ android.app.extra.PROVISIONING_ADMIN_EXTRAS_BUNDLE אל ה-DPC שלכם כתוספות ב-Intent. ה-DPC יכול לקרוא את הגדרות ההקצאה מתוך PersistableBundle באמצעות אותם מפתחות.

מומלץ – משתמשים בתוספות הבאות של Intent כדי להגדיר את בקר ה-DPC:

לא מומלץ – אל תכללו את התוספים הבאים שאולי אתם משתמשים בהם בשיטות הרשמה אחרות:

כדי ללמוד איך לחלץ את ההגדרות האלה ולהשתמש בהן ב-DPC, אפשר לקרוא את המאמר בנושא הקצאת מכשירים ללקוחות.

פיתוח ובדיקה

כדי לפתח ולבדוק את התכונות של ההרשמה ללא מגע במסוף, תצטרכו:

  • מכשיר נתמך
  • חשבון של לקוח שמשתמש בהרשמה דרך הארגון

כדאי לפתח ולבדוק באמצעות מכשירים שתומכים בהרשמה ללא מגע, כמו Google Pixel. אתם לא חייבים לרכוש את מכשירי הפיתוח שלכם משותף מפיץ.

כדי לקבל חשבון לקוח לניסיון וגישה לפורטל ההרשמה דרך הארגון, אפשר לפנות אלינו. אפשר לשלוח לנו אימייל מכתובת האימייל העסקית שמשויכת לחשבון Google. צריך לציין את היצרן ואת מספר ה-IMEI של מכשיר אחד או שניים, ואנחנו נוסיף אותם לחשבון הפיתוח שלכם.

חשוב לזכור: מכיוון שהרשמה ללא מגע מורידה ומתקינה באופן אוטומטי DPC, ה-DPC צריך להיות זמין ב-Google Play כדי שתוכלו לבדוק את ההקצאה. אי אפשר לבצע בדיקה באמצעות גרסת פיתוח של ה-DPC.

תמיכה באדמינים ממחלקת IT

אם אתם צריכים לעזור לאדמינים של IT בממשק של המסוף או במסמכים, תוכלו להיעזר בהנחיות שבמאמר הרשמה ללא מגע לאדמינים של IT. אפשר גם להפנות את המשתמשים במסוף למאמר הזה במרכז העזרה.

קריאה נוספת

כדי לשלב את ההרשמה דרך הארגון במסוף, כדאי לקרוא את המאמרים הבאים: