Created
April 4, 2018 07:31
-
-
Save evanca/0c48737ec4af3a18f2725ed48e379536 to your computer and use it in GitHub Desktop.
Android Useful Resources / Retrieve the last known location for a device https://github.com/googlesamples/android-play-location/tree/master/BasicLocationSample
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8"?> | |
<!-- | |
Copyright 2014 Google, Inc. | |
Licensed under the Apache License, Version 2.0 (the "License"); | |
you may not use this file except in compliance with the License. | |
You may obtain a copy of the License at | |
http://www.apache.org/licenses/LICENSE-2.0 | |
Unless required by applicable law or agreed to in writing, software | |
distributed under the License is distributed on an "AS IS" BASIS, | |
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
See the License for the specific language governing permissions and | |
limitations under the License. | |
--> | |
<manifest xmlns:android="http://schemas.android.com/apk/res/android" | |
package="com.google.android.gms.location.sample.basiclocationsample" > | |
<!-- | |
Android has two location request settings: {@code ACCESS_COARSE_LOCATION} and | |
{@code ACCESS_FINE_LOCATION}. These settings control the accuracy of the current location. This | |
sample uses ACCESS_COARSE_LOCATION. As a result, the location services return a location with | |
an accuracy approximately equivalent to a city block. | |
--> | |
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> | |
<application | |
android:allowBackup="true" | |
android:icon="@drawable/ic_launcher" | |
android:label="@string/app_name" | |
android:theme="@style/Theme.Base" > | |
<meta-data android:name="com.google.android.gms.version" | |
android:value="@integer/google_play_services_version" /> | |
<activity | |
android:name=".MainActivity" | |
android:label="@string/app_name" > | |
<intent-filter> | |
<action android:name="android.intent.action.MAIN" /> | |
<category android:name="android.intent.category.LAUNCHER" /> | |
</intent-filter> | |
</activity> | |
</application> | |
</manifest> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
apply plugin: 'com.android.application' | |
android { | |
compileSdkVersion 25 | |
buildToolsVersion "25.0.3" | |
defaultConfig { | |
applicationId "com.google.android.gms.location.sample.basiclocationsample" | |
minSdkVersion 16 | |
targetSdkVersion 25 | |
versionCode 1 | |
versionName "1.0" | |
} | |
buildTypes { | |
release { | |
minifyEnabled false | |
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' | |
} | |
} | |
} | |
dependencies { | |
compile fileTree(dir: 'libs', include: ['*.jar']) | |
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { | |
exclude group: 'com.android.support', module: 'support-annotations' | |
}) | |
compile 'com.android.support:appcompat-v7:25.3.1' | |
testCompile 'junit:junit:4.12' | |
compile 'com.android.support:design:25.3.1' | |
compile 'com.google.android.gms:play-services-location:11.0.0' | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8"?><!-- | |
Copyright (C) 2014 Google, Inc. | |
Licensed under the Apache License, Version 2.0 (the "License"); | |
you may not use this file except in compliance with the License. | |
You may obtain a copy of the License at | |
http://www.apache.org/licenses/LICENSE-2.0 | |
Unless required by applicable law or agreed to in writing, software | |
distributed under the License is distributed on an "AS IS" BASIS, | |
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
See the License for the specific language governing permissions and | |
limitations under the License. | |
--> | |
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | |
android:id="@+id/main_activity_container" | |
android:layout_width="match_parent" | |
android:layout_height="match_parent" | |
android:orientation="vertical" | |
android:paddingBottom="@dimen/activity_vertical_margin" | |
android:paddingLeft="@dimen/activity_horizontal_margin" | |
android:paddingRight="@dimen/activity_horizontal_margin" | |
android:paddingTop="@dimen/activity_vertical_margin"> | |
<TextView | |
android:id="@+id/latitude_text" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_marginLeft="10dp" | |
android:layout_marginStart="10dp" | |
android:textIsSelectable="true" | |
android:textSize="@dimen/lat_long_text_size" /> | |
<TextView | |
android:id="@+id/longitude_text" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_marginLeft="10dp" | |
android:layout_marginStart="10dp" | |
android:layout_marginTop="@dimen/text_margin" | |
android:textIsSelectable="true" | |
android:textSize="@dimen/lat_long_text_size" /> | |
</LinearLayout> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Copyright 2017 Google Inc. All Rights Reserved. | |
<p> | |
Licensed under the Apache License, Version 2.0 (the "License"); | |
you may not use this file except in compliance with the License. | |
You may obtain a copy of the License at | |
<p> | |
http://www.apache.org/licenses/LICENSE-2.0 | |
<p> | |
Unless required by applicable law or agreed to in writing, software | |
distributed under the License is distributed on an "AS IS" BASIS, | |
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
See the License for the specific language governing permissions and | |
limitations under the License. | |
*/ | |
package com.google.android.gms.location.sample.basiclocationsample; | |
import android.Manifest; | |
import android.content.Intent; | |
import android.content.pm.PackageManager; | |
import android.location.Location; | |
import android.net.Uri; | |
import android.os.Bundle; | |
import android.provider.Settings; | |
import android.support.annotation.NonNull; | |
import android.support.design.widget.Snackbar; | |
import android.support.v4.app.ActivityCompat; | |
import android.support.v7.app.AppCompatActivity; | |
import android.util.Log; | |
import android.view.View; | |
import android.widget.TextView; | |
import com.google.android.gms.location.FusedLocationProviderClient; | |
import com.google.android.gms.location.LocationServices; | |
import com.google.android.gms.tasks.OnCompleteListener; | |
import com.google.android.gms.tasks.Task; | |
import java.util.Locale; | |
/** | |
* Location sample. | |
* <p> | |
* Demonstrates use of the Location API to retrieve the last known location for a device. | |
*/ | |
public class MainActivity extends AppCompatActivity { | |
private static final String TAG = MainActivity.class.getSimpleName(); | |
private static final int REQUEST_PERMISSIONS_REQUEST_CODE = 34; | |
/** | |
* Provides the entry point to the Fused Location Provider API. | |
*/ | |
private FusedLocationProviderClient mFusedLocationClient; | |
/** | |
* Represents a geographical location. | |
*/ | |
protected Location mLastLocation; | |
private String mLatitudeLabel; | |
private String mLongitudeLabel; | |
private TextView mLatitudeText; | |
private TextView mLongitudeText; | |
@Override | |
public void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
setContentView(R.layout.main_activity); | |
mLatitudeLabel = getResources().getString(R.string.latitude_label); | |
mLongitudeLabel = getResources().getString(R.string.longitude_label); | |
mLatitudeText = (TextView) findViewById((R.id.latitude_text)); | |
mLongitudeText = (TextView) findViewById((R.id.longitude_text)); | |
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this); | |
} | |
@Override | |
public void onStart() { | |
super.onStart(); | |
if (!checkPermissions()) { | |
requestPermissions(); | |
} else { | |
getLastLocation(); | |
} | |
} | |
/** | |
* Provides a simple way of getting a device's location and is well suited for | |
* applications that do not require a fine-grained location and that do not need location | |
* updates. Gets the best and most recent location currently available, which may be null | |
* in rare cases when a location is not available. | |
* <p> | |
* Note: this method should be called after location permission has been granted. | |
*/ | |
@SuppressWarnings("MissingPermission") | |
private void getLastLocation() { | |
mFusedLocationClient.getLastLocation() | |
.addOnCompleteListener(this, new OnCompleteListener<Location>() { | |
@Override | |
public void onComplete(@NonNull Task<Location> task) { | |
if (task.isSuccessful() && task.getResult() != null) { | |
mLastLocation = task.getResult(); | |
mLatitudeText.setText(String.format(Locale.ENGLISH, "%s: %f", | |
mLatitudeLabel, | |
mLastLocation.getLatitude())); | |
mLongitudeText.setText(String.format(Locale.ENGLISH, "%s: %f", | |
mLongitudeLabel, | |
mLastLocation.getLongitude())); | |
} else { | |
Log.w(TAG, "getLastLocation:exception", task.getException()); | |
showSnackbar(getString(R.string.no_location_detected)); | |
} | |
} | |
}); | |
} | |
/** | |
* Shows a {@link Snackbar} using {@code text}. | |
* | |
* @param text The Snackbar text. | |
*/ | |
private void showSnackbar(final String text) { | |
View container = findViewById(R.id.main_activity_container); | |
if (container != null) { | |
Snackbar.make(container, text, Snackbar.LENGTH_LONG).show(); | |
} | |
} | |
/** | |
* Shows a {@link Snackbar}. | |
* | |
* @param mainTextStringId The id for the string resource for the Snackbar text. | |
* @param actionStringId The text of the action item. | |
* @param listener The listener associated with the Snackbar action. | |
*/ | |
private void showSnackbar(final int mainTextStringId, final int actionStringId, | |
View.OnClickListener listener) { | |
Snackbar.make(findViewById(android.R.id.content), | |
getString(mainTextStringId), | |
Snackbar.LENGTH_INDEFINITE) | |
.setAction(getString(actionStringId), listener).show(); | |
} | |
/** | |
* Return the current state of the permissions needed. | |
*/ | |
private boolean checkPermissions() { | |
int permissionState = ActivityCompat.checkSelfPermission(this, | |
Manifest.permission.ACCESS_COARSE_LOCATION); | |
return permissionState == PackageManager.PERMISSION_GRANTED; | |
} | |
private void startLocationPermissionRequest() { | |
ActivityCompat.requestPermissions(MainActivity.this, | |
new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, | |
REQUEST_PERMISSIONS_REQUEST_CODE); | |
} | |
private void requestPermissions() { | |
boolean shouldProvideRationale = | |
ActivityCompat.shouldShowRequestPermissionRationale(this, | |
Manifest.permission.ACCESS_COARSE_LOCATION); | |
// Provide an additional rationale to the user. This would happen if the user denied the | |
// request previously, but didn't check the "Don't ask again" checkbox. | |
if (shouldProvideRationale) { | |
Log.i(TAG, "Displaying permission rationale to provide additional context."); | |
showSnackbar(R.string.permission_rationale, android.R.string.ok, | |
new View.OnClickListener() { | |
@Override | |
public void onClick(View view) { | |
// Request permission | |
startLocationPermissionRequest(); | |
} | |
}); | |
} else { | |
Log.i(TAG, "Requesting permission"); | |
// Request permission. It's possible this can be auto answered if device policy | |
// sets the permission in a given state or the user denied the permission | |
// previously and checked "Never ask again". | |
startLocationPermissionRequest(); | |
} | |
} | |
/** | |
* Callback received when a permissions request has been completed. | |
*/ | |
@Override | |
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, | |
@NonNull int[] grantResults) { | |
Log.i(TAG, "onRequestPermissionResult"); | |
if (requestCode == REQUEST_PERMISSIONS_REQUEST_CODE) { | |
if (grantResults.length <= 0) { | |
// If user interaction was interrupted, the permission request is cancelled and you | |
// receive empty arrays. | |
Log.i(TAG, "User interaction was cancelled."); | |
} else if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { | |
// Permission granted. | |
getLastLocation(); | |
} else { | |
// Permission denied. | |
// Notify the user via a SnackBar that they have rejected a core permission for the | |
// app, which makes the Activity useless. In a real app, core permissions would | |
// typically be best requested during a welcome-screen flow. | |
// Additionally, it is important to remember that a permission might have been | |
// rejected without asking the user for permission (device policy or "Never ask | |
// again" prompts). Therefore, a user interface affordance is typically implemented | |
// when permissions are denied. Otherwise, your app could appear unresponsive to | |
// touches or interactions which have required permissions. | |
showSnackbar(R.string.permission_denied_explanation, R.string.settings, | |
new View.OnClickListener() { | |
@Override | |
public void onClick(View view) { | |
// Build intent that displays the App settings screen. | |
Intent intent = new Intent(); | |
intent.setAction( | |
Settings.ACTION_APPLICATION_DETAILS_SETTINGS); | |
Uri uri = Uri.fromParts("package", | |
BuildConfig.APPLICATION_ID, null); | |
intent.setData(uri); | |
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); | |
startActivity(intent); | |
} | |
}); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment