2

Google マップを備えた Android アプリと、Google Play Services の新しいロケーション API を介した自動ロケーション更新があります。

このように実装: https://developer.android.com/training/location/receive-location-updates.html

特に GPS や正確な位置を受信しようとしています。

それは 100% 完璧に正常に動作し、GPS アイコンが上にあり、数秒ごとに場所が表示されます。心配する必要はありません。

奇妙な問題は、Google マップに切り替えて、少し待ってからアプリケーションに戻ると、アプリケーションがもう 1 つ場所の更新を取得し、更新の受信を停止することです。

私のアプリは、位置情報の更新を onPause/onStop で適切に停止し、onStart/onResume で再接続して再起動しています。

Google マップから切り替えた後、デバッグ トーストに「接続済み」と表示され、もう 1 つ「更新された場所」と表示された後、更新が停止します。onDisconnected() が呼び出されず、mLocationClient.isConnected() のチェックで「true」が報告されます。

その後、数秒ごとに実行されるタイマー ハンドラーを使用したハックの回避策を追加しました。過去 10 秒間に場所が見つからない場合は、以下の stopPauseLocation() と checkStartLocation() を呼び出します。これにより、問題が修正され、場所が再び入り始めます。明らかにこれは醜いハックであり、私はそれについて満足していません.

これはバグのようで、Google マップと自分のアプリの間で矛盾しているように見えますが、本当の解決策を見つけることはできません。

何か案は?

主なコード スニペットは次のとおりです。

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // Create the LocationRequest object
    mLocationRequest = LocationRequest.create();
    // Use high accuracy
    mLocationRequest.setPriority(
            LocationRequest.PRIORITY_HIGH_ACCURACY);
    // Set the update interval to 2 seconds
    mLocationRequest.setInterval(2000);
    // Set the fastest update interval to 1 second
    mLocationRequest.setFastestInterval(1000);
    /*
     * Create a new location client, using the enclosing class to
     * handle callbacks.
     */
    mLocationClient = new LocationClient(this, this, this);

    mLocationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
}

@Override
protected void onStart() {
    super.onStart();

    // Check our connection to play services
    checkStartLocation();
}

/*
 * Called when the Activity is no longer visible at all.
 * Stop updates and disconnect.
 */
@Override
protected void onStop() {
    stopPauseLocation();
}

/*
 * Called by Location Services when the request to connect the
 * client finishes successfully. At this point, you can
 * request the current location or start periodic updates
 */
@Override
public void onConnected(Bundle dataBundle) {
    // Display the connection status
    Toast.makeText(this, "Connected", Toast.LENGTH_SHORT).show();
    mLocationClient.requestLocationUpdates(mLocationRequest, this);

    super.onStop();
}

private void stopPauseLocation()
{
    // If the client is connected
    if (mLocationClient.isConnected()) {
        /*
         * Remove location updates for a listener.
         * The current Activity is the listener, so
         * the argument is "this".
         */
        mLocationClient.removeLocationUpdates(this);
    }
    /*
     * After disconnect() is called, the client is
     * considered "dead".
     */
    mLocationClient.disconnect();
}

/**
 * Helper to check if we're connected to play, and try to connect if not
 */
protected void checkStartLocation() {
    if (!mLocationClient.isConnected())
    {
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        mLocationClient.connect();
    }
}

/*
 * Called by Location Services when the request to connect the
 * client finishes successfully. At this point, you can
 * request the current location or start periodic updates
 */
@Override
public void onConnected(Bundle dataBundle) {
    // Display the connection status
    Toast.makeText(this, "Connected", Toast.LENGTH_SHORT).show();
    mLocationClient.requestLocationUpdates(mLocationRequest, this);
}

@Override
public void onDisconnected() {
    // Display the connection status
    Toast.makeText(this, "Disconnected.",Toast.LENGTH_SHORT).show();
}

/*
 * Called by Location Services if the attempt to connect to
 * Location Services fails.
 */
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
    Toast.makeText(this, "onConnectionFailed", Toast.LENGTH_SHORT).show();
}

 // Define the callback method that receives location updates
@Override
public void onLocationChanged(Location location) {
    // Report to the UI that the location was updated
    String msg = "Updated Location: " +
            Double.toString(location.getLatitude()) + "," +
            Double.toString(location.getLongitude());
    Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
}
4

1 に答える 1

2

これに関して私が見つけた唯一の方法はハックですが、これは私が思いついたハックの最良のバージョンです。

以下のコードは、10 秒ごとに (その後、15 秒、20 秒、30 秒まで段階的に) 場所の更新をチェックします。場所が受信されていない場合は、removeLocationUpdates() と requestLocationUpdates() を呼び出します。これで問題が解決したようです。

private Handler locationCheck = null;
// Track the time of the last location update
private long lastLocationUpdate = System.currentTimeMillis();
private long lastLocationWaitTime = 0;
// How long to wait until we reconnect (10 sec)
private long WAIT_LOCATION_AGE_START = 10000;
// Increments of how much longer to wait before next check
// Increments on every failure to give the system more time to recover
private long WAIT_LOCATION_AGE_INCREMENT = 5000;
// Max time to wait
private long MAX_WAIT_LOCATION_AGE = 30000;

Add to onCreate in your class:
locationCheck = new Handler();

Add to onResume/onStart:
lastLocationUpdate = System.currentTimeMillis();
lastLocationWaitTime = WAIT_LOCATION_AGE_START;
locationCheck.removeCallbacks(locationCheckRunnable);
locationCheck.postDelayed(locationCheckRunnable, 1000);

Add to onStop/onPause:
locationCheck.removeCallbacks(locationCheckRunnable);

private Runnable locationCheckRunnable = new Runnable() {
    @Override
    public void run() {
        if ((System.currentTimeMillis() - lastLocationUpdate) > lastLocationWaitTime)
        {
            // Verify our connection
            checkStartLocation();
            // Reset the timer
            lastLocationUpdate = System.currentTimeMillis();
            // On next check wait a bit longer
            lastLocationWaitTime += WAIT_LOCATION_AGE_INCREMENT;
            lastLocationWaitTime = Math.min(lastLocationWaitTime, MAX_WAIT_LOCATION_AGE);
            // Re-request location updates
            mLocationClient.removeLocationUpdates(MyParentClassName.this);
            mLocationClient.requestLocationUpdates(mLocationRequest, LocationSocialBaseScreen.this);
        }

        locationCheck.postDelayed(this, 1000);
    }
};

@Override
public void onLocationChanged(Location location) {
    lastLocationUpdate = System.currentTimeMillis();
}
于 2013-10-21T10:13:49.580 に答える