Showing posts with label Google Play Services. Show all posts
Showing posts with label Google Play Services. Show all posts

Friday, April 22, 2016

Requesting Permissions of Manifest.permission.ACCESS_FINE_LOCATION at Run Time

Refer to last example of "Get my Last Known Location, by calling LocationServices.FusedLocationApi.getLastLocation()" in Android Studio, you will be prompted with "code should explicitly check to see if permission is available (with 'checkPermission') or explicitly handle a potential 'SecurityException'" on the code "LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient)".


Last example handle 'SecurityException' with try/catch. This example show another approach to check if permission is available with 'checkPermission', then call ActivityCompat.requestPermissions() if need, and handle the user answer in onRequestPermissionsResult().

reference: Android Developers - Requesting Permissions at Run Time




notice for sending location to Android Emulator: I have to open another app, Google Maps, to monitor location, otherwise my example cannot get the updated location.

Edit MainActivity.java from last post.
package com.blogspot.android_er.androidgetlastlocation;

import android.Manifest;
import android.content.pm.PackageManager;
import android.location.Location;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationServices;

public class MainActivity extends AppCompatActivity
implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {

Button btnGetLastLocation;
TextView textLastLocation;

GoogleApiClient mGoogleApiClient;
Location mLastLocation;

static final int MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION = 1;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnGetLastLocation = (Button) findViewById(R.id.getlastlocation);
btnGetLastLocation.setOnClickListener(btnGetLastLocationOnClickListener);
textLastLocation = (TextView) findViewById(R.id.lastlocation);

// Create an instance of GoogleAPIClient.
if (mGoogleApiClient == null) {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
}

View.OnClickListener btnGetLastLocationOnClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {

if (mGoogleApiClient != null) {
if (mGoogleApiClient.isConnected()) {
getMyLocation();
} else {
Toast.makeText(MainActivity.this,
"!mGoogleApiClient.isConnected()", Toast.LENGTH_LONG).show();
}
} else {
Toast.makeText(MainActivity.this,
"mGoogleApiClient == null", Toast.LENGTH_LONG).show();
}
}
};

/*
// Handle 'SecurityException' with try/catch
private void getMyLocation(){
try{
//code should explicitly check to see if permission is available
//(with 'checkPermission') or explicitly handle a potential 'SecurityException'
//
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (mLastLocation != null) {
textLastLocation.setText(
String.valueOf(mLastLocation.getLatitude()) + "\n"
+ String.valueOf(mLastLocation.getLongitude()));
Toast.makeText(MainActivity.this,
String.valueOf(mLastLocation.getLatitude()) + "\n"
+ String.valueOf(mLastLocation.getLongitude()),
Toast.LENGTH_LONG).show();
}else{
Toast.makeText(MainActivity.this,
"mLastLocation == null",
Toast.LENGTH_LONG).show();
}
} catch (SecurityException e){
Toast.makeText(MainActivity.this,
"SecurityException:\n" + e.toString(),
Toast.LENGTH_LONG).show();
}
}
*/


//------------------------------------------------------------------------------
//ref: Requesting Permissions at Run Time
//http://developer.android.com/training/permissions/requesting.html
//------------------------------------------------------------------------------
private void getMyLocation() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.


//------------------------------------------------------------------------------
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);

return;
}
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (mLastLocation != null) {
textLastLocation.setText(
String.valueOf(mLastLocation.getLatitude()) + "\n"
+ String.valueOf(mLastLocation.getLongitude()));
Toast.makeText(MainActivity.this,
String.valueOf(mLastLocation.getLatitude()) + "\n"
+ String.valueOf(mLastLocation.getLongitude()),
Toast.LENGTH_LONG).show();
}else{
Toast.makeText(MainActivity.this,
"mLastLocation == null",
Toast.LENGTH_LONG).show();
}
}


@Override
public void onRequestPermissionsResult(
int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

switch (requestCode) {
case MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(MainActivity.this,
"permission was granted, :)",
Toast.LENGTH_LONG).show();
getMyLocation();

} else {
Toast.makeText(MainActivity.this,
"permission denied, ...:(",
Toast.LENGTH_LONG).show();
}
return;
}

// other 'case' lines to check for other
// permissions this app might request
}
}


@Override
protected void onStart() {
mGoogleApiClient.connect();
super.onStart();
}

@Override
protected void onStop() {
mGoogleApiClient.disconnect();
super.onStop();
}

@Override
public void onConnected(@Nullable Bundle bundle) {
getMyLocation();
}

@Override
public void onConnectionSuspended(int i) {
Toast.makeText(MainActivity.this,
"onConnectionSuspended: " + String.valueOf(i),
Toast.LENGTH_LONG).show();
}

@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
Toast.makeText(MainActivity.this,
"onConnectionFailed: \n" + connectionResult.toString(),
Toast.LENGTH_LONG).show();
}
}


Related:
- Request Location Updates with LocationListener.onLocationChanged()

Thursday, April 21, 2016

Get my Last Known Location, by calling LocationServices.FusedLocationApi.getLastLocation()

The example show how to get my Last Known Location, by calling LocationServices.FusedLocationApi.getLastLocation() of Google play Service.


reference: Android Developers - Getting the Last Known Location


To use Google Play Service in your project, you have to Add Google Play Services to Android Studio project, refer last post.

MainActivity.java
package com.blogspot.android_er.androidgetlastlocation;

import android.location.Location;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationServices;

public class MainActivity extends AppCompatActivity
implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {

Button btnGetLastLocation;
TextView textLastLocation;

GoogleApiClient mGoogleApiClient;
Location mLastLocation;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnGetLastLocation = (Button) findViewById(R.id.getlastlocation);
btnGetLastLocation.setOnClickListener(btnGetLastLocationOnClickListener);
textLastLocation = (TextView) findViewById(R.id.lastlocation);

// Create an instance of GoogleAPIClient.
if (mGoogleApiClient == null) {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
}

View.OnClickListener btnGetLastLocationOnClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {

if(mGoogleApiClient != null){
if(mGoogleApiClient.isConnected()){
getMyLocation();
}else{
Toast.makeText(MainActivity.this,
"!mGoogleApiClient.isConnected()", Toast.LENGTH_LONG).show();
}
}else{
Toast.makeText(MainActivity.this,
"mGoogleApiClient == null", Toast.LENGTH_LONG).show();
}
}
};

private void getMyLocation(){
try{
/* code should explicitly check to see if permission is available
(with 'checkPermission') or explicitly handle a potential 'SecurityException'
*/
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (mLastLocation != null) {
textLastLocation.setText(
String.valueOf(mLastLocation.getLatitude()) + "\n"
+ String.valueOf(mLastLocation.getLongitude()));
Toast.makeText(MainActivity.this,
String.valueOf(mLastLocation.getLatitude()) + "\n"
+ String.valueOf(mLastLocation.getLongitude()),
Toast.LENGTH_LONG).show();
}else{
Toast.makeText(MainActivity.this,
"mLastLocation == null",
Toast.LENGTH_LONG).show();
}
} catch (SecurityException e){
Toast.makeText(MainActivity.this,
"SecurityException:\n" + e.toString(),
Toast.LENGTH_LONG).show();
}
}

@Override
protected void onStart() {
mGoogleApiClient.connect();
super.onStart();
}

@Override
protected void onStop() {
mGoogleApiClient.disconnect();
super.onStop();
}

@Override
public void onConnected(@Nullable Bundle bundle) {
getMyLocation();
}

@Override
public void onConnectionSuspended(int i) {
Toast.makeText(MainActivity.this,
"onConnectionSuspended: " + String.valueOf(i),
Toast.LENGTH_LONG).show();
}

@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
Toast.makeText(MainActivity.this,
"onConnectionFailed: \n" + connectionResult.toString(),
Toast.LENGTH_LONG).show();
}
}


layout/activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp"
android:orientation="vertical"
tools:context="com.blogspot.android_er.androidgetlastlocation.MainActivity">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://android-er.blogspot.com/"
android:textStyle="bold" />

<Button
android:id="@+id/getlastlocation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Get my last location"/>

<TextView
android:id="@+id/lastlocation"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>


Permission:
Add uses-permission of ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION in your AndroidManifest.xml. In this example, I use ACCESS_FINE_LOCATION. (Read remark below about getLastLocation() return null)


remark: getLastLocation() return null!
- When run on real device, ASUS Zenfone 2 running Android 5.0:
According to Android Developers - Getting the Last Known Location, you can add permission of ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION. But in my trial, if add permission of ACCESS_COARSE_LOCATION, getLastLocation() return null mostly, around 2 success in more than 30 try. if add permission of ACCESS_FINE_LOCATION, it almost success every time.


Next:
- Requesting Permissions of Manifest.permission.ACCESS_FINE_LOCATION at Run Time

Related:
- Request Location Updates with LocationListener.onLocationChanged()

Add Google Play Services to Android Studio project

To add Google Play Services to Android Studio project, make sure Google Play services SDK is installed.


Open Project Structure to add dependencies of compile 'com.google.android.gms:play-services:8.4.0' to app/build.gradle.

To open Project Structure:
- Click File - Project Structure, or
- Right click your App, select Open Module Setting..., or
- With your App selected, press F4.

Follow the video to add 'com.google.android.gms:play-services:x.x.x' to your module.


After finished,  dependencies of compile 'com.google.android.gms:play-services:8.4.0' will be added to app/build.gradle.