คู่มือนักพัฒนา Android เกี่ยวกับ Google Location Services API
เผยแพร่แล้ว: 2022-03-11การทราบตำแหน่งของผู้ใช้เป็นข้อมูลที่เป็นประโยชน์ในแอปพลิเคชันต่างๆ ที่เราพัฒนาและใช้งานในปัจจุบัน มีแอปพลิเคชั่นตามตำแหน่งยอดนิยมมากมายที่ทำให้ชีวิตของเราง่ายขึ้น รวมถึงเปลี่ยนวิธีที่เราใช้บริการเหล่านี้ ตัวอย่างคือ Foursquare แอปพลิเคชั่นที่ได้รับความนิยมอย่างมาก ซึ่งผู้ใช้ที่ไปสถานประกอบการบ่อยครั้งและ "เช็คอิน" มักจะได้รับส่วนลด Uber ซึ่งช่วยให้คุณนั่งรถจากโทรศัพท์มือถือในราคาที่ต่ำกว่าแท็กซี่ปกติ รายการมีขนาดใหญ่และยังคงเติบโต
ในบทความนี้ เราจะสร้างแอปพลิเคชัน Android อย่างง่ายเพื่อกำหนดละติจูดและลองจิจูดของผู้ใช้โดยใช้ Google Location Services API ของ Android เมื่อพัฒนาแอปพลิเคชัน Android มีสองวิธีในการรับตำแหน่งของผู้ใช้
แพ็คเกจ “android.location”
แพ็คเกจ “android.location” มีวางจำหน่ายตั้งแต่เปิดตัว Android ครั้งแรก และทำให้เราสามารถเข้าถึงบริการระบุตำแหน่งได้ บริการเหล่านี้อนุญาตให้แอปพลิเคชันรับการอัปเดตตำแหน่งทางภูมิศาสตร์ของอุปกรณ์เป็นระยะ
แพ็คเกจนี้มีวิธีการรับข้อมูลตำแหน่งสองวิธี:
LocationManager.GPS_PROVIDER: ระบุตำแหน่งโดยใช้ดาวเทียม ผู้ให้บริการนี้อาจใช้เวลาสักครู่เพื่อส่งคืนการแก้ไขตำแหน่งทั้งนี้ขึ้นอยู่กับเงื่อนไข
LocationManager.NETWORK_PROVIDER: กำหนดตำแหน่งตามความพร้อมใช้งานของเสาสัญญาณในบริเวณใกล้เคียงและจุดเชื่อมต่อ WiFi ซึ่งเร็วกว่า GPS_PROVIDER
เมื่อคุณกำลังมองหาตำแหน่งผู้ใช้ คุณต้องเล่นกับผู้ให้บริการเหล่านี้และความพร้อมของพวกเขา ตามหลักการแล้วคุณจะได้รับตำแหน่งแรกโดยใช้ NETWORK_PROVIDER ซึ่งอาจไม่ถูกต้อง แต่เร็วกว่ามาก จากนั้น คุณอาจพยายามเพิ่มความแม่นยำโดยการฟังเพื่อแก้ไขตำแหน่งที่ดีขึ้นโดยใช้ GPS_PROVIDER
API ที่จัดเตรียมโดยแพ็คเกจนี้ค่อนข้างต่ำ และต้องการให้ผู้พัฒนาแอปพลิเคชันจัดการรายละเอียดปลีกย่อยในการกำหนดเวลาที่จะขอข้อมูลตำแหน่งและกำหนดเวลาการเรียกใช้ API ด้วยวิธีที่เหมาะสมที่สุด เพื่อปรับปรุงประสบการณ์ของนักพัฒนาด้วยบริการระบบตามตำแหน่งและลดความยุ่งยากในการพัฒนาแอปพลิเคชันที่ทราบตำแหน่ง Google ได้แนะนำวิธีใหม่ในการร้องขอตำแหน่งของผู้ใช้โดยใช้บริการ Google Play นำเสนอ API ที่ง่ายกว่าด้วยความแม่นยำสูงกว่า การกำหนดขอบเขตตำแหน่งพลังงานต่ำ และอื่นๆ อีกมากมาย
Google Location Services API
Google Location Services API หรือที่เรียกว่า FusedLocationProviderApi เป็นวิธีที่ Google แนะนำในการรับตำแหน่งของผู้ใช้ ให้ความแม่นยำสูงสุดตามความต้องการของเรา ข้อดีบางประการของการใช้ API นี้กับ API ก่อนหน้านี้คือ:
ความเรียบง่าย: คุณไม่จำเป็นต้องจัดการกับผู้ให้บริการหลายรายซึ่งแตกต่างจาก API ก่อนหน้านี้ แต่คุณระบุความต้องการระดับสูง เช่น "ความแม่นยำสูง" หรือ "พลังงานต่ำ" และจะใช้แนวทางที่เหมาะสม
ความพร้อมใช้งาน: ให้แอปของคุณเข้าถึงตำแหน่งที่ดีที่สุดและรู้จักล่าสุดได้ทันที โดยปกติข้อมูลนี้จะพร้อมใช้งาน คุณเพียงแค่ต้องขอข้อมูล
ประสิทธิภาพการใช้พลังงาน: ลดการใช้พลังงานของแอปพลิเคชันของคุณ
ความเก่งกาจ: ตอบสนองความต้องการที่หลากหลาย ตั้งแต่การใช้งานเบื้องหน้า - ต้องการข้อมูลตำแหน่งที่แม่นยำสูง ไปจนถึงการใช้งานในเบื้องหลัง - ต้องการเพียงการอัปเดตตำแหน่งเป็นระยะโดยมีผลกระทบต่อพลังงานเพียงเล็กน้อย
ให้เราสร้างแอปพลิเคชัน Android ตามตำแหน่งโดยใช้ API นี้ สำหรับสิ่งนี้ เราจะใช้ IDE ที่ Google แนะนำสำหรับการพัฒนาแอปพลิเคชัน Android - Android Studio การเริ่มต้นใช้งาน Android Studio นั้นค่อนข้างตรงไปตรงมา เว็บไซต์ของพวกเขาอธิบายขั้นตอนที่เกี่ยวข้องกับการติดตั้งและการกำหนดค่าของ Android Studio อย่างละเอียด รวมถึงวิธีการบูตแอปพลิเคชัน Android เครื่องแรกของคุณสำหรับการพัฒนา
Android Studio ควรทำให้ทุกอย่างเป็นเรื่องง่ายสำหรับเรา อย่างไรก็ตาม เราจะต้องเริ่มต้นด้วยการกำหนดค่าสคริปต์การสร้างและเพิ่มบริการ Google Play เป็นการพึ่งพาสำหรับแอปพลิเคชันนี้ ซึ่งสามารถทำได้โดยแก้ไขไฟล์ “build.gradle” ดังนี้:
dependencies { compile 'com.android.support:appcompat-v7:21.0.3' compile 'com.google.android.gms:play-services:6.5.87' // Add this line }
ในขณะที่ฉันเขียนบทความนี้ Google Play Services เวอร์ชันล่าสุดที่มีคือ 6.5.87 ตรวจสอบให้แน่ใจว่าคุณได้ตรวจสอบเวอร์ชันล่าสุดที่มีให้เสมอก่อนที่จะเริ่ม ในกรณีที่เวอร์ชันที่ใหม่กว่าออกมาในภายหลังและคุณตัดสินใจที่จะอัปเดตสำหรับโครงการของคุณเอง ให้ทดสอบคุณลักษณะที่เกี่ยวข้องกับตำแหน่งทั้งหมดกับ Android เวอร์ชันทั้งหมดที่คุณสนับสนุน
ณ จุดนี้ เราควรจะสามารถเริ่มทำงานจริงสำหรับแอปพลิเคชันของเราได้
การขออนุญาต การกำหนดค่า AndroidManifest.xml
Androids มีคุณลักษณะด้านความปลอดภัยเฉพาะที่จะป้องกันไม่ให้แอปพลิเคชันใดๆ ร้องขอตำแหน่งที่แน่นอนของผู้ใช้ เพื่อแก้ปัญหานี้ เราต้องแก้ไข “AndroidManifest.xml” และเพิ่มการอนุญาตที่เราต้องการสำหรับแอปพลิเคชันนี้:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
ในขณะที่เรากำลังดำเนินการอยู่ เราควรกำหนดเวอร์ชันของบริการ Google Play ที่เราใช้สำหรับแอปพลิเคชันนี้ด้วย:
<meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />
กำลังตรวจสอบความพร้อมใช้งานของบริการ Google Play
ก่อนเข้าถึงคุณลักษณะต่างๆ ที่ให้บริการโดย Google Play Services เราต้องตรวจสอบว่าอุปกรณ์นั้นติดตั้ง Google Play Services ไว้หรือไม่ และเวอร์ชันนั้นเป็นเวอร์ชันที่เราตั้งใจจะใช้ (6.5.87)
private boolean checkGooglePlayServices(){ int checkGooglePlayServices = GooglePlayServicesUtil .isGooglePlayServicesAvailable(mContext); if (checkGooglePlayServices != ConnectionResult.SUCCESS) { /* * Google Play Services is missing or update is required * return code could be * SUCCESS, * SERVICE_MISSING, SERVICE_VERSION_UPDATE_REQUIRED, * SERVICE_DISABLED, SERVICE_INVALID. */ GooglePlayServicesUtil.getErrorDialog(checkGooglePlayServices, mContext, REQUEST_CODE_RECOVER_PLAY_SERVICES).show(); return false; } return true; }
วิธีนี้จะตรวจสอบบริการ Google Play และในกรณีที่อุปกรณ์ไม่ได้ติดตั้งไว้ (หายาก แต่ฉันเคยเห็นกรณีดังกล่าว) จะเปิดกล่องโต้ตอบที่มีข้อผิดพลาดที่เกี่ยวข้องและเชิญผู้ใช้ให้ติดตั้ง/อัปเดต บริการ Google Play จาก Google Play Store
หลังจากที่ผู้ใช้ดำเนินการแก้ไขโดย “GooglePlayServicesUtil.getErrorDialog()” แล้ว วิธีการโทรกลับ “onActivityResult()” จะเริ่มทำงาน ดังนั้นเราจึงต้องใช้ตรรกะบางอย่างเพื่อจัดการกับการโทรนั้น:
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == REQUEST_CODE_RECOVER_PLAY_SERVICES) { if (resultCode == RESULT_OK) { // Make sure the app is not already connected or attempting to connect if (!mGoogleApiClient.isConnecting() && !mGoogleApiClient.isConnected()) { mGoogleApiClient.connect(); } } else if (resultCode == RESULT_CANCELED) { Toast.makeText(mContext, "Google Play Services must be installed.", Toast.LENGTH_SHORT).show(); finish(); } } }
การเข้าถึง Google APIs
ในการเข้าถึง Google API เราแค่ต้องดำเนินการอีกหนึ่งขั้นตอน: สร้างอินสแตนซ์ของ GoogleApiClient ไคลเอ็นต์ Google API เป็นจุดเริ่มต้นทั่วไปสำหรับบริการ Google Play ทั้งหมด และจัดการการเชื่อมต่อเครือข่ายระหว่างอุปกรณ์ของผู้ใช้และบริการ Google แต่ละบริการ ขั้นตอนแรกของเราที่นี่คือการเริ่มต้นการเชื่อมต่อ ฉันมักจะเรียกรหัสนี้จากวิธี "onCreate" ของกิจกรรม:
protected synchronized void buildGoogleApiClient() { mGoogleApiClient = new GoogleApiClient.Builder(this) .addConnectionCallbacks(this) .addOnConnectionFailedListener(this) .addApi(LocationServices.API) .build(); }
โดยการเชื่อมโยงชุดของการเรียกเมธอด เรากำลังระบุการใช้งานอินเทอร์เฟซการโทรกลับและ Location Service API ที่เราต้องการใช้ การใช้งานอินเทอร์เฟซ ในกรณีนี้ "นี้" จะได้รับการตอบสนองต่อวิธี "เชื่อมต่อ ()" แบบอะซิงโครนัสเมื่อการเชื่อมต่อกับบริการ Google Play สำเร็จ ล้มเหลว หรือถูกระงับ หลังจากเพิ่มรหัสนี้ “กิจกรรมหลัก” ของเราควรมีลักษณะดังนี้:

package com.bitwoo.userlocation; import android.content.Intent; import android.location.Location; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; import android.view.Menu; import android.view.MenuItem; import android.widget.Toast; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.GooglePlayServicesUtil; import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.location.LocationServices; public class MainActivity extends ActionBarActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener { private static int REQUEST_CODE_RECOVER_PLAY_SERVICES = 200; private GoogleApiClient mGoogleApiClient; private Location mLastLocation; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (checkGooglePlayServices()) { buildGoogleApiClient(); } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } private boolean checkGooglePlayServices() { int checkGooglePlayServices = GooglePlayServicesUtil .isGooglePlayServicesAvailable(this); if (checkGooglePlayServices != ConnectionResult.SUCCESS) { /* * google play services is missing or update is required * return code could be * SUCCESS, * SERVICE_MISSING, SERVICE_VERSION_UPDATE_REQUIRED, * SERVICE_DISABLED, SERVICE_INVALID. */ GooglePlayServicesUtil.getErrorDialog(checkGooglePlayServices, this, REQUEST_CODE_RECOVER_PLAY_SERVICES).show(); return false; } return true; } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == REQUEST_CODE_RECOVER_PLAY_SERVICES) { if (resultCode == RESULT_OK) { // Make sure the app is not already connected or attempting to connect if (!mGoogleApiClient.isConnecting() && !mGoogleApiClient.isConnected()) { mGoogleApiClient.connect(); } } else if (resultCode == RESULT_CANCELED) { Toast.makeText(this, "Google Play Services must be installed.", Toast.LENGTH_SHORT).show(); finish(); } } } protected synchronized void buildGoogleApiClient() { mGoogleApiClient = new GoogleApiClient.Builder(this) .addConnectionCallbacks(this) .addOnConnectionFailedListener(this) .addApi(LocationServices.API) .build(); } @Override public void onConnected(Bundle bundle) { } @Override public void onConnectionSuspended(int i) { } @Override public void onConnectionFailed(ConnectionResult connectionResult) { } }
จากนั้นในวิธี “onStart” ของเรา เราเรียกวิธี “เชื่อมต่อ” และรอให้วิธีการโทรกลับ “onConnected” ถูกเรียกใช้:
@Override protected void onStart() { super.onStart(); if (mGoogleApiClient != null) { mGoogleApiClient.connect(); } }
วิธี “onConnected” จะมีลักษณะดังนี้:
@Override public void onConnected(Bundle bundle) { mLastLocation = LocationServices.FusedLocationApi.getLastLocation( mGoogleApiClient); if (mLastLocation != null) { Toast.makeText(this, "Latitude:" + mLastLocation.getLatitude()+", Longitude:"+mLastLocation.getLongitude(),Toast.LENGTH_LONG).show(); } }
การโทรกลับนี้เริ่มทำงานเมื่อมีการเชื่อมต่อ Google Play Services ซึ่งหมายความว่าเมื่อถึงเวลานั้น เราควรจะมีตำแหน่งที่รู้จักล่าสุด อย่างไรก็ตาม ตำแหน่งนี้สามารถเป็นโมฆะได้ (หายากแต่ไม่ใช่เป็นไปไม่ได้) ในกรณีนั้น สิ่งที่ฉันแนะนำคือการฟังการอัปเดตตำแหน่งซึ่งจะกล่าวถึงในครั้งต่อไป
กำลังฟังการอัปเดตตำแหน่ง
หลังจากที่คุณเรียกใช้ "getLastLocation" คุณอาจต้องการขออัปเดตเป็นระยะจาก Fused Location Provider ช่วงเวลานี้อาจสั้นหรือยาวขึ้นอยู่กับใบสมัครของคุณ ตัวอย่างเช่น หากคุณกำลังสร้างแอปพลิเคชันที่ติดตามตำแหน่งของผู้ใช้ในขณะที่เขาขับรถ คุณจะต้องฟังการอัปเดตในช่วงเวลาสั้นๆ ในทางกลับกัน หากแอปพลิเคชันของคุณเกี่ยวกับการแชร์ตำแหน่งของผู้ใช้กับเพื่อนของเขา คุณอาจต้องขอตำแหน่งเป็นครั้งคราว
การสร้างคำขอนั้นค่อนข้างง่าย - คุณสามารถเรียกวิธีนี้ในวิธี “onCreate”:
protected void createLocationRequest() { mLocationRequest = new LocationRequest(); mLocationRequest.setInterval(20000); mLocationRequest.setFastestInterval(5000); mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); }
เราสร้างอินสแตนซ์อ็อบเจ็กต์ LocationRequest ใหม่ ตั้งช่วงเวลาเป็น 20 วินาที (20000 มิลลิวินาที) นอกจากนี้ เราตั้งอัตราการอัปเดตแบบจำกัดเป็น 5 วินาที สิ่งนี้บอก API ให้อัปเดตทุก ๆ 20 วินาที (ควร) แต่ถ้ามีการเปลี่ยนแปลงภายใน 5 วินาทีก็ควรให้สิ่งนั้นเช่นกัน สุดท้าย เราตั้งค่าลำดับความสำคัญเป็น “PRIORITY_HIGH_ACCURACY” ท่ามกลางตัวเลือกลำดับความสำคัญอื่นๆ: PRIORITY_BALANCED_POWER_ACCURACY, PRIORITY_LOW_POWER, PRIORITY_NO_POWER
เมื่อคุณสร้างคำขอแล้ว คุณก็พร้อมที่จะเริ่มฟังการอัพเดตตำแหน่งหลังจากวิธีการ “onConnected()” ถูกไล่ออก:
protected void startLocationUpdates() { LocationServices.FusedLocationApi.requestLocationUpdates( mGoogleApiClient, mLocationRequest, this); }
สิ่งที่เหลืออยู่ในตอนนี้คือการใช้วิธีการโทรกลับเพื่อตอบสนองอินเทอร์เฟซ LocationListener:
public class MainActivity extends ActionBarActivity implements ConnectionCallbacks, OnConnectionFailedListener, LocationListener { // ... @Override public void onLocationChanged(Location location) { mLastLocation = location; Toast.makeText(this, "Latitude:" + mLastLocation.getLatitude()+", Longitude:"+mLastLocation.getLongitude(),Toast.LENGTH_LONG).show(); } }
หยุดฟังการอัปเดต
สิ่งสำคัญคือต้องหยุดฟังการอัปเดตอย่างชัดเจนเมื่อคุณไม่ต้องการใช้อีกต่อไป หรือหากผู้ใช้ออกจากแอปพลิเคชันของคุณ ควรเรียกใช้เมธอดต่อไปนี้จากภายในการโทรกลับ "onPause":
protected void stopLocationUpdates() { if (mGoogleApiClient != null) { LocationServices.FusedLocationApi.removeLocationUpdates( mGoogleApiClient, this); } }
… และยกเลิกการเชื่อมต่อ Google API:
@Override protected void onStop() { super.onStop(); if (mGoogleApiClient != null) { mGoogleApiClient.disconnect(); } }
ห่อ
อย่างที่คุณเห็น แนวคิดพื้นฐานเบื้องหลังการนำแอปพลิเคชันทราบตำแหน่งไปใช้ใน Android นั้นง่ายมาก นอกจากนี้ ด้วย API ที่มีอยู่ซึ่งทั้งใช้งานง่ายและเข้าใจง่าย จึงไม่ควรคิดที่จะสร้างแอปพลิเคชันพื้นฐานตามตำแหน่งสำหรับ Android แอปพลิเคชันตัวอย่างขนาดเล็กที่เราสร้างขึ้นที่นี่มีขึ้นเพื่อแสดงให้เห็นอย่างชัดเจนว่า คุณสามารถค้นหาซอร์สโค้ดที่สมบูรณ์สำหรับสิ่งนี้ได้ที่ GitHub โปรดทราบว่าเพื่อให้สิ่งต่าง ๆ ง่ายขึ้น แอปพลิเคชันไม่ได้จัดการวิธีการโทรกลับ “onConnectionFailed”
หวังว่าบทช่วยสอนนี้จะช่วยคุณในการเริ่มต้นใช้งาน Google Location Services API