63

nexus s(Google Playサービスが利用可能な4.0.4)とavd(Google APIを使用した4.2.2)をテストする前に誰かが遭遇した質問のように、どちらの場合も locationclient はgetLastLocation()常に return null.

public class MainActivity extends Activity implements LocationListener,
        GooglePlayServicesClient.ConnectionCallbacks,
        GooglePlayServicesClient.OnConnectionFailedListener {

    private LocationClient mLocationClient;
    private LocationRequest mLocationRequest;
    boolean mUpdatesRequested = false;
    boolean mConnected = false;
    SharedPreferences mPrefs;
    SharedPreferences.Editor mEditor;
    private TextView mText;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mText = (TextView) findViewById(R.id.text);
        mLocationRequest = LocationRequest.create();
        mLocationRequest
                .setInterval(LocationUtils.UPDATE_INTERVAL_IN_MILLISECONDS);
    mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        mLocationRequest
.setFastestInterval(LocationUtils.FAST_INTERVAL_CEILING_IN_MILLISECONDS);
        mUpdatesRequested = false;
        mPrefs = getSharedPreferences(LocationUtils.SHARED_PREFERENCES,
                Context.MODE_PRIVATE);
        mEditor = mPrefs.edit();
        mLocationClient = new LocationClient(this, this, this);
    }
    @Override
    public void onStart() {
        super.onStart();
        /*
         * Connect the client. Don't re-start any requests here; instead, wait
         * for onResume()
         */
        mLocationClient.connect();
    }

    @Override
    protected void onResume() {
        super.onResume();
        // If the app already has a setting for getting location updates, get it
        if (mPrefs.contains(LocationUtils.KEY_UPDATES_REQUESTED)) {
            mUpdatesRequested = mPrefs.getBoolean(
                    LocationUtils.KEY_UPDATES_REQUESTED, false);
            // Otherwise, turn off location updates until requested
        } else {
            mEditor.putBoolean(LocationUtils.KEY_UPDATES_REQUESTED, false);
            mEditor.commit();
        }
    }
    @Override
    public void onStop() {
        // If the client is connected
        if (mLocationClient.isConnected()) {
            stopPeriodicUpdates();
        }
        // After disconnect() is called, the client is considered "dead".
        mLocationClient.disconnect();
        super.onStop();
    }

    @Override
    public void onPause() {
        // Save the current setting for updates
        mEditor.putBoolean(LocationUtils.KEY_UPDATES_REQUESTED,
                mUpdatesRequested);
        mEditor.commit();
        super.onPause();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
    public void getLocation(View v) {
        // If Google Play Services is available
        if (isGooglePlayServicesAvailable()) {
            if (!mConnected)
                mText.setText("location client is not connected to service yet");
            else {
                // Get the current location
                Location currentLocation = mLocationClient.getLastLocation();
                // Display the current location in the UI
                mText.setText(LocationUtils.getLocationString(currentLocation));
            }
        }
    }

    private boolean isGooglePlayServicesAvailable() {

        // Check that Google Play services is available
        int resultCode = GooglePlayServicesUtil
                .isGooglePlayServicesAvailable(this);

        // If Google Play services is available
        if (ConnectionResult.SUCCESS == resultCode) {
            // In debug mode, log the status
            Log.d(LocationUtils.APPTAG, "google play service is available");

            // Continue
            return true;
            // Google Play services was not available for some reason
        } else {
            // Display an error dialog
            Dialog dialog = GooglePlayServicesUtil.getErrorDialog(resultCode,
                    this, 0);
            if (dialog != null) {
                Log.e(LocationUtils.APPTAG,
                        "google play service is unavailable");
            }
            return false;
        }
    }

    private void stopPeriodicUpdates() {
        mLocationClient.removeLocationUpdates(this);
        // mConnectionState.setText(R.string.location_updates_stopped);
    }

    @Override
    public void onConnectionFailed(ConnectionResult arg0) {
        mConnected = false;
        Log.d(LocationUtils.APPTAG, "connection failed");
    }

    @Override
    public void onConnected(Bundle arg0) {
        mConnected = true;
        Log.d(LocationUtils.APPTAG,
                "location client connected to the location server");
        LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        lm.requestLocationUpdates(LocationManager.PASSIVE_PROVIDER, 0, 0,
                new android.location.LocationListener() {
                    @Override
                    public void onStatusChanged(String provider, int status,
                            Bundle extras) {}

                    @Override
                    public void onProviderEnabled(String provider) {}

                    @Override
                    public void onProviderDisabled(String provider) {}

                    @Override
                    public void onLocationChanged(final Location location) {
                    }
                });
        Log.d(LocationUtils.APPTAG, "done trying to get location");
    }

    @Override
    public void onDisconnected() {
        // TODO Auto-generated method stub
        mConnected = false;
        Log.d(LocationUtils.APPTAG,
                "location client disconnected from the location server");
    }

    @Override
    public void onLocationChanged(Location arg0) {}

}

それらのほとんどは、グーグルが提供する例から来ました。上記のコードでは、hava は次のような方法を試しました。

LocationRequest request = LocationRequest.create();
request.setNumUpdates(1);
mLocationClient.requestLocationUpdates(request, this);

LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

        lm.requestLocationUpdates(LocationManager.PASSIVE_PROVIDER, 0, 0,
                new android.location.LocationListener() {
                    @Override
                    public void onStatusChanged(String provider, int status,Bundle extras) {}

                    @Override
                    public void onProviderEnabled(String provider) {}

                    @Override
                    public void onProviderDisabled(String provider) {}

                    @Override
                    public void onLocationChanged(final Location location) {}
                });

onConnected()を呼び出す前にgetLastLocation()、まだ運がありません。どこが間違っていますか、よろしくお願いします。

4

13 に答える 13

56

現在、Fused Location Provider少なくとも 1 つのクライアントが接続されている場合、 はバックグラウンドの場所のみを維持します。最初のクライアントが接続すると、すぐに場所を取得しようとします。あなたのアクティビティが接続する最初のクライアントであり、getLastLocation()すぐに で電話をかけるonConnected()場合、最初の場所が到着するのに十分な時間がない可能性があります。

于 2013-05-31T22:17:04.577 に答える
22

チュートリアルの指示に従うと、同じ問題が発生しました。電話では機能し、(Genymotion) エミュレーターでは機能しませんでした。

解決

AndroidManifest.xml で、これを変更します。

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

これに:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

...そして、すぐに場所を取得します。コードを変更する必要はありません (ロケーションの更新をリッスンするため)。

于 2013-10-26T10:47:26.810 に答える
20

この問題は、デバイスで「Wi-Fi & モバイル ネットワークの場所」が有効になっていないことによっても発生する可能性があります。

LocationClient (融合されたロケーション プロバイダー) は、GPS と WiFi の両方を使用します。Wi-Fi ははるかに高速ですが、GPS は現在地を見つけるのに時間がかかります。ただし、これら 2 つのサービスのいずれかが接続されている場合は、コールバック メソッド onConnected が呼び出されます。また、すぐに onConnected メソッドで LocationClient.getLastLocation() を呼び出そうとすると、Wi-Fi 位置情報サービスが無効になっていると、ほとんどの場合 null 値が返されます。これは、GPS の速度が十分でないためです。

ローカルで問題を解決するには、「Wi-Fi & モバイル ネットワークの場所」を有効にします。「設定 > 個人 > 位置情報アクセス > Wi-Fi とモバイル ネットワークの位置情報」に移動して、それを行うことができます。

ただし、アプリのユーザーの問題を解決したい場合は、getLastLocation() が null を返すかどうかを確認することをお勧めします。その場合は、Google マップと同じようにサービスを有効にするようにユーザーに促します。

うまくいけば、それは役に立ちます。

于 2013-09-16T13:26:17.843 に答える
7

私は同様の問題に直面していました。

Google Play Services への接続が確立された後、またはmLocationClient.getLastLocation()呼び出します。onConnectedLocation Client が接続される前にこのメソッドを呼び出すと、返される場所は になりますnull

ロケーション クライアントが によって接続されているかどうかを確認できますmLocationClient.isConnected()

お役に立てれば。

于 2013-06-26T14:13:08.273 に答える
5

ユーザーが Wi-Fi/GSM または GPS 経由で位置情報を有効にしているかどうかを確認する必要があります。利用可能なロケーション プロバイダーがない場合は、null.

このコードは、場所の設定を含む画面を表示します。

startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
于 2013-05-30T12:13:29.010 に答える
3

SDK バージョン 23 について

https://developer.android.com/training/permissions/requesting.htmlに従って 、マニフェスト ファイルに含めるだけでなく、実行時に場所の許可を明示的に要求する必要もあります。

実行時にアクセス許可がない場合、明示的なエラーは発生しません。ロケーション プロバイダーは単に null を返します。

Google がこれを文書化し、null を返すだけでなく例外をスローすることも役立ちます。null を返すことは、この状況で最も役に立たないことです。

于 2016-08-27T16:00:09.043 に答える
2

私も自分のアプリで同じ問題に直面していましたが、唯一欠けていたのは、アプリが ACCESS_FINE_LOCATION ではなく ACCESS_COARSE_LOCATION のみを要求したことです。後の許可を追加したところ、すべて正常に機能しました。

于 2013-09-06T16:45:25.260 に答える
0

私は実行し、Nexus 7 デバイスで完璧に動作します。新しい API で使用されていない古いバージョンの LocationListener を誤って記述してしまいました。

新しい LocationListener で設定する必要があります。

このクラスをインポートしてから試す必要があります。

import com.google.android.gms.location.LocationListener;

そして、新しい API ごとに 1 つのメソッドのみをオーバーライドします

@Override
public void onLocationChanged(final Location newLocation) 
{}

この方法を試して、まだ問題が発生している場合はお知らせください。

ありがとう。

于 2013-07-30T05:13:56.590 に答える
0

Google Play サービスの地理位置情報は、GPS とは無関係に、インターネット接続なしでは機能しません。そのため、モバイルデータをオンにしてアプリを確認してください。

于 2013-08-28T07:39:29.153 に答える
-3

少し遅くなりますが、最も簡単な修正方法は、ヘルパー関数を使用することです。私の問題は、それが接続されることでしたが、場所が見つかる前に、それにアクセスしようとしてヌル ポインターにヒットしました。

public Location getLocation(LocationClient locationClient){

    if(locationClient.getLastLocation() == null){
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return getLocation(locationClient);
    }else{
        return locationClient.getLastLocation();
    }
}

これを使用して、onConnectedこの関数を使用してロケーションに必要なものを設定し、ロケーション クライアントを渡します。

@Override
public void onConnected(Bundle dataBundle) {

    Location temp = getLocation(mLocationClient);
    mLocation = temp;
}

また、何らかの理由で場所を取得したくない場合はonConnected、 を渡す限り、どこでも同じヘルパー関数を使用できますlocationClient

于 2014-07-10T23:34:53.573 に答える