This is my first post in stackoverflow so please dont hate me if I say something wrong!
I am trying to adapt this tutorial https://developers.google.com/maps/documentation/android-api/current-place-tutorial to work on my fragment and with PermisionDispatcher. However, I am getting checkPermision error and I dont understand why.
I have checked this answer trying to add marshmallow permissions using "Permissions Dispatcher" however, I still cant get that right..
This is my fragment code:
import android.Manifest;
import android.app.FragmentManager;
import android.content.Context;
import android.location.Location;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapFragment;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import permissions.dispatcher.NeedsPermission;
import permissions.dispatcher.OnNeverAskAgain;
import permissions.dispatcher.OnPermissionDenied;
import permissions.dispatcher.OnShowRationale;
import permissions.dispatcher.PermissionRequest;
import permissions.dispatcher.RuntimePermissions;
import static android.content.ContentValues.TAG;
/**
* Created by Daumantas on 2017-05-25.
*/
#RuntimePermissions
public class AddPlacesFragment extends Fragment implements OnMapReadyCallback, GoogleApiClient.OnConnectionFailedListener, GoogleApiClient.ConnectionCallbacks {
Context mContext;
private GoogleApiClient mGoogleApiClient;
private GoogleMap mMap;
private boolean mLocationPermissionGranted = false;
private Location mLastKnownLocation = null;
private CameraPosition mCameraPosition = null;
private LatLng mDefaultLocation = new LatLng(40.76793169992044,
-73.98180484771729);
private float DEFAULT_ZOOM = 10;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
mGoogleApiClient = new GoogleApiClient.Builder(getActivity())
.enableAutoManage(getActivity(),
this)
.addConnectionCallbacks(this)
.addApi(LocationServices.API)
//.addApi(Places.GEO_DATA_API)
//.addApi(Places.PLACE_DETECTION_API)
.build();
mGoogleApiClient.connect();
return inflater.inflate(R.layout.add_places_fragment, container, false);
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mContext = getContext();
FragmentManager fragment = getActivity().getFragmentManager();
MapFragment mf = (MapFragment) fragment.findFragmentById(R.id.map);
mf.getMapAsync(this);
}
#Override
public void onMapReady(final GoogleMap map) {
mMap = map;
// Do other setup activities here too, as described elsewhere in this tutorial.
AddPlacesFragmentPermissionsDispatcher.updateLocationUIWithCheck(this); //UpdateLocationUI
// Turn on the My Location layer and the related control on the map.
// Get the current location of the device and set the position of the map.
//getDeviceLocation();
AddPlacesFragmentPermissionsDispatcher.getDeviceLocationWithCheck(this);
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
Log.d("CONNECTION CALLBACK","failed");
}
#Override
public void onConnected(#Nullable Bundle bundle) {
Log.d("CONNECTION CALLBACK","connected");
}
#Override
public void onConnectionSuspended(int i) {
Log.d("CONNECTION CALLBACK","suspended");
}
#NeedsPermission({Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION})
void updateLocationUI() {
if (mMap == null) {
Log.d("LOCATION","MAPS ARE NULL");
}else{
Log.d("LOCATION","updateLocationUI");
//noinspection MissingPermission
mMap.setMyLocationEnabled(true);
mLocationPermissionGranted = true;
mMap.getUiSettings().setMyLocationButtonEnabled(true);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
AddPlacesFragmentPermissionsDispatcher.onRequestPermissionsResult(this, requestCode, grantResults);
}
#OnShowRationale({Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION})
void updateLocationUIOnShowRationale(final PermissionRequest request) {
}
#OnPermissionDenied({Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION})
void updateLocationUIOnPermissionDenied() {
mMap.setMyLocationEnabled(false);
mMap.getUiSettings().setMyLocationButtonEnabled(false);
}
#OnNeverAskAgain({Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION})
void updateLocationUIOnNeverAskAgain() {
}
#NeedsPermission({Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION})
void getDeviceLocation() {
mLastKnownLocation = LocationServices.FusedLocationApi
.getLastLocation(mGoogleApiClient);
// Set the map's camera position to the current location of the device.
if (mCameraPosition != null) {
mMap.moveCamera(CameraUpdateFactory.newCameraPosition(mCameraPosition));
} else if (mLastKnownLocation != null) {
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(
new LatLng(mLastKnownLocation.getLatitude(),
mLastKnownLocation.getLongitude()), DEFAULT_ZOOM));
} else {
Log.d(TAG, "Current location is null. Using defaults.");
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(mDefaultLocation, DEFAULT_ZOOM));
mMap.getUiSettings().setMyLocationButtonEnabled(false);
}
}
}
EDIT
So I have made some changes as you have suggested and I don't longer get the error in
SetMyLocationEnabled(true)
(even though I sometimes get it if I move it around in the method)
now I have advanced a bit in the tutorial and I have same problems.. Now I get an error in
mLastKnownLocation = LocationServices.FusedLocationApi
.getLastLocation(mGoogleApiClient);
and dont really know what do to. The code compiles, but running it on emulator just zooms in on default location and running it on my phone the app crashes
EDIT
Runned it on my phone and found an exception in stacktrace (the app didn't crash this time but showed only world map, without any sign of my location or zooming onto the default location)
06-19 23:10:33.990 3728-6926/? D/LocationManagerService: request 3ab885c
fused Request[ACCURACY_BLOCK fused requested=+30m0s0ms fastest=+30m0s0ms] from com.samsung.voiceserviceplatform(10039)
06-19 23:10:34.083 3728-6926/? D/LocationManagerService: provider request: fused ProviderRequest[ON interval=+30m0s0ms]
06-19 23:10:34.084 4511-4511/? D/FusedRequestManager_FLP: manageLocationRequest, new fused request from com.samsung.voiceserviceplatform with 3ab885c , interval = 1800000 through LocationManagerService
06-19 23:10:34.126 4707-4936/? E/LocationClientHelper: exception when setting module id
java.lang.IllegalStateException: Unable to get current module info in ModuleManager created with non-module Context
at com.google.android.chimera.config.ModuleManager.getCurrentModule(:com.google.android.gms:1)
at tpn.a(:com.google.android.gms:17)
at tpr.b(:com.google.android.gms:13)
at too.a(:com.google.android.gms:4)
at kit.b(:com.google.android.gms:3)
at kjv.b(:com.google.android.gms:14)
at kks.b(:com.google.android.gms:7)
at kkk.b(:com.google.android.gms:25)
at txt.a(:com.google.android.gms:6)
at txs.b(:com.google.android.gms:1)
at txs.a(:com.google.android.gms:1)
at txs.a(:com.google.android.gms:15)
at tyc.a(:com.google.android.gms:8)
at ajuo.handleMessage(:com.google.android.gms:21)
at android.os.Handler.dispatchMessage(Handler.java:102)
at akwg.dispatchMessage(:com.google.android.gms:7)
at android.os.Looper.loop(Looper.java:154)
at android.os.HandlerThread.run(HandlerThread.java:61)
06-19 23:10:37.578 4707-27455/? W/ctxmgr: [AclManager]No 2 for (accnt=account#1348010355#, com.google.android.gms(10018):UserLocationProducer, vrsn=11055000, 0, 3pPkg = null , 3pMdlId = null , pid = 4707). Was: 2 for 1, account#1348010355#
06-19 23:10:37.580 4707-27455/? W/ctxmgr: [AclManager]No 2 for (accnt=account#-1563429706#, com.google.android.gms(10018):UserLocationProducer, vrsn=11055000, 0, 3pPkg = null , 3pMdlId = null , pid = 4707). Was: 2 for 1, account#-1563429706#
06-19 23:10:43.903 3728-4583/? D/LocationManagerService: getLastLocation: Request[POWER_NONE passive fastest=0 num=1]
06-19 23:10:43.968 3728-6921/? D/LocationManagerService: getLastLocation: Request[POWER_NONE passive fastest=0 num=1]
Thank you or helping me..
The app is getting the map asynchronously, so even though it is asking permission right after calling mf.getMapAsync(this), the app could load the map and can call onMapReady, which calls mMap.setMyLocationEnabled(true) through your method, before the user has a chance to allow the permission. I would suggest the following:
#Override
public void onMapReady(final GoogleMap map) {
mMap = map;
//Now that you have the map, request permission here.
getPermisions();
}
This is how you should handle this, since you only request the location once the map is loaded.
Related
I have written code for getting current location in android project. But it is not picking my location automatically and showing marker somewhere in the world although I'm sitting in Pakistan.
Map Activity code is here
package com.example.uber;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.FragmentActivity;
import android.Manifest;
import android.content.pm.PackageManager;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import java.io.IOException;
import java.util.List;
import java.util.Locale;
public class MapsActivity2 extends FragmentActivity implements OnMapReadyCallback {
private GoogleMap mMap;
private LocationManager locationManager;
private LocationListener locationListener;
#RequiresApi(api = Build.VERSION_CODES.M)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps2);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
/**
* Manipulates the map once available.
* This callback is triggered when the map is ready to be used.
* This is where we can add markers or lines, add listeners or move the camera. In this case,
* we just add a marker near Sydney, Australia.
* If Google Play services is not installed on the device, the user will be prompted to install
* it inside the SupportMapFragment. This method will only be triggered once the user has
* installed Google Play services and returned to the app.
*/
#RequiresApi(api = Build.VERSION_CODES.M)
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
locationManager = (LocationManager) this.getSystemService(LOCATION_SERVICE);
locationListener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
Log.d("Location", location.toString());
mMap.clear();
// Add a marker in Sydney and move the camera
LatLng newLocation = new LatLng(location.getLatitude(),location.getLongitude());
//LatLng sydney = new LatLng(-34, 151);
mMap.addMarker(new MarkerOptions().position(newLocation).title("Marker in Sydney"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(newLocation));
Geocoder geocoder = new Geocoder(getApplicationContext(), Locale.getDefault());
try{
List<Address> addressList = geocoder.getFromLocation(location.getLatitude(),location.getLongitude(),1);
if(addressList != null && addressList.size()>0){
Log.d("Address",addressList.get(0).toString());
}else {
Log.d("Address","Couldn't find Address");
}
}catch (IOException e){
e.printStackTrace();
}
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
};
if (Build.VERSION.SDK_INT < 23) {
if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// Activity#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 Activity#requestPermissions for more details.
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1);
// return;
}
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
} else {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// Ask for permission
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1);
} else {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
}
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
if (ContextCompat.checkSelfPermission(this,Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED){
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
}
}
}
}
Manifiest Permisions
I have given following permission
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission>
<uses-permission android:name="android.permission.INTERNET" />
My actual location is
31.175669, 74.104891
I have manually set my location in extended control of emulator.as shown in figure. But I want's that my code pick my location dynamically please help me
Android emulator image with extended control
I have the same issue. When you test your app in AVD map will show google corporation as your place. But if your code is correct, when you test the app in your device, you will get your current location correctly.
Your Android emulator doesn't use your real location. Most of the times the location is set in the Emulator settings, like in Android Studio.
Use a real device for testing, or open the settings to change your location.
You can find more information about the emulator here:
https://developer.android.com/studio/run/emulator
This is the Code for my MapActivity. It is made to just track user location but it shows location only when there is movement but when i added code to show current location on app launch, it started crashing.
import android.*;
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.FragmentActivity;
import android.os.Bundle;
import android.support.v4.content.ContextCompat;
import android.widget.Toast;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {
private GoogleMap mMap;
LocationManager locationManager;
LocationListener locationListener;
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == 1) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
{
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
}
}
}
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
/**
* Manipulates the map once available.
* This callback is triggered when the map is ready to be used.
* This is where we can add markers or lines, add listeners or move the camera. In this case,
* we just add a marker near Sydney, Australia.
* If Google Play services is not installed on the device, the user will be prompted to install
* it inside the SupportMapFragment. This method will only be triggered once the user has
* installed Google Play services and returned to the app.
*/
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
locationListener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
LatLng userLocation = new LatLng(location.getLatitude(), location.getLongitude());
mMap.clear();
mMap.addMarker(new MarkerOptions().position(userLocation).title("Your Location"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(userLocation));
}
#Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
#Override
public void onProviderEnabled(String s) {
}
#Override
public void onProviderDisabled(String s) {
}
};
if (Build.VERSION.SDK_INT < 23) {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
} else {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1);
} else {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
Location lastKnownLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
LatLng userLocation = new LatLng(lastKnownLocation.getLatitude(), lastKnownLocation.getLongitude());
mMap.clear();
mMap.addMarker(new MarkerOptions().position(userLocation).title("Your Location"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(userLocation));
}
}
}
}
The issue is , i was able to get location while changing and sending location from Emulator but when I add the else part to show the current location the app is crashing.
This is the error am getting while the app is launched.
2019-03-06 01:50:39.000 24094-24094/com.example.userlocationdemo E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.userlocationdemo, PID: 24094
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.userlocationdemo/com.example.userlocationdemo.MapsActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'double android.location.Location.getLatitude()' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2678)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2743)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1490)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6165)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:888)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:778)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'double android.location.Location.getLatitude()' on a null object reference
at com.example.userlocationdemo.MapsActivity.onCreate(MapsActivity.java:94)
at android.app.Activity.performCreate(Activity.java:6687)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1140)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2631)
You are trying to get get latitude from null object of location in the oncreate method of MapsActivity at line 94 as mentioned in the log print
android.location.Location.getLatitude()' on a null object reference at com.example.userlocationdemo.MapsActivity.onCreate(MapsActivity.java:94)
I am trying to display a users current location using the google map activity. when the activity is launched the google map is displayed as it should be, but there is no marker and the users current location is not gotten. The map displays a view over many different countries. After putting Toast messages in every method i realise onLocationChange is not being called, as no Toast appears for this method.
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.FragmentActivity;
import android.os.Bundle;
import android.support.v4.content.ContextCompat;
import android.widget.Toast;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
public class MapsActivity extends FragmentActivity implements
OnMapReadyCallback,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
LocationListener
{
private GoogleMap mMap;
private GoogleApiClient googleApiClient;
private LocationRequest locationRequest;
private Location lastKnownLocation;
private Marker userLocationMarker;
private static final int REQUEST_USER_LOCATION_CODE = 99;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
if(Build.VERSION.SDK_INT > Build.VERSION_CODES.M)
{
checkPermissions();
}
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
#Override
public void onMapReady(GoogleMap googleMap)
{
// Get the users current location
mMap = googleMap;
// Check that the access permissions are granted by the device
if(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED)
{
buildGoogleApiClient();
mMap.setMyLocationEnabled(true);
}
}
protected synchronized void buildGoogleApiClient()
{
googleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
googleApiClient.connect();
}
#Override
public void onLocationChanged(Location location)
{
lastKnownLocation = location;
if(userLocationMarker != null)
{
// Remove that marker as if marker already exists it is likely wrong
userLocationMarker.remove();
}
// Get users longitude and latitude
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
// Display Marker on users current location
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(latLng);
markerOptions.title("You are Here");
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_VIOLET));
userLocationMarker = mMap.addMarker(markerOptions);
//Focus map on users current location
mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
mMap.animateCamera(CameraUpdateFactory.zoomBy(1));
if(googleApiClient != null)
{
LocationServices.FusedLocationApi.removeLocationUpdates(googleApiClient, this);
}
}
#Override
public void onConnected(#Nullable Bundle bundle)
{
// Update map while user is currently moving
locationRequest= new LocationRequest();
locationRequest.setInterval(1100);
locationRequest.setFastestInterval(1100);
locationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
if(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED)
{
LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this);
}
}
#Override
public void onConnectionSuspended(int i)
{
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult)
{
}
private boolean checkPermissions()
{
if(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED)
{
if(ActivityCompat.shouldShowRequestPermissionRationale(this,Manifest.permission.ACCESS_FINE_LOCATION))
{
ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_USER_LOCATION_CODE);
}
else
{
ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_USER_LOCATION_CODE);
}
return false;
}
else
{
return true;
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults)
{
switch(requestCode)
{
case REQUEST_USER_LOCATION_CODE:
if(grantResults.length > 0 && grantResults[0]== PackageManager.PERMISSION_GRANTED)
{
if(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED)
{
if(googleApiClient == null)
{
buildGoogleApiClient();
}
mMap.setMyLocationEnabled(true);
}
}
else
{
Toast.makeText(this, "Permission Denied", Toast.LENGTH_LONG).show();
}
}
}
}
Permissions
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
In order to display user location you should add:
mMap.setMyLocationEnabled(true);
on your onMapReady callback, there's no need to use a LocationRequest.
Be aware that you'll be able to get user position after your app has achieved location permissions. To do so you can follow this guide or use a third party library like easy permissions
After hours of research the answer was in front of me, the location settings were disabled in the phone settings. Witting this so the next person inst as stupid as me.
I am trying to make an app that can track the GPS location of my bike. To start off, I've been trying to read the GPS location of my own phone. My app keeps crashing whenever I try to launch the fragment below. I have put in a Google API key for the App and placed the line " " in my manifest file. What are some good ways to debug this issue? I am new to Android Studio so I would love to hear any sort of feedback.
//FindBikeFragment.java
import android.Manifest;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
/**
* A simple {#link Fragment} subclass.
*/
public class FindBikeFragment extends Fragment implements OnMapReadyCallback {
/**
* GoogleMaps object
*/
private GoogleMap mMap;
/**
* Provides the entry point to the Fused Location Provider API.
*/
private FusedLocationProviderClient mFusedLocationClient;
/**
* Represents a geographical location.
*/
protected Location mLastLocation;
public FindBikeFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.fragment_find_bike, container, false);
return v;
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
SupportMapFragment mapFragment = (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.map1);
mapFragment.getMapAsync(this);
}
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(getActivity());
if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(getContext(), 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.
mLastLocation = mFusedLocationClient.getLastLocation().getResult();
LatLng pp = new LatLng(mLastLocation.getLatitude(), mLastLocation.getLongitude());
MarkerOptions option = new MarkerOptions();
option.position(pp).title("Some City");
mMap.addMarker(option);
mMap.moveCamera(CameraUpdateFactory.newLatLng(pp));
return;
}
}
}
You need to use GoogleApiClient for FusedLocationApi.Here is a working code
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();}
return;
}
Call buildGoogleApiClient method on onCreate().And implement required interfaces. GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener,
LocationListener
#Override
public void onConnected(#Nullable Bundle bundle) {
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.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.
return;
}
Location mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
mGoogleApiClient);
if (mLastLocation != null) {
//place marker at current position
// Log.e("x", mLastLocation.getLongitude() + "");
//Log.e("y", mLastLocation.getLatitude() + "");
currentLocation = mLastLocation;
}
LocationRequest mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(5000); //5 seconds
mLocationRequest.setFastestInterval(5000); //3 seconds
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
mLocationRequest.setSmallestDisplacement(50F); //1/10 meter
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
#Override
public void onLocationChanged(Location location) {
currentLocation = location;
}
And define this parameters
private GoogleApiClient mGoogleApiClient;
private Location currentLocation;
Btw if you are using Android 6.x or 7.x version. You need to grant permission at runtime.Check here
#FnR you're talking about the old version of the fusedlocationapi, a new one came out with the version 11 of the playservices, it's supposed to be much simpler, look here : https://android-developers.googleblog.com/2017/06/reduce-friction-with-new-location-apis.html
I got the same issue there seems to be a conflict between the new fusedlocationapi and the map activities.
I'm able to get my current location with this new technique in an empty activity with no map but the exact same code used in a map activity returns a null result.
Google didn't even provide any example of this with a map, which is crazy since getting the location is 99% of the time coupled with a map
i'm working on an app that requires getting current location on many activities , to make things easier i made a class that incorporates all of the requirements and get me the location through the Method get location. Unfortunately i kept getting numerous errors , here is the Activity Code , and the Class as well as the Error Message.
This Is The Activity
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
public class Acceuil extends FragmentActivity implements OnMapReadyCallback {
private GoogleMap mMap;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_acceuil);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
/**
* Manipulates the map once available.
* This callback is triggered when the map is ready to be used.
* This is where we can add markers or lines, add listeners or move the camera. In this case,
* we just add a marker near Sydney, Australia.
* If Google Play services is not installed on the device, the user will be prompted to install
* it inside the SupportMapFragment. This method will only be triggered once the user has
* installed Google Play services and returned to the app.
*/
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
Locate Obj = new Locate(getParent());
LatLng Loc=Obj.GetLocation();
// Add a Marker Containing Last Known Location Provided By The Main Fragment
LatLng Current = new LatLng(34.0132500,-6.8325500);
mMap.addMarker(new MarkerOptions().position(Current).title("Your Current Location"));
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(Current, 15));
}
}
This Is The Class
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
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.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.maps.model.LatLng;
/**
* Created by Otmane on 26/03/2016.
*/
public class Locate implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
private final static int Play_services_resolution_request = 1000;
private Location mLocation;
private Location UpdatedLocation;
private GoogleApiClient mGoogleApiClient;
private boolean mRequestingLocationUpdates = false;
private LocationRequest mLocationRequest;
private static int Update_Interval = 10000; // 10 Seconds
private static int Fastest_Interval = 5000; // 5 Seconds
private static int Displacement = 10; // 10 meters
private Context mContext;
private boolean toggleUpdate= false;
public Locate(Context context) {
this.mContext = context;
try {
buildGoogleApiClient();
}
catch (Exception e )
{
/*AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(mContext);
alertDialogBuilder.setMessage("Unable To Connect To Location Services");
alertDialogBuilder.show();*/
}
createLocationRequest();
GetLocation();
}
public void setUpdate(boolean State)
{
this.toggleUpdate=State;
}
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(mContext)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(Update_Interval);
mLocationRequest.setFastestInterval(Fastest_Interval);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setSmallestDisplacement(Displacement);
}
protected void StartLocationUpdates() {
if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(mContext, 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.
return;
}
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
protected void StopLocationUpdates() {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
public LatLng GetLocation() {
buildGoogleApiClient();
try{
if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(mContext, 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.*
LatLng Temp= new LatLng(0.0,0.0);
return Temp;
}
}
catch (Exception e)
{
//Toast.makeText(this,"Permissions Error",Toast.LENGTH_LONG).show();
}
mLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (mLocation!=null){
LatLng Current = new LatLng(mLocation.getLatitude(),mLocation.getLongitude());
return Current;
}
LatLng Current = new LatLng(34.0132500,-6.8325500);
return Current;
}
public void onConnected(#Nullable Bundle bundle) {
GetLocation();
if (toggleUpdate== true ){
StartLocationUpdates();
}
}
#Override
public void onConnectionSuspended(int i) {
mGoogleApiClient.connect();
}
public LatLng GetUpdatedLocation(LatLng Loc){
return Loc;
}
#Override
public void onLocationChanged(Location location) {
UpdatedLocation=location;
if (UpdatedLocation != null){
LatLng temp = new LatLng(UpdatedLocation.getLatitude(),UpdatedLocation.getLongitude());
GetUpdatedLocation(temp);
}
else
{
LatLng temp = new LatLng(0.0,0.0);
GetUpdatedLocation(temp);
}
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Toast.makeText(mContext,"Connection Failed",Toast.LENGTH_SHORT).show();
}
}
This is The Error Message
53:41.486 14944-14944/otmos.pfe E/AndroidRuntime: FATAL EXCEPTION: main
Process: otmos.pfe, PID: 14944
java.lang.NullPointerException: Attempt to invoke virtual method 'android.os.Looper android.content.Context.getMainLooper()' on a null object reference
at com.google.android.gms.common.api.GoogleApiClient$Builder.<init>(Unknown Source)
at otmos.pfe.Locate.buildGoogleApiClient(Locate.java:56)
at otmos.pfe.Locate.GetLocation(Locate.java:90)
at otmos.pfe.Locate.<init>(Locate.java:48)
at otmos.pfe.Acceuil.onMapReady(Acceuil.java:38)
at com.google.android.gms.maps.SupportMapFragment$zza$1.zza(Unknown Source)
at com.google.android.gms.maps.internal.zzo$zza.onTransact(Unknown Source)
at android.os.Binder.transact(Binder.java:387)
at com.google.android.gms.maps.internal.v$a$a.a(:com.google.android.gms.alldynamite:82)
at maps.ei.bu$6.run(Unknown Source)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
I think the problem can occur with any library you can find that use com.google.android.gms.
If you have references to com.google.android.gms in android/app/build.gradle.
Try giving the associated library a new version that you currently have installed.
I found the version number of the library I am using by navigating to [YOUR_ANDROID_SDK]/extras/google/m2repository/com/google/android/gms
Then find the library that might be causing you problems for example play-services-auth.
In there you will see all the versions. Apply the newest to your build.gradle.
compile 'com.google.android.gms:play-services:10.2.1'
Also add (It seems gcm is needed in GoogleApiClient Builder)
compile 'com.google.android.gms:play-services-gcm:10.2.1'