שינוי הגדרות המיקום

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

בשיעור הזה נסביר איך להשתמש ב-Settings Client כדי לבדוק אילו הגדרות מופעלות, ולהציג את תיבת הדו-שיח Location Settings כדי שהמשתמש יוכל לעדכן את ההגדרות שלו בלחיצה אחת.

הגדרת שירותי מיקום

כדי להשתמש בשירותי המיקום שמסופקים על ידי Google Play Services וספק המיקום המשולב, צריך לחבר את האפליקציה באמצעות Settings Client, ואז לבדוק את הגדרות המיקום הנוכחיות ולבקש מהמשתמש להפעיל את ההגדרות הנדרשות במקרה הצורך.

באפליקציות שכוללות תכונות שמשתמשות בשירותי מיקום, צריך לבקש הרשאות מיקום בהתאם לתרחישי השימוש של התכונות האלה.

הגדרת בקשת מיקום

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

‘עדכון המרווח’
setIntervalMillis() - השיטה הזו מגדירה את הקצב באלפיות השנייה שבו האפליקציה מעדיפה לקבל עדכוני מיקום. חשוב לזכור שעדכוני המיקום עשויים להיות מהירים או איטיים יותר מהקצב הזה כדי לבצע אופטימיזציה של השימוש בסוללה, או שלא יהיו עדכונים בכלל (לדוגמה, אם למכשיר אין קישוריות).
מרווח העדכון המהיר ביותר
setMinUpdateIntervalMillis() – השיטה הזו מגדירה את הקצב המהיר ביותר באלפיות השנייה שבו האפליקציה יכולה לטפל בעדכוני מיקום. אלא אם האפליקציה שלכם צריכה לקבל עדכונים מהר יותר מהקצב שצוין ב-setInterval(), אתם לא צריכים להפעיל את השיטה הזו.
עדיפות

setPriority() – השיטה הזו מגדירה את העדיפות של הבקשה, ונותנת לשירותי המיקום של Google Play Services רמז חזק לגבי מקורות המיקום שבהם צריך להשתמש. אלה הערכים הנתמכים:

  • PRIORITY_BALANCED_POWER_ACCURACY – ההגדרה הזו מאפשרת לבקש דיוק מיקום בטווח של בלוק עירוני, כלומר דיוק של כ-100 מטרים. רמת הדיוק הזו נחשבת לרמה נמוכה, וסביר להניח שהיא תצרוך פחות חשמל. כשההגדרה הזו מופעלת, סביר להניח ששירותי המיקום ישתמשו ב-Wi-Fi ובמיקום של מגדלי תקשורת. עם זאת, חשוב לזכור שהבחירה בספק המיקום תלויה בגורמים רבים אחרים, כמו המקורות הזמינים.
  • PRIORITY_HIGH_ACCURACY - משתמשים בהגדרה הזו כדי לבקש את המיקום הכי מדויק שאפשר. כשההגדרה הזו פועלת, סביר יותר ששירותי המיקום ישתמשו ב-GPS כדי לקבוע את המיקום.
  • PRIORITY_LOW_POWER - משתמשים בהגדרה הזו כדי לבקש דיוק ברמת העיר, כלומר דיוק של כ-10 קילומטרים. רמת הדיוק הזו נחשבת לרמה נמוכה, וסביר להניח שהיא תצרוך פחות חשמל.
  • PRIORITY_PASSIVE - Use this setting if you need negligible impact on power consumption, but want to receive location updates when available. בהגדרה הזו, האפליקציה לא מפעילה עדכוני מיקום, אבל מקבלת מיקומים שמופעלים על ידי אפליקציות אחרות.

יוצרים את בקשת המיקום ומגדירים את הפרמטרים כמו בדוגמת הקוד הבאה:

Kotlin

  fun createLocationRequest() {
    val locationRequest = LocationRequest.Builder(Priority.PRIORITY_HIGH_ACCURACY, 10000)
        .setMinUpdateIntervalMillis(5000)
        .build()
}

Java

  protected void createLocationRequest() {
    LocationRequest locationRequest = new LocationRequest.Builder(Priority.PRIORITY_HIGH_ACCURACY, 10000)
            .setMinUpdateIntervalMillis(5000)
            .build();
}

העדיפות של PRIORITY_HIGH_ACCURACY, בשילוב עם הגדרת ההרשאה ACCESS_FINE_LOCATION שהגדרתם בקובץ מניפסט של אפליקציה ומרווח עדכונים מהיר של 5, 000 אלפיות השנייה (5 שניות), גורמת לספק המיקום המשולב להחזיר עדכונים לגבי מיקום מדויקים בטווח של כמה מטרים. הגישה הזו מתאימה לאפליקציות מיפוי שמציגות את המיקום בזמן אמת.

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

איך בודקים את הגדרות המיקום הנוכחיות

אחרי שמתחברים ל-Google Play Services ול-API של שירותי המיקום, אפשר לקבל את הגדרות המיקום הנוכחיות של מכשיר המשתמש. כדי לעשות את זה, יוצרים LocationSettingsRequest.Builder ומוסיפים בקשה אחת או יותר למיקום. בקטע הקוד הבא מוצג איך להוסיף את בקשת המיקום שנוצרה בשלב הקודם:

Kotlin

val builder = LocationSettingsRequest.Builder()
        .addLocationRequest(locationRequest)

Java

LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
     .addLocationRequest(locationRequest);

אחר כך בודקים אם הגדרות המיקום הנוכחיות מתאימות:

Kotlin

val builder = LocationSettingsRequest.Builder()

// ...

val client: SettingsClient = LocationServices.getSettingsClient(this)
val task: Task<LocationSettingsResponse> = client.checkLocationSettings(builder.build())

Java

LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();

// ...

SettingsClient client = LocationServices.getSettingsClient(this);
Task<LocationSettingsResponse> task = client.checkLocationSettings(builder.build());

כשה-Task מסתיים, האפליקציה יכולה לבדוק את הגדרות המיקום באמצעות קוד הסטטוס מהאובייקט LocationSettingsResponse. כדי לקבל פרטים נוספים על המצב הנוכחי של הגדרות המיקום הרלוונטיות, האפליקציה יכולה להפעיל את השיטה getLocationSettingsStates() של האובייקט LocationSettingsResponse.

בקשה מהמשתמש לשנות את הגדרות המיקום

כדי לקבוע אם הגדרות המיקום מתאימות לבקשת המיקום, מוסיפים OnFailureListener לאובייקט Task שמאמת את הגדרות המיקום. לאחר מכן, בודקים אם האובייקט Exception שהועבר ל-method‏ onFailure() הוא מופע של המחלקה ResolvableApiException, מה שמציין שצריך לשנות את ההגדרות. לאחר מכן, מציגים תיבת דו-שיח שמבקשת מהמשתמש הרשאה לשנות את הגדרות המיקום באמצעות קריאה ל- startResolutionForResult().

בקטע הקוד הבא אפשר לראות איך לקבוע אם הגדרות המיקום של המשתמש מאפשרות לשירותי המיקום ליצור LocationRequest, ואיך לבקש מהמשתמש הרשאה לשנות את הגדרות המיקום במקרה הצורך:

Kotlin

task.addOnSuccessListener { locationSettingsResponse ->
    // All location settings are satisfied. The client can initialize
    // location requests here.
    // ...
}

task.addOnFailureListener { exception ->
    if (exception is ResolvableApiException){
        // Location settings are not satisfied, but this can be fixed
        // by showing the user a dialog.
        try {
            // Show the dialog by calling startResolutionForResult(),
            // and check the result in onActivityResult().
            exception.startResolutionForResult(this@MainActivity,
                    REQUEST_CHECK_SETTINGS)
        } catch (sendEx: IntentSender.SendIntentException) {
            // Ignore the error.
        }
    }
}

Java

task.addOnSuccessListener(this, new OnSuccessListener<LocationSettingsResponse>() {
    @Override
    public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
        // All location settings are satisfied. The client can initialize
        // location requests here.
        // ...
    }
});

task.addOnFailureListener(this, new OnFailureListener() {
    @Override
    public void onFailure(@NonNull Exception e) {
        if (e instanceof ResolvableApiException) {
            // Location settings are not satisfied, but this can be fixed
            // by showing the user a dialog.
            try {
                // Show the dialog by calling startResolutionForResult(),
                // and check the result in onActivityResult().
                ResolvableApiException resolvable = (ResolvableApiException) e;
                resolvable.startResolutionForResult(MainActivity.this,
                        REQUEST_CHECK_SETTINGS);
            } catch (IntentSender.SendIntentException sendEx) {
                // Ignore the error.
            }
        }
    }
});

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