Trong ứng dụng Google Maps trên Android và nhiều ứng dụng khác mà bạn đã thấy rằng nếu vị trí của mình bị vô hiệu hóa thì sau đó một hộp thoại yêu cầu bật vị trí GPS xuất hiện trực tiếp trên màn hình mà không chuyển hướng bạn đến trang Cài đặt.
Để hiển thị hộp thoại này, chúng ta phải biết được những điều này:
- Google API Client : GoogleApiClient được sử dụng với một loạt các phương thức tĩnh. Một số trong những phương thức này yêu cầu GoogleApiClient được kết nối; kiểm tra tài liệu API cụ thể để xác định xem bạn cần phải được kết nối.
- Location Request : Đối tượng LocationRequest được sử dụng để yêu cầu một Service cập nhật vị trí từ FusedLocationProviderApi.
Trong hướng dẫn này, chúng ta sẽ tìm hiểu làm thế nào để thực hiện Request Location Dialog bằng cách sử dụng GoogleAPIClient và Broadcast Receiver để kiểm tra tình trạng GPS.
Video Demo Show Location Setting Dialog
-
- Tạo 1 project mới trong Android Studio: Vào File ⇒ New ⇒ New Project và điền thông tin yêu cầu. Mặc định sẽ là MainActivity.java.
- Mở build.gradle (Module: app) và thêm vào các thư viện như bên dưới:
dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.google.android.gms:play-services:9.8.0' compile 'com.android.support:appcompat-v7:25.0.0' }
-
- Mở AndroidManifest.xml và thêm quyền cho phép truy cập vị trí.
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
-
- Thêm đoạn code sau vào activity_main.xml.
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.project.ntc.showlocationsettingdialog.MainActivity"> <!-- TextView to show GPS Status --> <TextView android:id="@+id/gps_status" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="15sp" android:layout_centerInParent="true" /> </RelativeLayout>
-
- Bây giờ làm theo các bước dưới đây để thực hiện các chức năng.
- Bước 1: Khởi Google API Khách hàng
- Bây giờ làm theo các bước dưới đây để thực hiện các chức năng.
/* Initiate Google API Client */ private void initGoogleAPIClient() { //Without Google API Client Auto Location Dialog will not work mGoogleApiClient = new GoogleApiClient.Builder(MainActivity.this) .addApi(LocationServices.API) .build(); mGoogleApiClient.connect(); }
-
-
- Bước 2: Kiểm tra Location Permission cho thiết bị Android 6.0 Marshmallow
-
private void checkPermissions() { if (Build.VERSION.SDK_INT >= 23) { if (ContextCompat.checkSelfPermission(MainActivity.this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) requestLocationPermission(); else showSettingDialog(); } else showSettingDialog(); } private void requestLocationPermission() { if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, android.Manifest.permission.ACCESS_FINE_LOCATION)) { ActivityCompat.requestPermissions(MainActivity.this, new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION}, ACCESS_FINE_LOCATION_INTENT_ID); } else { ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, ACCESS_FINE_LOCATION_INTENT_ID); } }
-
-
- Bước 3: Hiển thị Dialog khi GPS đang Tắt
-
private void showSettingDialog() { LocationRequest locationRequest = LocationRequest.create(); locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);//Setting priotity of Location request to high locationRequest.setInterval(30 * 1000); locationRequest.setFastestInterval(5 * 1000);//5 sec Time interval for location update LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder() .addLocationRequest(locationRequest); builder.setAlwaysShow(true); //this is the key ingredient to show dialog always when GPS is off PendingResult<LocationSettingsResult> result = LocationServices.SettingsApi.checkLocationSettings(mGoogleApiClient, builder.build()); result.setResultCallback(new ResultCallback<LocationSettingsResult>() { @Override public void onResult(LocationSettingsResult result) { final Status status = result.getStatus(); final LocationSettingsStates state = result.getLocationSettingsStates(); switch (status.getStatusCode()) { case LocationSettingsStatusCodes.SUCCESS: // All location settings are satisfied. The client can initialize location // requests here. updateGPSStatus("GPS is Enabled in your device"); break; case LocationSettingsStatusCodes.RESOLUTION_REQUIRED: // Location settings are not satisfied. But could be fixed by showing the user // a dialog. try { // Show the dialog by calling startResolutionForResult(), // and check the result in onActivityResult(). status.startResolutionForResult(MainActivity.this, REQUEST_CHECK_SETTINGS); } catch (IntentSender.SendIntentException e) { e.printStackTrace(); // Ignore the error. } break; case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE: // Location settings are not satisfied. However, we have no way to fix the // settings so we won't show the dialog. break; } } }); }
-
-
- Bước 4: Nhận kết quả về hành động của người dùng khi Location Request Dialog hiển thị (Yes or No)
-
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { // Check for the integer request code originally supplied to startResolutionForResult(). case REQUEST_CHECK_SETTINGS: switch (resultCode) { case RESULT_OK: Log.e("Settings", "Result OK"); updateGPSStatus("GPS is Enabled in your device"); //startLocationUpdates(); break; case RESULT_CANCELED: Log.e("Settings", "Result Cancel"); updateGPSStatus("GPS is Disabled in your device"); break; } break; } }
-
-
- Bước 5: Tạo một Broadcast Receiver để kiểm tra tình trạng của GPS bất cứ khi nào nó On hoặc Off
-
private BroadcastReceiver gpsLocationReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { //If Action is Location if (intent.getAction().matches(BROADCAST_ACTION)) { LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); //Check if GPS is turned ON or OFF if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) { Log.e("About GPS", "GPS is Enabled in your device"); updateGPSStatus("GPS is Enabled in your device"); } else { //If GPS turned OFF show Location Dialog new Handler().postDelayed(sendUpdatesToUI, 10); // showSettingDialog(); updateGPSStatus("GPS is Disabled in your device"); Log.e("About GPS", "GPS is Disabled in your device"); } } } };
-
-
- Bước 6: Show Location Request Dialog khi ở trạng thái GPS Off. Ở đây chúng ta phải sử dụng Handler để gọi phương thức trong Main Thread.
-
private Runnable sendUpdatesToUI = new Runnable() { public void run() { showSettingDialog(); } };
-
-
- Bước 7: Đăng ký và Hủy đăng ký Receiver trên onResume và phương thức onDestroy tương ứng.
-
@Override protected void onResume() { super.onResume(); registerReceiver(gpsLocationReceiver, new IntentFilter(BROADCAST_ACTION));//Register broadcast receiver to check the status of GPS } @Override protected void onDestroy() { super.onDestroy(); //Unregister receiver on destroy if (gpsLocationReceiver != null) unregisterReceiver(gpsLocationReceiver); }
- Đoạn code hoàn chỉnh trong MainActivity.java
package com.project.ntc.showlocationsettingdialog; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.IntentSender; import android.content.pm.PackageManager; import android.location.LocationManager; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.support.annotation.NonNull; import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.widget.TextView; import android.widget.Toast; import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.common.api.PendingResult; import com.google.android.gms.common.api.ResultCallback; import com.google.android.gms.common.api.Status; import com.google.android.gms.location.LocationRequest; import com.google.android.gms.location.LocationServices; import com.google.android.gms.location.LocationSettingsRequest; import com.google.android.gms.location.LocationSettingsResult; import com.google.android.gms.location.LocationSettingsStates; import com.google.android.gms.location.LocationSettingsStatusCodes; public class MainActivity extends AppCompatActivity { private static final int REQUEST_CHECK_SETTINGS = 0x1; private static final int ACCESS_FINE_LOCATION_INTENT_ID = 3; private static final String BROADCAST_ACTION = "android.location.PROVIDERS_CHANGED"; private static GoogleApiClient mGoogleApiClient; private TextView gps_status; //Run on UI private Runnable sendUpdatesToUI = new Runnable() { public void run() { showSettingDialog(); } }; /* Broadcast receiver to check status of GPS */ private BroadcastReceiver gpsLocationReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { //If Action is Location if (intent.getAction().matches(BROADCAST_ACTION)) { LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); //Check if GPS is turned ON or OFF if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) { Log.e("About GPS", "GPS is Enabled in your device"); updateGPSStatus("GPS is Enabled in your device"); } else { //If GPS turned OFF show Location Dialog new Handler().postDelayed(sendUpdatesToUI, 10); // showSettingDialog(); updateGPSStatus("GPS is Disabled in your device"); Log.e("About GPS", "GPS is Disabled in your device"); } } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); gps_status = (TextView) findViewById(R.id.gps_status); initGoogleAPIClient();//Init Google API Client checkPermissions();//Check Permission } /* Initiate Google API Client */ private void initGoogleAPIClient() { //Without Google API Client Auto Location Dialog will not work mGoogleApiClient = new GoogleApiClient.Builder(MainActivity.this) .addApi(LocationServices.API) .build(); mGoogleApiClient.connect(); } /* Check Location Permission for Marshmallow Devices */ private void checkPermissions() { if (Build.VERSION.SDK_INT >= 23) { if (ContextCompat.checkSelfPermission(MainActivity.this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) requestLocationPermission(); else showSettingDialog(); } else showSettingDialog(); } /* Show Popup to access User Permission */ private void requestLocationPermission() { if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, android.Manifest.permission.ACCESS_FINE_LOCATION)) { ActivityCompat.requestPermissions(MainActivity.this, new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION}, ACCESS_FINE_LOCATION_INTENT_ID); } else { ActivityCompat.requestPermissions(MainActivity.this, new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION}, ACCESS_FINE_LOCATION_INTENT_ID); } } /* Show Location Access Dialog */ private void showSettingDialog() { LocationRequest locationRequest = LocationRequest.create(); locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);//Setting priotity of Location request to high locationRequest.setInterval(30 * 1000); locationRequest.setFastestInterval(5 * 1000);//5 sec Time interval for location update LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder() .addLocationRequest(locationRequest); builder.setAlwaysShow(true); //this is the key ingredient to show dialog always when GPS is off PendingResult<LocationSettingsResult> result = LocationServices.SettingsApi.checkLocationSettings(mGoogleApiClient, builder.build()); result.setResultCallback(new ResultCallback<LocationSettingsResult>() { @Override public void onResult(LocationSettingsResult result) { final Status status = result.getStatus(); final LocationSettingsStates state = result.getLocationSettingsStates(); switch (status.getStatusCode()) { case LocationSettingsStatusCodes.SUCCESS: // All location settings are satisfied. The client can initialize location // requests here. updateGPSStatus("GPS is Enabled in your device"); break; case LocationSettingsStatusCodes.RESOLUTION_REQUIRED: // Location settings are not satisfied. But could be fixed by showing the user // a dialog. try { // Show the dialog by calling startResolutionForResult(), // and check the result in onActivityResult(). status.startResolutionForResult(MainActivity.this, REQUEST_CHECK_SETTINGS); } catch (IntentSender.SendIntentException e) { e.printStackTrace(); // Ignore the error. } break; case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE: // Location settings are not satisfied. However, we have no way to fix the // settings so we won't show the dialog. break; } } }); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { // Check for the integer request code originally supplied to startResolutionForResult(). case REQUEST_CHECK_SETTINGS: switch (resultCode) { case RESULT_OK: Log.e("Settings", "Result OK"); updateGPSStatus("GPS is Enabled in your device"); //startLocationUpdates(); break; case RESULT_CANCELED: Log.e("Settings", "Result Cancel"); updateGPSStatus("GPS is Disabled in your device"); break; } break; } } @Override protected void onResume() { super.onResume(); registerReceiver(gpsLocationReceiver, new IntentFilter(BROADCAST_ACTION));//Register broadcast receiver to check the status of GPS } @Override protected void onDestroy() { super.onDestroy(); //Unregister receiver on destroy if (gpsLocationReceiver != null) unregisterReceiver(gpsLocationReceiver); } //Method to update GPS status text private void updateGPSStatus(String status) { gps_status.setText(status); } /* On Request permission method to check the permisison is granted or not for Marshmallow+ Devices */ @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); switch (requestCode) { case ACCESS_FINE_LOCATION_INTENT_ID: { // If request is cancelled, the result arrays are empty. if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { //If permission granted show location dialog if APIClient is not null if (mGoogleApiClient == null) { initGoogleAPIClient(); showSettingDialog(); } else showSettingDialog(); } else { updateGPSStatus("Location Permission denied."); Toast.makeText(MainActivity.this, "Location Permission denied.", Toast.LENGTH_SHORT).show(); // permission denied, boo! Disable the // functionality that depends on this permission. } return; } } } }
Code đã xong, giờ thì chạy app và xem thành quả thôi 😀
Thanks. 😀
Link download: https://www.dropbox.com/s/efm11makksm2go3/%5Bntcde.com%5DShowLocationSettingDialog.zip?dl=0
Github: https://github.com/trongcong/ShowLocationSettingDialog.git