4

I have a Fragment in which I want to show current location of user(device). I use Google Map Android API v2. How get current latitude and longitude of device?

Here below you can see code that I used. Unfortunately app works wrong, not as i expected. It just show map but there is no marker that i set and no current location. Can anyone check it and fix it? Whats wrong? Thanks for any help!

EDIT:

MainFragment.java

public class MainFragment extends Fragment{

    private SupportMapFragment mSupportMapFragment;
    private GoogleMap mGoogleMap;

    public BroadcastReceiver receiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {

        Bundle extras = intent.getExtras();
        LatLng temp = new LatLng(extras.getDouble("Latitude"),extras.getDouble("Longitude"));
    }
    };

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        FragmentManager mFragmentManager = getChildFragmentManager();
        mSupportMapFragment = (SupportMapFragment) mFragmentManager.findFragmentById(R.id.map_container);
        if (mSupportMapFragment == null) {
            mSupportMapFragment = SupportMapFragment.newInstance();
            mFragmentManager.beginTransaction().replace(R.id.map_container, mSupportMapFragment).commit();
        }

        //Broadcast/ Filter
        IntentFilter filter = new IntentFilter();
        filter.addAction(LocationService.BROADCAST_ACTION);
        getActivity().registerReceiver(receiver, filter);
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
           //Start service
           getActivity().startService(new Intent(getActivity(),LocationService.class));
    }

    @Override
    public void onResume(){
         receiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {

            Log.d(TAG, "BroadcastReceiver works!");

            Bundle extras = intent.getExtras();
            final LatLng temp = new LatLng(extras.getDouble("Latitude"),extras.getDouble("Longitude"));

            if (mGoogleMap != null) {
                mGoogleMap = mSupportMapFragment.getMap();
                mGoogleMap.addMarker(new MarkerOptions().position(temp).title("Marker").snippet("Location"));
            }
            try {
                CameraUpdate center = CameraUpdateFactory.newLatLng(temp);
                CameraUpdate zoom = CameraUpdateFactory.zoomTo(15f);
                mGoogleMap.moveCamera(center);
                mGoogleMap.animateCamera(zoom);
            }catch (NumberFormatException e) {
                //Some code here for exception
            }
        }
    };
    }

    @Override
    public void onDetach() {
        super.onDetach();
        try {
            Field childFragmentManager = Fragment.class.getDeclaredField("mChildFragmentManager");
            childFragmentManager.setAccessible(true);
            childFragmentManager.set(this, null);
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }
}

fragment_main.xml

<RelativeLayout
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:id="@+id/map_container">

       <!-- The map fragments will go here -->
</RelativeLayout>
Nurzhan Nogerbek
  • 4,806
  • 16
  • 87
  • 193
  • Can you add your error log? – Muthu Feb 08 '15 at 18:07
  • @Muthu I tested it in real device. I tested with latitude and longitude values which i just wrote and zome it so in that case it worked. I also tried to test in emulator which have Google APIs but there was error with memory. – Nurzhan Nogerbek Feb 08 '15 at 19:48
  • Hello @Muthu I edited my post. Now I just see map and it didnt show marker and current location. Please can you check code of the post again and say whats wrong? Thanks and have a nice day! – Nurzhan Nogerbek Feb 09 '15 at 09:02
  • if you want I could share my working Location service code. – Muthu Feb 09 '15 at 09:26
  • I think it will be usefull for me if you will give me your example @Muthu. – Nurzhan Nogerbek Feb 09 '15 at 09:43

4 Answers4

1

This information, and more, is available in the Location object that your app can retrieve from the fused location provider: https://developer.android.com/training/location/retrieve-current.html.

Marian Paździoch
  • 8,813
  • 10
  • 58
  • 103
  • Is GoogleApiClient workable in Fragment? As a matter of fact I tried to use it too but app crashed too. – Nurzhan Nogerbek Feb 08 '15 at 19:03
  • Hello Marian Paździoch! I edited my post with the help of information in that sourse which you gave me. Now I just see map and it didnt show marker and current location. Please can you check code of the post again and say whats wrong? Thanks and have a nice day! – Nurzhan Nogerbek Feb 09 '15 at 09:00
1

Note that getLastKnownLocation can return null if no recently-acquired location is available. You should check the result from this method call before attempting to extract the latitude/longitude. Obviously, if the result is null, requesting either the latitude or longitude will result in a NullPointerException.

stkent
  • 19,772
  • 14
  • 85
  • 111
  • hello! I tried to create separate service class and implements it with LocationListener and I had such think as you said. Values of latitude/longitude was 0/0. I can show you that class if you want. Do you have any workable example? – Nurzhan Nogerbek Feb 08 '15 at 19:59
  • Hello @stkent I edited my post with the help of information in that sourse which you gave me. Now I just see map and it didnt show marker and current location. Please can you check code of the post again and say whats wrong? Thanks and have a nice day! – Nurzhan Nogerbek Feb 09 '15 at 09:01
  • This line is problematic: `if(mLocation !=null & mGoogleMap == null){`. You don't want to check that `mGoogleMap` is null every single time you receive a location update. Break this out into two separate if statements (with the check on `mGoogleMap` first). Does that make sense? – stkent Feb 09 '15 at 13:33
  • So how to fix it? Do you have any ideas @stkent ? – Nurzhan Nogerbek Feb 09 '15 at 14:29
  • Yep, as I said, you should be checking mGoogleMap for null separately from checking mLocation for null. – stkent Feb 09 '15 at 15:20
  • Where about now? Can you check my code again? Its just show map again. I think I called showLocation method in onLocationChanged in wrong way =( – Nurzhan Nogerbek Feb 09 '15 at 15:43
1

This my current working code which is a service used to send location via Broadcast.

package maps.custom.com.googlemapsapi;

import android.app.IntentService;
import android.app.Notification;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
import android.hardware.GeomagneticField;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import android.widget.Toast;
import android.app.Service;

import com.google.android.gms.maps.model.LatLng;

import java.util.ArrayList;
import java.util.List;
import maps.custom.com.googlemapsapi.support.CNotificationBuilder;

/**
 * Created by hackers on 7/12/14.
 */
public class LocationService extends Service
{
    public static final String BROADCAST_ACTION = "com.location.service.location";
    public static final long DEFAULT_DELAY=1000;
    private static final int TWO_MINUTES = 1000 * 60 * 2;
    public LocationManager locationManager;
    public MyLocationListener listener;
    public Location previousBestLocation = null;

    Intent intent;
    int counter = 0;

    @Override
    public void onCreate()
    {
        super.onCreate();
        Log.i("Service","create");
        intent = new Intent(BROADCAST_ACTION);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i("Service","started");
        locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        listener = new MyLocationListener();
        locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 3*DEFAULT_DELAY, 0, listener); //get updates in every 3 seconds
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 3*DEFAULT_DELAY, 0, listener); //get updates in every 3 seconds
        return super.onStartCommand(intent, flags, startId);
    }



    @Override
    public IBinder onBind(Intent intent)
    {
        return null;
    }

    protected boolean isBetterLocation(Location location, Location currentBestLocation) {
        if (currentBestLocation == null) {
            // A new location is always better than no location
            return true;
        }

        // Check whether the new location fix is newer or older
        long timeDelta = location.getTime() - currentBestLocation.getTime();
        boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
        boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
        boolean isNewer = timeDelta > 0;

        // If it's been more than two minutes since the current location, use the new location
        // because the user has likely moved
        if (isSignificantlyNewer) {
            return true;
            // If the new location is more than two minutes older, it must be worse
        } else if (isSignificantlyOlder) {
            return false;
        }

        // Check whether the new location fix is more or less accurate
        int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
        boolean isLessAccurate = accuracyDelta > 0;
        boolean isMoreAccurate = accuracyDelta < 0;
        boolean isSignificantlyLessAccurate = accuracyDelta > 200;

        // Check if the old and new location are from the same provider
        boolean isFromSameProvider = isSameProvider(location.getProvider(),
                currentBestLocation.getProvider());

        // Determine location quality using a combination of timeliness and accuracy
        if (isMoreAccurate) {
            return true;
        } else if (isNewer && !isLessAccurate) {
            return true;
        } else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
            return true;
        }
        return false;
    }



    /** Checks whether two providers are the same */
    private boolean isSameProvider(String provider1, String provider2) {
        if (provider1 == null) {
            return provider2 == null;
        }
        return provider1.equals(provider2);
    }



    @Override
    public void onDestroy() {
        // handler.removeCallbacks(sendUpdatesToUI);
        super.onDestroy();
        Log.v("STOP_SERVICE", "DONE");
        locationManager.removeUpdates(listener);
    }

    public static Thread performOnBackgroundThread(final Runnable runnable) {
        final Thread t = new Thread() {
            @Override
            public void run() {
                try {
                    runnable.run();
                } finally {

                }
            }
        };
        t.start();
        return t;
    }


    GeomagneticField geoField;
    float heading;

    public class MyLocationListener implements LocationListener
    {


        public void onLocationChanged(final Location loc)
        {
            Log.i("**************************************", "Location changed");
            if(isBetterLocation(loc, previousBestLocation)) {
                loc.getLatitude();
                loc.getLongitude();

                intent.putExtra("Latitude", loc.getLatitude());
                intent.putExtra("Longitude", loc.getLongitude());
                intent.putExtra("Provider", loc.getProvider());
                intent.putExtra("Accuracy",  loc.getAccuracy());
                intent.putExtra("Speed",loc.getSpeed());
                sendBroadcast(intent);
        }

        public void onProviderDisabled(String provider)
        {
            Toast.makeText(getApplicationContext(), "Gps Disabled", Toast.LENGTH_SHORT).show();
        }


        public void onProviderEnabled(String provider)
        {
            Toast.makeText( getApplicationContext(), "Gps Enabled", Toast.LENGTH_SHORT).show();
        }


        public void onStatusChanged(String provider, int status, Bundle extras)
        {

        }

    }
}

You need to start service by following code

Intent locationservice= new Intent(this,LocationService.class);
startService(locationservice);

to receive Broadcast

  BroadcastReceiver receiver = new BroadcastReceiver() {

                @Override
                public void onReceive(Context context, Intent intent) {

                    Bundle extras = intent.getExtras();
                    LatLng temp = new LatLng(extras.getDouble("Latitude"),extras.getDouble("Longitude"));
    }
    }

to Register Broadcast Recever.

IntentFilter filter = new IntentFilter();
    filter.addAction(LocationService.BROADCAST_ACTION);
    registerReceiver(receiver, filter); 

Using service consumes power stop service when not in use.

Update on your Code

public class MainFragment extends Fragment{

    private SupportMapFragment mSupportMapFragment;
    private GoogleMap mGoogleMap;

    public BroadcastReceiver receiver=null;
    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);


    receiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {

        Bundle extras = intent.getExtras();
        final LatLng temp = new LatLng(extras.getDouble("Latitude"),extras.getDouble("Longitude"));
           if (mGoogleMap != null) {
      mGoogleMap.addMarker(new MarkerOptions().position(temp).title("Marker").snippet("Location"));

        try {
            CameraUpdate center = CameraUpdateFactory.newLatLng(temp);
            CameraUpdate zoom = CameraUpdateFactory.zoomTo(15f);
            mGoogleMap.moveCamera(center);
            mGoogleMap.animateCamera(zoom);
        }catch (NumberFormatException e) {
            //Some code here for exception
        }
           }
    }
    };
        FragmentManager mFragmentManager = getChildFragmentManager();
        mSupportMapFragment = (SupportMapFragment) mFragmentManager.findFragmentById(R.id.map_container);
        if (mSupportMapFragment == null) {
            mSupportMapFragment = SupportMapFragment.newInstance();
            mFragmentManager.beginTransaction().replace(R.id.map_container, mSupportMapFragment).commit();
        }


    }

    @Override
    public void onResume(){
         if (mGoogleMap == null) {
        mGoogleMap = mSupportMapFragment.getMap();
        mGoogleMap.getUiSettings().setMyLocationButtonEnabled(false);
        mGoogleMap.setMyLocationEnabled(true);

    }

        //Broadcast/ Filter
        IntentFilter filter = new IntentFilter();
        filter.addAction(LocationService.BROADCAST_ACTION);
        getActivity().registerReceiver(receiver, filter);
    }

    @Override
    public void onDetach() {
        super.onDetach();
        try {
            Field childFragmentManager = Fragment.class.getDeclaredField("mChildFragmentManager");
            childFragmentManager.setAccessible(true);
            childFragmentManager.set(this, null);
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }
}
Muthu
  • 1,022
  • 1
  • 7
  • 17
  • Ohhh its just show map without nothing. So sad =( I tried next too: I think its better to call receiver in onResume method and removed it to that method but the same result. Do you have any ideas now? Anyway thanks! You spend time to me. – Nurzhan Nogerbek Feb 10 '15 at 09:42
  • Do one thing Can you log the lat&long in BradCast recever? if your getting lat & lang we can find a way else that means service is not running you need to start the service. – Muthu Feb 10 '15 at 09:47
  • Hello Muthu! I thought about that too. Is it possible to remove Intent mLocationService= new Intent(this,LocationService.class); startService(mLocationService); to Fragment cause now its in my MainActivity... – Nurzhan Nogerbek Feb 10 '15 at 13:36
  • @NurzhanNogerbek any luck? – Muthu Feb 10 '15 at 14:30
  • I updated my post. Can you check it? I removed Intent to Fragment and added Log.d to Broadcast. Unfortunately the same result and app opened in emulator without Google APIs. It mean that BroadcastService dont work. But why? =( – Nurzhan Nogerbek Feb 10 '15 at 14:35
  • @NurzhanNogerbek move getActivity().registerReceiver(receiver, filter); after receiver diclaration and check! – Muthu Feb 10 '15 at 14:44
  • @NurzhanNogerbek are You using Emulator to test the output? – Muthu Feb 10 '15 at 15:23
  • Comments are not for extended discussion; this conversation has been [moved to chat](http://chat.stackoverflow.com/rooms/70641/discussion-on-answer-by-muthu-how-to-get-latitude-and-longitude-of-current-locat). – Taryn Feb 10 '15 at 15:24
  • You mean to put getActivity().registerReceiver(receiver, filter); after public BroadcastReceiver receiver = null; ? I try to test it in everything that I have (Emulator/Real device). =) – Nurzhan Nogerbek Feb 10 '15 at 15:34
  • Yes! try them in Real device. – Muthu Feb 10 '15 at 16:27
  • did you get the log from broadcast recever? else check the log for any errors and warnings. – Muthu Feb 11 '15 at 06:05
1

You can try this out from my current project -

Using location manager to get last known location:

public void onLocationChanged(Location location) {
    TextView locationTv = (TextView) findViewById(R.id.latlongLocation);
    double latitude = location.getLatitude();
    double longitude = location.getLongitude();
    LatLng latLng = new LatLng(latitude, longitude);
    googleMap.addMarker(new MarkerOptions().position(latLng));
    googleMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
    googleMap.animateCamera(CameraUpdateFactory.zoomTo(21));
    locationTv.setText("Latitude:" + latitude + ", Longitude:" + longitude);
}

I'm calling this method to get the last location from my phone.

user3152131
  • 543
  • 3
  • 7
  • 18