質問

I am working on a BlackBerry Application that is supposed to update the location at fixed intervals. The interval value can be selected/changed from a slider. It varies between 1 minute, 2 minutes, 5 minutes, 30 minutes etc. On the very first load (Start App), location interval is 30 seconds. After this, I store the slider value in a persistent store and location is updated accordingly with the set interval. Background thread running to update location is as follows:

private boolean startLocationUpdate()
{
    boolean retval = false;
    try
    {
        LocationProvider locationProvider = LocationProvider.getInstance(null);
        if ( locationProvider == null )
        {
            Runnable showGpsUnsupportedDialog = new Runnable()
            {
                public void run()
                {
                    Dialog.alert("GPS is not supported on this platform, exiting...");
                    //System.exit( 1 );
                }
            };
            UiApplication.getUiApplication().invokeAndWait( showGpsUnsupportedDialog ); // Ask event-dispatcher thread to display dialog ASAP.
        }
        else
        {
            locationProvider.setLocationListener(new LocationListenerImpl(), interval, -1, -1);
            retval = true;
        }
    }
    catch (LocationException le)
    {
        System.err.println("Failed to instantiate the LocationProvider object, exiting...");
        System.err.println(le);
        System.exit(0);
    }
    return retval;
}

private class LocationListenerImpl implements LocationListener
{
    public void locationUpdated(LocationProvider provider, Location location)
    {
        if(location.isValid())
        {
            double longitude = location.getQualifiedCoordinates().getLongitude();
            double latitude = location.getQualifiedCoordinates().getLatitude();
            updateLocationScreen(latitude, longitude);
        }
    }
    public void providerStateChanged(LocationProvider provider, int newState)
    {
    }
}

private void updateLocationScreen(final double latitude, final double longitude)
{
    UiApplication.getUiApplication().invokeAndWait(new Runnable()
    {
        public void run()
        {
            double lat = latitude;
            double longi = longitude;
            lblLatitude.setText(Double.toString(lat));
            spacing.setText(", ");
            lblLongitude.setText(Double.toString(longi));
        }
    });
}  

Along with this, there is a "Refresh" button available that will start acquiring a location update immediately once clicked. This button calls a method is another class to acquire the location. The method is as follows:

try {
    Criteria myCriteria = new Criteria();
    myCriteria.setCostAllowed(false);
    LocationProvider myLocationProvider = LocationProvider.getInstance(myCriteria);
    double heading = 0;
    double velocity = 0;

    try {
        Location myLocation = myLocationProvider.getLocation(6000);
        if(myLocation.isValid())
        {
            double longitude = myLocation.getQualifiedCoordinates().getLongitude();
            double latitude = myLocation.getQualifiedCoordinates().getLatitude();
        }
        UiApplication.getUiApplication().invokeLater(new Runnable() {
            public void run() {
                //Dialog.alert("Location Updated");
            }
        });
        setLocation(myLocation.getQualifiedCoordinates(),velocity,heading);
    } catch ( InterruptedException iex ) {
        System.out.println(iex.getMessage());
    } catch ( LocationException lex ) {
        System.out.println(lex.getMessage());
    }
} catch ( LocationException lex ) {
    System.out.println(lex.getMessage());
}

Problems I am facing:

1) Interval value not changing. I am implementing the change by picking the value from the persistent store as:

if (PersistentStoreHelper.persistentHashtable.containsKey("gpsInterval"))
{
    String intervalValue=((String) PersistentStoreHelper.persistentHashtable.get("gpsInterval"));
    MyScreen.interval=Integer.parseInt(intervalValue);
}

This is never empty as navigation to this page inserts a value of 30 minutes to it.

2) Once the "Refresh" button is clicked, the background thread seems to be cancelled. It no longer runs at any interval value.

I read that there is only one instance of the location provider created and with "Refresh" it is cancelled after acquiring the location and thus the background thread stops. Is this true? If yes, how can I achieve my desired result.

EDIT: The gpsInterval value is read as follows:

if (PersistentStoreHelper.persistentHashtable.containsKey("gpsInterval"))
{
    String intervalValue=((String)PersistentStoreHelper.persistentHashtable.get("gpsInterval"));
    interval=Integer.parseInt(intervalValue);
}
else
{
    interval=10;
}
役に立ちましたか?

解決

Saving the Interval

So, first of all, make sure that when you let the user change the update interval, via the slider, you properly save it to the PersistentStore. The code should look something like this:

// NOTE: I would recommend persisting the slider value as an Integer, not a String,
//   but, the original code used String, so that's what this uses
hashtable.put("gpsInterval", (new Integer(intervalSlider.getValue())).toString());
PersistentObject po = PersistentStore.getPersistentObject(APP_BUNDLE_ID);
po.setContents(hashtable);
po.commit();

Since you didn't post that code, I just wanted to be sure that it was being saved to the persistent store correctly.

Updating the Location Provider / Listener

The other issue, that is a problem, is that you kick off the location updates in startLocationUpdate() with this code:

locationProvider.setLocationListener(new LocationListenerImpl(), interval, -1, -1);

That uses the value of the interval variable at the instant that setLocationListener() is called. If you later update the interval variable,

String intervalValue=((String) PersistentStoreHelper.persistentHashtable.get("gpsInterval"));
MyScreen.interval=Integer.parseInt(intervalValue);

this will have no effect on the location listener. It will keep updating with the original interval value, not the new one. You would have to call setLocationListener() again, with the new value of interval. With your code, you should probably just call startLocationUpdate() again:

String intervalValue=((String) PersistentStoreHelper.persistentHashtable.get("gpsInterval"));
MyScreen.interval=Integer.parseInt(intervalValue);
startLocationUpdate();

Refresh Problem

I'm not 100% sure, but my guess would be that in your existing code that's used when the Refresh button is pressed, you are changing to a different LocationProvider with different criteria. That's probably why the first one is cancelled.

Try changing your startLocationUpdate() method to save the provider as a member variable:

/** this is the one location provider used by this class! */
private LocationProvider _locationProvider;

private boolean startLocationUpdate()
{
    boolean retval = false;
    try
    {
        _locationProvider = LocationProvider.getInstance(null);

then, in your refresh code, use the same location provider to get the current location:

double heading = 0;
double velocity = 0;

try {
    Location myLocation = _locationProvider.getLocation(6000);
    if(myLocation.isValid())

Note: if you really do want to setCostAllowed(false), that's fine. Do that the first time that you assign the _locationProvider member variable. And use that provider/criteria both for normal periodic location updates, and your Refresh button handler. I think the key is to use the same provider, not create a new one with different criteria.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top