Guest User

Untitled

a guest
Apr 26th, 2018
67
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 22.48 KB | None | 0 0
  1. String.xml
  2.  
  3. <resources>
  4. <string name="app_name">FusedLocationProviderClientDemo</string>
  5. <string name="action_settings">Settings</string>
  6.  
  7. <string name="latitude_label">Latitude</string>
  8. <string name="longitude_label">Longitude</string>
  9. <string name="last_update_time_label">Last location update time</string>
  10.  
  11. <string name="start_updates">Start updates</string>
  12. <string name="stop_updates">Stop updates</string>
  13.  
  14. <string name="location_settings_inadequate_warning">The location settings on the device are not
  15. adequate to run this sample. Fix in Settings.</string>
  16.  
  17. <string name="permission_rationale">Location permission is needed for core functionality</string>
  18. <string name="permission_denied_explanation">Permission was denied, but is needed for core
  19. functionality.</string>
  20. <string name="settings">Settings</string>
  21. </resources>
  22.  
  23.  
  24. -----------------------------------------------
  25. Manifest permission
  26. <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
  27. ---------------------------------------------------------------------------
  28. build.gradle
  29. compile 'com.google.android.gms:play-services-location:11.0.0'
  30. --------------------------------------------------------------------------
  31. MainActivity.class
  32.  
  33. import android.Manifest;
  34. import android.app.Activity;
  35. import android.content.Intent;
  36. import android.content.IntentSender;
  37. import android.content.pm.PackageManager;
  38. import android.location.Location;
  39. import android.net.Uri;
  40. import android.os.Bundle;
  41. import android.os.Looper;
  42. import android.provider.Settings;
  43. import android.support.annotation.NonNull;
  44. import android.support.design.widget.Snackbar;
  45. import android.support.v4.app.ActivityCompat;
  46. import android.support.v7.app.AppCompatActivity;
  47. import android.support.v7.widget.Toolbar;
  48. import android.util.Log;
  49. import android.view.Menu;
  50. import android.view.MenuItem;
  51. import android.view.View;
  52. import android.widget.Button;
  53. import android.widget.TextView;
  54. import android.widget.Toast;
  55.  
  56. import com.google.android.gms.common.api.ApiException;
  57. import com.google.android.gms.common.api.ResolvableApiException;
  58. import com.google.android.gms.location.FusedLocationProviderClient;
  59. import com.google.android.gms.location.LocationCallback;
  60. import com.google.android.gms.location.LocationRequest;
  61. import com.google.android.gms.location.LocationResult;
  62. import com.google.android.gms.location.LocationServices;
  63. import com.google.android.gms.location.LocationSettingsRequest;
  64. import com.google.android.gms.location.LocationSettingsResponse;
  65. import com.google.android.gms.location.LocationSettingsStatusCodes;
  66. import com.google.android.gms.location.SettingsClient;
  67. import com.google.android.gms.tasks.OnCompleteListener;
  68. import com.google.android.gms.tasks.OnFailureListener;
  69. import com.google.android.gms.tasks.OnSuccessListener;
  70. import com.google.android.gms.tasks.Task;
  71.  
  72. import java.text.DateFormat;
  73. import java.util.Date;
  74. import java.util.Locale;
  75.  
  76. public class MainActivity extends AppCompatActivity {
  77.  
  78. private static final String TAG = MainActivity.class.getSimpleName();
  79.  
  80. private static final int REQUEST_PERMISSIONS_REQUEST_CODE = 34;
  81. private static final int REQUEST_CHECK_SETTINGS = 0x1;
  82.  
  83. /**
  84. * The desired interval for location updates. Inexact. Updates may be more or less frequent.
  85. */
  86. private static final long UPDATE_INTERVAL_IN_MILLISECONDS = 5000;
  87.  
  88. /**
  89. * The fastest rate for active location updates. Exact. Updates will never be more frequent than this value.
  90. */
  91. private static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = UPDATE_INTERVAL_IN_MILLISECONDS / 2;
  92.  
  93.  
  94. /**
  95. * Provides access to the Fused Location Provider API.
  96. */
  97. private FusedLocationProviderClient mFusedLocationClient;
  98.  
  99. /**
  100. * Provides access to the Location Settings API.
  101. */
  102. private SettingsClient mSettingsClient;
  103.  
  104. /**
  105. * Stores parameters for requests to the FusedLocationProviderApi.
  106. */
  107. private LocationRequest mLocationRequest;
  108.  
  109. /**
  110. * Stores the types of location services the client is interested in using. Used for checking
  111. * settings to determine if the device has optimal location settings.
  112. */
  113. private LocationSettingsRequest mLocationSettingsRequest;
  114.  
  115. /**
  116. * Callback for Location events.
  117. */
  118. private LocationCallback mLocationCallback;
  119.  
  120. /**
  121. * Represents a geographical location.
  122. */
  123. private Location mCurrentLocation;
  124.  
  125. // UI Widgets.
  126. private Button mStartUpdatesButton;
  127. private Button mStopUpdatesButton;
  128. private TextView mLastUpdateTimeTextView;
  129. private TextView mLatitudeTextView;
  130. private TextView mLongitudeTextView;
  131.  
  132. // Labels.
  133. private String mLatitudeLabel;
  134. private String mLongitudeLabel;
  135. private String mLastUpdateTimeLabel;
  136.  
  137. /**
  138. * Tracks the status of the location updates request. Value changes when the user presses the
  139. * Start Updates and Stop Updates buttons.
  140. */
  141. private Boolean mRequestingLocationUpdates;
  142.  
  143. /**
  144. * Time when the location was updated represented as a String.
  145. */
  146. private String mLastUpdateTime;
  147.  
  148. @Override
  149. protected void onCreate(Bundle savedInstanceState) {
  150. super.onCreate(savedInstanceState);
  151. setContentView(R.layout.activity_main);
  152. Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
  153. setSupportActionBar(toolbar);
  154.  
  155. // Locate the UI widgets.
  156. mStartUpdatesButton = (Button) findViewById(R.id.start_updates_button);
  157. mStopUpdatesButton = (Button) findViewById(R.id.stop_updates_button);
  158. mLatitudeTextView = (TextView) findViewById(R.id.latitude_text);
  159. mLongitudeTextView = (TextView) findViewById(R.id.longitude_text);
  160. mLastUpdateTimeTextView = (TextView) findViewById(R.id.last_update_time_text);
  161.  
  162. // Set labels.
  163. mLatitudeLabel = getResources().getString(R.string.latitude_label);
  164. mLongitudeLabel = getResources().getString(R.string.longitude_label);
  165. mLastUpdateTimeLabel = getResources().getString(R.string.last_update_time_label);
  166.  
  167. mRequestingLocationUpdates = false;
  168. mLastUpdateTime = "";
  169.  
  170. mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
  171. mSettingsClient = LocationServices.getSettingsClient(this);
  172.  
  173. // Kick off the process of building the LocationCallback, LocationRequest, and
  174. // LocationSettingsRequest objects.
  175. createLocationCallback();
  176. createLocationRequest();
  177. buildLocationSettingsRequest();
  178. if (!mRequestingLocationUpdates) {
  179. mRequestingLocationUpdates = true;
  180. setButtonsEnabledState();
  181. startLocationUpdates();
  182. }
  183. }
  184.  
  185. /**
  186. * Sets up the location request. Android has two location request settings:
  187. * {@code ACCESS_COARSE_LOCATION} and {@code ACCESS_FINE_LOCATION}. These settings control
  188. * the accuracy of the current location. This sample uses ACCESS_FINE_LOCATION, as defined in
  189. * the AndroidManifest.xml.
  190. * <p/>
  191. * When the ACCESS_FINE_LOCATION setting is specified, combined with a fast update
  192. * interval (5 seconds), the Fused Location Provider API returns location updates that are
  193. * accurate to within a few feet.
  194. * <p/>
  195. * These settings are appropriate for mapping applications that show real-time location
  196. * updates.
  197. */
  198. private void createLocationRequest() {
  199. mLocationRequest = new LocationRequest();
  200.  
  201. // Sets the desired interval for active location updates. This interval is
  202. // inexact. You may not receive updates at all if no location sources are available, or
  203. // you may receive them slower than requested. You may also receive updates faster than
  204. // requested if other applications are requesting location at a faster interval.
  205. mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
  206.  
  207. // Sets the fastest rate for active location updates. This interval is exact, and your
  208. // application will never receive updates faster than this value.
  209. mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
  210.  
  211. mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
  212. }
  213.  
  214. /**
  215. * Creates a callback for receiving location events.
  216. */
  217. private void createLocationCallback() {
  218. mLocationCallback = new LocationCallback() {
  219. @Override
  220. public void onLocationResult(LocationResult locationResult) {
  221. super.onLocationResult(locationResult);
  222.  
  223. mCurrentLocation = locationResult.getLastLocation();
  224. mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
  225. updateLocationUI();
  226. }
  227. };
  228. }
  229.  
  230. /**
  231. * Uses a {@link com.google.android.gms.location.LocationSettingsRequest.Builder} to build
  232. * a {@link com.google.android.gms.location.LocationSettingsRequest} that is used for checking
  233. * if a device has the needed location settings.
  234. */
  235. private void buildLocationSettingsRequest() {
  236. LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
  237. builder.addLocationRequest(mLocationRequest);
  238. mLocationSettingsRequest = builder.build();
  239. }
  240.  
  241. /**
  242. * Handles the Start Updates button and requests start of location updates. Does nothing if
  243. * updates have already been requested.
  244. */
  245. public void startUpdatesButtonHandler(View view) {
  246. if (!mRequestingLocationUpdates) {
  247. mRequestingLocationUpdates = true;
  248. setButtonsEnabledState();
  249. startLocationUpdates();
  250. }
  251. }
  252.  
  253. @Override
  254. protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  255. switch (requestCode) {
  256. // Check for the integer request code originally supplied to startResolutionForResult().
  257. case REQUEST_CHECK_SETTINGS:
  258. switch (resultCode) {
  259. case Activity.RESULT_OK:
  260. Log.e(TAG, "User agreed to make required location settings changes.");
  261. // Nothing to do. startLocationupdates() gets called in onResume again.
  262. startLocationUpdates();
  263. break;
  264. case Activity.RESULT_CANCELED:
  265. Log.e(TAG, "User chose not to make required location settings changes.");
  266. startLocationUpdates();
  267. mRequestingLocationUpdates = false;
  268. updateUI();
  269. break;
  270. }
  271. break;
  272. }
  273. }
  274.  
  275.  
  276. /**
  277. * Requests location updates from the FusedLocationApi. Note: we don't call this unless location
  278. * runtime permission has been granted.
  279. */
  280. private void startLocationUpdates() {
  281. // Begin by checking if the device has the necessary location settings.
  282. mSettingsClient.checkLocationSettings(mLocationSettingsRequest)
  283. .addOnSuccessListener(this, new OnSuccessListener<LocationSettingsResponse>() {
  284. @Override
  285. public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
  286. Log.e(TAG, "All location settings are satisfied.");
  287.  
  288. //noinspection MissingPermission
  289. mFusedLocationClient.requestLocationUpdates(mLocationRequest,
  290. mLocationCallback, Looper.myLooper());
  291.  
  292. updateUI();
  293. }
  294. })
  295. .addOnFailureListener(this, new OnFailureListener() {
  296. @Override
  297. public void onFailure(@NonNull Exception e) {
  298. int statusCode = ((ApiException) e).getStatusCode();
  299. switch (statusCode) {
  300. case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
  301. Log.e(TAG, "Location settings are not satisfied. Attempting to upgrade " +
  302. "location settings ");
  303. try {
  304. // Show the dialog by calling startResolutionForResult(), and check the
  305. // result in onActivityResult().
  306. ResolvableApiException rae = (ResolvableApiException) e;
  307. rae.startResolutionForResult(MainActivity.this, REQUEST_CHECK_SETTINGS);
  308. } catch (IntentSender.SendIntentException sie) {
  309. Log.e(TAG, "PendingIntent unable to execute request.");
  310. }
  311. break;
  312. case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
  313. String errorMessage = "Location settings are inadequate, and cannot be " +
  314. "fixed here. Fix in Settings.";
  315. Log.e(TAG, errorMessage);
  316. Toast.makeText(MainActivity.this, errorMessage, Toast.LENGTH_LONG).show();
  317. mRequestingLocationUpdates = false;
  318. }
  319.  
  320. updateUI();
  321. }
  322. });
  323. }
  324.  
  325. /**
  326. * Updates all UI fields.
  327. */
  328. private void updateUI() {
  329. setButtonsEnabledState();
  330. updateLocationUI();
  331. }
  332.  
  333. /**
  334. * Disables both buttons when functionality is disabled due to insuffucient location settings.
  335. * Otherwise ensures that only one button is enabled at any time. The Start Updates button is
  336. * enabled if the user is not requesting location updates. The Stop Updates button is enabled
  337. * if the user is requesting location updates.
  338. */
  339. private void setButtonsEnabledState() {
  340. if (mRequestingLocationUpdates) {
  341. mStartUpdatesButton.setEnabled(false);
  342. mStopUpdatesButton.setEnabled(true);
  343. } else {
  344. mStartUpdatesButton.setEnabled(true);
  345. mStopUpdatesButton.setEnabled(false);
  346. }
  347. }
  348.  
  349. /**
  350. * Sets the value of the UI fields for the location latitude, longitude and last update time.
  351. */
  352. private void updateLocationUI() {
  353. if (mCurrentLocation != null) {
  354. mLatitudeTextView.setText(String.format(Locale.ENGLISH, "%s: %f", mLatitudeLabel,
  355. mCurrentLocation.getLatitude()));
  356. mLongitudeTextView.setText(String.format(Locale.ENGLISH, "%s: %f", mLongitudeLabel,
  357. mCurrentLocation.getLongitude()));
  358. mLastUpdateTimeTextView.setText(String.format(Locale.ENGLISH, "%s: %s",
  359. mLastUpdateTimeLabel, mLastUpdateTime));
  360. }
  361. }
  362.  
  363. /**
  364. * Removes location updates from the FusedLocationApi.
  365. */
  366. private void stopLocationUpdates() {
  367. if (!mRequestingLocationUpdates) {
  368. Log.d(TAG, "stopLocationUpdates: updates never requested, no-op.");
  369. return;
  370. }
  371.  
  372. // It is a good practice to remove location requests when the activity is in a paused or
  373. // stopped state. Doing so helps battery performance and is especially
  374. // recommended in applications that request frequent location updates.
  375. mFusedLocationClient.removeLocationUpdates(mLocationCallback)
  376. .addOnCompleteListener(this, new OnCompleteListener<Void>() {
  377. @Override
  378. public void onComplete(@NonNull Task<Void> task) {
  379. mRequestingLocationUpdates = false;
  380. setButtonsEnabledState();
  381. }
  382. });
  383. }
  384.  
  385. @Override
  386. public void onResume() {
  387. super.onResume();
  388. // Within {@code onPause()}, we remove location updates. Here, we resume receiving
  389. // location updates if the user has requested them.
  390. if (mRequestingLocationUpdates && checkPermissions()) {
  391. startLocationUpdates();
  392. } else if (!checkPermissions()) {
  393. requestPermissions();
  394. }
  395.  
  396. updateUI();
  397. }
  398.  
  399. @Override
  400. protected void onPause() {
  401. super.onPause();
  402.  
  403. // Remove location updates to save battery.
  404. stopLocationUpdates();
  405. }
  406.  
  407. /**
  408. * Shows a {@link Snackbar}.
  409. *
  410. * @param mainTextStringId The id for the string resource for the Snackbar text.
  411. * @param actionStringId The text of the action item.
  412. * @param listener The listener associated with the Snackbar action.
  413. */
  414. private void showSnackbar(final int mainTextStringId, final int actionStringId,
  415. View.OnClickListener listener) {
  416. Snackbar.make(
  417. findViewById(android.R.id.content),
  418. getString(mainTextStringId),
  419. Snackbar.LENGTH_INDEFINITE)
  420. .setAction(getString(actionStringId), listener).show();
  421. }
  422.  
  423. /**
  424. * Return the current state of the permissions needed.
  425. */
  426. private boolean checkPermissions() {
  427. int permissionState = ActivityCompat.checkSelfPermission(this,
  428. Manifest.permission.ACCESS_FINE_LOCATION);
  429. return permissionState == PackageManager.PERMISSION_GRANTED;
  430. }
  431.  
  432. /**
  433. * Handles the Stop Updates button, and requests removal of location updates.
  434. */
  435. public void stopUpdatesButtonHandler(View view) {
  436. // It is a good practice to remove location requests when the activity is in a paused or
  437. // stopped state. Doing so helps battery performance and is especially
  438. // recommended in applications that request frequent location updates.
  439. stopLocationUpdates();
  440. }
  441.  
  442. private void requestPermissions() {
  443. boolean shouldProvideRationale =
  444. ActivityCompat.shouldShowRequestPermissionRationale(this,
  445. Manifest.permission.ACCESS_FINE_LOCATION);
  446.  
  447. // Provide an additional rationale to the user. This would happen if the user denied the
  448. // request previously, but didn't check the "Don't ask again" checkbox.
  449. if (shouldProvideRationale) {
  450. Log.e(TAG, "Displaying permission rationale to provide additional context.");
  451. showSnackbar(R.string.permission_rationale,
  452. android.R.string.ok, new View.OnClickListener() {
  453. @Override
  454. public void onClick(View view) {
  455. // Request permission
  456. ActivityCompat.requestPermissions(MainActivity.this,
  457. new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
  458. REQUEST_PERMISSIONS_REQUEST_CODE);
  459. }
  460. });
  461. } else {
  462. Log.e(TAG, "Requesting permission");
  463. // Request permission. It's possible this can be auto answered if device policy
  464. // sets the permission in a given state or the user denied the permission
  465. // previously and checked "Never ask again".
  466. ActivityCompat.requestPermissions(MainActivity.this,
  467. new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
  468. REQUEST_PERMISSIONS_REQUEST_CODE);
  469. }
  470. }
  471.  
  472. /**
  473. * Callback received when a permissions request has been completed.
  474. */
  475. @Override
  476. public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
  477. @NonNull int[] grantResults) {
  478. Log.e(TAG, "onRequestPermissionResult");
  479. if (requestCode == REQUEST_PERMISSIONS_REQUEST_CODE) {
  480. if (grantResults.length <= 0) {
  481. // If user interaction was interrupted, the permission request is cancelled and you
  482. // receive empty arrays.
  483. Log.e(TAG, "User interaction was cancelled.");
  484. } else if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
  485. if (mRequestingLocationUpdates) {
  486. Log.e(TAG, "Permission granted, updates requested, starting location updates");
  487. startLocationUpdates();
  488. }
  489. } else {
  490. // Permission denied.
  491.  
  492. // Notify the user via a SnackBar that they have rejected a core permission for the
  493. // app, which makes the Activity useless. In a real app, core permissions would
  494. // typically be best requested during a welcome-screen flow.
  495.  
  496. // Additionally, it is important to remember that a permission might have been
  497. // rejected without asking the user for permission (device policy or "Never ask
  498. // again" prompts). Therefore, a user interface affordance is typically implemented
  499. // when permissions are denied. Otherwise, your app could appear unresponsive to
  500. // touches or interactions which have required permissions.
  501. showSnackbar(R.string.permission_denied_explanation,
  502. R.string.settings, new View.OnClickListener() {
  503. @Override
  504. public void onClick(View view) {
  505. // Build intent that displays the App settings screen.
  506. Intent intent = new Intent();
  507. intent.setAction(
  508. Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
  509. Uri uri = Uri.fromParts("package",
  510. BuildConfig.APPLICATION_ID, null);
  511. intent.setData(uri);
  512. intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  513. startActivity(intent);
  514. }
  515. });
  516. }
  517. }
  518. }
  519.  
  520. @Override
  521. public boolean onCreateOptionsMenu(Menu menu) {
  522. // Inflate the menu; this adds items to the action bar if it is present.
  523. getMenuInflater().inflate(R.menu.menu_main, menu);
  524. return true;
  525. }
  526.  
  527. @Override
  528. public boolean onOptionsItemSelected(MenuItem item) {
  529. // Handle action bar item clicks here. The action bar will
  530. // automatically handle clicks on the Home/Up button, so long
  531. // as you specify a parent activity in AndroidManifest.xml.
  532. int id = item.getItemId();
  533.  
  534. //noinspection SimplifiableIfStatement
  535. if (id == R.id.action_settings) {
  536. return true;
  537. }
  538.  
  539. return super.onOptionsItemSelected(item);
  540. }
  541. }
Add Comment
Please, Sign In to add comment