Question

I would like to create an Android compass - based only on GPS. The device I am developing it for does not have any accelorometer or magnetic field sensor, that's why I have to rely on the android.location classes only.

So far, accessing the LocationManager to display current GPS coordinates works fine for me (see below). I am struggling on what's the best way to proceed. I was thinking about circuit angle calculation - using the current coordinate & geographic north coordinate as known values to calculate direction.

Can anyone advise if this approach makes sense or even share code?

Here's the code I got so far:

public class CompassActivity extends Activity implements LocationListener {


Compass myCompass;
private TextView mInfoText;
private LocationManager mLoc;

private static final Integer MINIMUM_UPDATE_INTERVAL = 5000; //update every 5s
private static final Integer MINIMUM_UPDATE_DISTANCE = 5; //update every 5m

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_compass);
    myCompass = (Compass)findViewById(R.id.mycompass);

    mInfoText = (TextView) findViewById(R.id.infotext);
    mLoc = (LocationManager) getSystemService(LOCATION_SERVICE);

}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.compass, menu);
    return true;
}

@Override
protected void onResume() {
    mLoc.requestLocationUpdates(LocationManager.GPS_PROVIDER, MINIMUM_UPDATE_INTERVAL, MINIMUM_UPDATE_DISTANCE, this);
    super.onResume();

}

@Override
protected void onPause() {
    mLoc.removeUpdates(this);
    super.onPause();
}

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

@Override
public void onLocationChanged(Location loc) { //display coordinates
    System.out.println(loc.toString());
    String title = "Current location: ";
    final StringBuilder sb = new StringBuilder(title);
    sb.append("Longitude: ");
    sb.append(loc.getLongitude());
    sb.append("Latitude: ");
    sb.append(loc.getLatitude());
    runOnUiThread(new Runnable() {

        @Override
        public void run() {
            mInfoText.setText(sb.toString());
        }
    });
}

@Override
public void onProviderDisabled(String provider){ // message if GPS is disabled
    Toast.makeText(this, "GPS disabled", Toast.LENGTH_LONG).show();
    AlertDialog.Builder alertbox = new AlertDialog.Builder(this);
    alertbox.setMessage("Please activate GPS!");
    alertbox.setNeutralButton("OK", new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface arg0, int arg1) {
            finish();
        }
    }
    );
    alertbox.show();
}


@Override
public void onProviderEnabled(String provider) {
    Toast.makeText(this, "GPS enabled", Toast.LENGTH_LONG).show();
}


@Override
public void onStatusChanged(String provider, int status, Bundle b) { // called upon GPS status changes
    switch (status) {
    case LocationProvider.OUT_OF_SERVICE:
        Toast.makeText(this, "Status changed: out of service", Toast.LENGTH_LONG).show();
        break;
    case LocationProvider.TEMPORARILY_UNAVAILABLE:
        Toast.makeText(this, "Status changed: temporarily unavailable", Toast.LENGTH_LONG).show();
        break;
    case LocationProvider.AVAILABLE:
        Toast.makeText(this, "Status changed: available", Toast.LENGTH_LONG).show();
        break;
    }

}

}

No correct solution

OTHER TIPS

You simply cannot show the user the direction the device is facing at the moment. But if you have the possibility to get the GPS provided location of the device, you can show which direction the device moved.

If you get location updates, you need two locations to calculate the bearing between this two:

double x = Math.cos(lat2) * Math.sin(lng1-lng2);
double y = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(lng1-lng2);
double bearing = Math.atan2(x, y);

Hope this helps!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top