Android Location getBearing() always returns 0
Asked Answered
S

1

10

I've been trying to implement a feature for my Android app that gets the speed and direction of travel of the device, no matter where the device is pointed at. For example: If my Android device is pointed in the North direction and if I'm moving backwards in the South direction, it would return that I'm moving Southbound.

I've been looking around and I have came up with a possibility of using the Location's getBearing() method (Still, I do not know if that will solve my whole problem). When I invoke getBearing(), it always returns 0.0 for some reason. I have no idea why. Here is my code:

LocationManager lm;
@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_gcm);
    setUpUI(findViewById(R.id.LinearLayout1));
    isRegged = false;

    // GCM startup
    gcm = GoogleCloudMessaging.getInstance(this);
    context = getApplicationContext();

    gps = new GPSTracker(context);
    // gps.startListening(context);
    // gps.setGpsCall(this);

    /*
     * Variables to indicate location and device ID
     */
    TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);

    if (gps.getIsGPSTrackingEnabled())
    {
        longitude = Double.valueOf(gps.getLongitude()).toString();
        latitude = Double.valueOf(gps.getLatitude()).toString();
    }

    deviceID = telephonyManager.getDeviceId();

    mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);

    lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, (float) 0.0,
            this);
}

This is where I am getting the bearing.

@Override
public void onLocationChanged(Location currentLocation)
{
    float speed = 0;
    float speed_mph = 0;

    if (previousLocation != null)
    {
        float distance = currentLocation.distanceTo(previousLocation);

        // time taken (in seconds)
        float timeTaken = ((currentLocation.getTime() - previousLocation
                .getTime()) / 1000);

        // calculate speed
        if (timeTaken > 0)
        {
            speed = getAverageSpeed(distance, timeTaken);
            speed_mph = (float) (getAverageSpeed(distance, timeTaken) / 1.6);
        }

        if (speed >= 0)
        {
            info_text.setVisibility(View.VISIBLE);
            info_text_mph.setVisibility(View.VISIBLE);

            DecimalFormat df = new DecimalFormat("#.#");
            info_text.setText("Speed: " + df.format(speed) + " " + "km/h");
            info_text_mph.setText("  Speed: " + df.format(speed_mph) + " "
                    + "mph");

            if (speed >= 10 && lm.getProvider(LocationManager.GPS_PROVIDER).supportsBearing())
            {
                float degree = currentLocation.getBearing();

                direction_text.setVisibility(View.VISIBLE);

                Log.i(TAG, String.valueOf(degree));

                if (degree == 0 && degree < 45 || degree >= 315
                        && degree == 360)
                {
                    direction_text.setText("You are: Northbound");
                }

                if (degree >= 45 && degree < 90)
                {
                    direction_text.setText("You are: NorthEastbound");
                }

                if (degree >= 90 && degree < 135)
                {
                    direction_text.setText("You are: Eastbound");
                }

                if (degree >= 135 && degree < 180)
                {
                    direction_text.setText("You are: SouthEastbound");
                }

                if (degree >= 180 && degree < 225)
                {
                    direction_text.setText("You are: SouthWestbound");
                }

                if (degree >= 225 && degree < 270)
                {
                    direction_text.setText("You are: Westbound");
                }

                if (degree >= 270 && degree < 315)
                {
                    direction_text.setText("You are: NorthWestbound");
                }

            }

        }
    }
    previousLocation = currentLocation;

}

Thanks so much!

Seismograph answered 13/7, 2015 at 15:57 Comment(0)
P
6

getBearing() will return 0 if you are obtaining your data using LocationManager.NETWORK_PROVIDER because the signal/accuracy is too weak. Try setting the GPS provider to GPS and be sure to test it outside (GPS does not work indoors or in the middle of very tall buildings due to satellites not having direct communication)

To ensure the provider you have chosen supports getBearing() you can use the method from LocationProvider called supportsBearing () which returns true if the provider you have chosen supports the getBearing() call.

Lastly ensure that you have the ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permissions in your AndroidManifest.xml

Code as per my suggestions would be something like this:

LocationManager mlocManager =

(LocationManager)getSystemService(Context.LOCATION_SERVICE);

LocationListener mlocListener = new MyLocationListener();


mlocManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, 0, 0, mlocListener);

Resources: http://developer.android.com/reference/android/location/LocationManager.html http://developer.android.com/reference/android/location/LocationProvider.html http://www.firstdroid.com/2010/04/29/android-development-using-gps-to-get-current-location-2/

UPDATE: The answer was that the two points that were being used to calculate in getBearing() were too close and therefore giving an inaccurate result. To correct this, manually grab two GPS points and use the bearingTo() to see a more accurate result.

Prowess answered 13/7, 2015 at 16:33 Comment(13)
Thank you for your feedback and I apologize that I completely forgot to mention in my post that I am using GPS provider. I will update my code.Seismograph
And did you attempt the use of getBearing() while outside and in a location away from tall buildings or other objects which could prevent you from satellite communication?Prowess
Yes I did. I've tried testing that feature while driving around. Although the speed is pretty accurate (5-10 km off) the getBearing() always returns 0, which always returns "You are: Northbound" no matter which direction I go.Seismograph
And is the result of the supportsBearing() method true?Prowess
Yes it does. I've added in lm.getProvider(LocationManager.GPS_PROVIDER).supportsBearing()) into the if (speed >= 10) statement.Seismograph
Hmm, interesting. Bearings are calculated with two GPS points, so what is probably happening is the GPS points are so close to each other that it is unable do an accurate calculation. I would try manually grabbing two GPS points (within 10 seconds) and calculating using the bearingTo Method. This way you can ensure 1) You are getting two different GPS points 2) The calculation itself is working and its the GPS data that is incorrect. Similar to what is done here android-er.blogspot.com/2013/02/…Prowess
After using the bearingTo() method, the bearing doesn't always return 0 anymore! I have to further test if this is accurate when I am driving. However, it works. Thank you so much! Also, is there a reason why my getBearing() always returns random floating number every second? Is it possible that it is due to the minimum distance and minimum time of update for the LocationManager?Seismograph
Awesome! The getBearing() returns the degrees, but if the points are too close to each other than the numbers are going to be inaccurate(or "random").Prowess
Hello guys, Is there anyway to get accurate heading information for indoor environment? For example, iOS provides trueHeading using CoreLocation Framework. Is there anything like this in Android? My detailed question is here #32693924Tecumseh
@Matt Newbill do you know how to align a car marker along the street based on the bearing the car is moving? Here is my question. #35449769Terrapin
@Terrapin Did you try applying the answer here to your situation? Manually grabbing two points because the two you get are too close together, which gives you an inaccurate facing direction.Prowess
@Matt Newbill the bearing is returning a value, but I have hard time to rotate the car on the street. I set the anchor at (.5,5.) but that didn't help. My question is how do I trick it to think the front of the car should always face the direction the car is moving.Terrapin
@Terrapin Keep a variable of the old location or the location it was at 1 or 2 seconds ago and calculate the direction manually. If you do it every time it won't be accurate enough to provide the correct direction.Prowess

© 2022 - 2024 — McMap. All rights reserved.