I'm trying to write a simple app that receives location info from GPS and plots the points on a map. I wrote a Service for GPS handling but I'm having trouble with using it in an Activity - I'm unable to get values of latitude/longitude/altitude.
The Service appears to start correctly (GPS is initiated on the phone and acquires a fix) but when I try to retrieve coordinates (by pressing the button in Activity to call relevant methods) the app crashes and I get a java.lang.NullPointerException error in LogCat.
I've looked at many examples on Stack Overflow and other website but I'm new to Android development and I'm not sure what I'm doing wrong. I would greatly appreciate any advice.
Service:
public class TrackingService extends Service {
private LocationManager SgpstLocationManager;
private LocationListener spgstLocationListener;
private static long minimumDistanceBwUpdates = 10; //10 metres
private static long minimumTimeBwUpdates = 3000; //3 seconds
static Location location;
private void startTrackingService() {
//location manager declaration
SgpstLocationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
//location listener declaration
spgstLocationListener = new SgpstLocationListener();
//request location updates from location manager
SgpstLocationManager.requestLocationUpdates(
SgpstLocationManager.GPS_PROVIDER,
minimumTimeBwUpdates,
minimumDistanceBwUpdates,
spgstLocationListener);
}
private void stopTrackingService() {
//remove location updates from location manager
SgpstLocationManager.removeUpdates(spgstLocationListener);
}
//location listener class
public class SgpstLocationListener implements LocationListener {
public void onLocationChanged(Location location) {
if (location != null) {
try {
if (location.hasAccuracy()) {
//retrieve information about a point:
location.getLatitude();
location.getLongitude();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void onProviderDisabled(String provider) {
//mandatory method - not used
}
public void onProviderEnabled(String provider) {
//mandatory method - not used
}
public void onStatusChanged(String provider, int status, Bundle extras) {
//mandatory method - not used
}
}
//mandatory service methods
public void onCreate() {
super.onCreate();
startTrackingService();
}
public void onDestroy() {
super.onDestroy();
stopTrackingService();
}
//methods for interaction with client objects
private final IBinder sgpstBinder = new LocalBinder();
@Override
public IBinder onBind(Intent intent) {
return sgpstBinder;
}
public class LocalBinder extends Binder {
TrackingService getService() {
return TrackingService.this;
}
}
//get and set methods
public static void setMinimumDistanceBwUpdates(long distance) {
minimumDistanceBwUpdates = distance;
}
public static void setMinimumTimeBwUpdates(long time) {
minimumTimeBwUpdates = time;
}
public static long getMinimumDistanceBwUpdates() {
return minimumDistanceBwUpdates;
}
public static long getMinimumTimeBwUpdates() {
return minimumTimeBwUpdates;
}
public static double getMyLatitude() {
return location.getAltitude();
}
public static double getMyLongitude() {
return location.getLongitude();
}
public static double getMyAltitude() {
return location.getAltitude();
}
}
Activity:
public class GPSTestActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_gpstest);
startService(new Intent(GPSTestActivity.this, TrackingService.class));
Button updateButton = (Button)findViewById(R.id.update_button);
final TextView latitudeText = (TextView)findViewById(R.id.latitude);
final TextView longitudeText = (TextView)findViewById(R.id.longitude);
final TextView altitudeText = (TextView)findViewById(R.id.altitude);
latitudeText.setText("latitude");
longitudeText.setText("longitude");
altitudeText.setText("altitude");
updateButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
latitudeText.setText(String.valueOf(TrackingService.getMyLatitude()));
longitudeText.setText(String.valueOf(TrackingService.getMyLongitude()));
altitudeText.setText(String.valueOf(TrackingService.getMyAltitude()));
}
});
}
Many thanks for help. I rewrote/refactored the code based on your suggestions. I am now receiving the following error:
java.lang.RuntimeException: Unable to instantiate activity
ComponentInfo{com.example.simplegpstracker/com.example.simplegpstracker.GPSTestActivity}: java.lang.NullPointerException
I'll try to read up on Services Binding myself but any advice would be welcome.
amended code:
service:
public class TrackingService extends Service {
//fields
private LocationManager SgpstLocationManager;
private LocationListener spgstLocationListener;
private static long minimumDistanceBwUpdates = 10; //10 metres
private static long minimumTimeBwUpdates = 3000; //3 seconds
static Location myLocation;
private void startTrackingService() {
//location manager declaration
SgpstLocationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
//location listener declaration
spgstLocationListener = new SgpstLocationListener();
//request location updates from location manager
SgpstLocationManager.requestLocationUpdates(
SgpstLocationManager.GPS_PROVIDER,
minimumTimeBwUpdates,
minimumDistanceBwUpdates,
spgstLocationListener);
}
private void stopTrackingService() {
//remove location updates from location manager
SgpstLocationManager.removeUpdates(spgstLocationListener);
}
//location listener class
public class SgpstLocationListener implements LocationListener {
public void onLocationChanged(Location location) {
if (location != null) {
try {
if (location.hasAccuracy()) {
//retrieve information about a point:
myLocation = location;
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void onProviderDisabled(String provider) {
//mandatory method - not used
}
public void onProviderEnabled(String provider) {
//mandatory method - not used
}
public void onStatusChanged(String provider, int status, Bundle extras) {
//mandatory method - not used
}
}
//mandatory service methods
public void onCreate() {
super.onCreate();
startTrackingService();
}
public void onDestroy() {
super.onDestroy();
stopTrackingService();
}
//methods for interaction with client objects
private final IBinder sgpstBinder = new LocalBinder();
@Override
public IBinder onBind(Intent intent) {
return sgpstBinder;
}
public class LocalBinder extends Binder {
TrackingService getService() {
return TrackingService.this;
}
}
//get and set methods
public static void setMinimumDistanceBwUpdates(long distance) {
minimumDistanceBwUpdates = distance;
}
public static void setMinimumTimeBwUpdates(long time) {
minimumTimeBwUpdates = time;
}
public static long getMinimumDistanceBwUpdates() {
return minimumDistanceBwUpdates;
}
public static long getMinimumTimeBwUpdates() {
return minimumTimeBwUpdates;
}
public static double getMyLatitude() {
return myLocation.getAltitude();
}
public static double getMyLongitude() {
return myLocation.getLongitude();
}
public static double getMyAltitude() {
return myLocation.getAltitude();
}
}
activity:
public class GPSTestActivity extends Activity {
boolean trackingServiceBounded;
TrackingService trackingService;
TextView latitudeText = (TextView)findViewById(R.id.latitude);
TextView longitudeText = (TextView)findViewById(R.id.longitude);
TextView altitudeText = (TextView)findViewById(R.id.altitude);
Button updateButton = (Button)findViewById(R.id.update_button);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_gpstest);
//startService(new Intent(GPSTestActivity.this, TrackingService.class));
latitudeText.setText("latitude");
longitudeText.setText("longitude");
altitudeText.setText("altitude");
updateButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
latitudeText.setText(String.valueOf(TrackingService.getMyLatitude()));
longitudeText.setText(String.valueOf(TrackingService.getMyLongitude()));
altitudeText.setText(String.valueOf(TrackingService.getMyAltitude()));
}
});
}
@Override
protected void onStart() {
super.onStart();
Intent intent = new Intent(this, TrackingService.class);
bindService(intent, serviceConnection, BIND_AUTO_CREATE);
}
//bind Activity to the Service
ServiceConnection serviceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName name, IBinder service) {
trackingServiceBounded = true;
LocalBinder localBinder = (LocalBinder)service;
trackingService = localBinder.getService();
}
public void onServiceDisconnected(ComponentName name) {
trackingServiceBounded = false;
trackingService = null;
}
};
@Override
protected void onStop() {
super.onStop();
if (trackingServiceBounded) {
unbindService(serviceConnection);
trackingServiceBounded = false;
}
}
}
To get the instance of your service you need to bind the service with the activity. Check these links:
http://developer.android.com/guide/components/bound-services.html http://dharmendra4android.blogspot.mx/2012/05/bind-service-using-ibinder-class.html
If you need aditional help, plese tell me.
You declare location
but never instantiate it.
Do this at onLocationChange
if (location.hasAccuracy()) {
//save location in the private variable:
this.location = location;
}
To have a cleaner code move the SgpstLocationListener class to another file.
As you like more i will rename CurrentLocation to myLocation.
//location listener class
public class SgpstLocationListener implements LocationListener {
public Location myLocation; //THIS IS WHAT YOU READ IN THE SERVICE
public void onLocationChanged(Location location) {
if (location != null) {
try {
if (location.hasAccuracy()) {
//retrieve information about a point:
myLocation = location; //SET TO THE CURRENT POSITION
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void onProviderDisabled(String provider) {
//mandatory method - not used
}
public void onProviderEnabled(String provider) {
//mandatory method - not used
}
public void onStatusChanged(String provider, int status, Bundle extras) {
//mandatory method - not used
}
}
In the service use this to get latitude from SgpstLocationListener
public static double getMyLatitude() {
return spgstLocationListener.myLocation.getLatitude();
}
Before proceeding you must be sure that the GPS is working !!
As you may have already noticed my english is not very good, I hope you understood
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.