0

我正在尝试编写一个简单的应用程序,它从 GPS 接收位置信息并在地图上绘制点。我为 GPS 处理编写了一个服务,但在 Activity 中使用它时遇到问题 - 我无法获取纬度/经度/高度的值。

服务似乎可以正确启动(在手机上启动 GPS 并获得修复)但是当我尝试检索坐标时(通过按下 Activity 中的按钮调用相关方法)应用程序崩溃并且我收到 java.lang.NullPointerException 错误在 LogCat 中。

我在 Stack Overflow 和其他网站上查看了许多示例,但我是 Android 开发的新手,我不确定自己做错了什么。我将不胜感激任何建议。

服务:

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();
}

}

活动:

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()));
            }
    });
}

非常感谢您的帮助。我根据您的建议重写/重构了代码。我现在收到以下错误:

java.lang.RuntimeException: Unable to instantiate activity
ComponentInfo{com.example.simplegpstracker/com.example.simplegpstracker.GPSTestActivity}: java.lang.NullPointerException

我会尝试自己阅读服务绑定,但欢迎提出任何建议。

修改后的代码:

服务:

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();
}

}

活动:

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;
    }
}

}
4

3 回答 3

0

您声明location但从不实例化它。
在 onLocationChange 执行此操作

if (location.hasAccuracy()) {
                    //save location in the private variable:
                    this.location = location;
                }  
于 2013-07-11T20:57:57.573 回答
0

要获取服务实例,您需要将服务与活动绑定。检查这些链接:

http://developer.android.com/guide/components/bound-services.html http://dharmendra4android.blogspot.mx/2012/05/bind-service-using-ibinder-class.html

如果您需要其他帮助,请告诉我。

于 2013-07-11T20:44:09.720 回答
0

要使代码更简洁,请将 SgpstLocationListener 类移动到另一个文件。
如果您喜欢更多,我会将 CurrentLocation 重命名为 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
    }
}  

在服务中使用它来获取纬度SgpstLocationListener

public static double getMyLatitude() {

        return spgstLocationListener.myLocation.getLatitude();
    }  

在继续之前,您必须确保 GPS 工作正常!

你可能已经注意到我的英语不是很好,希望你能理解

于 2013-07-13T14:04:59.830 回答