web-dev-qa-db-ja.com

LocationClient getLastLocation()はnullを返します

ネクサスs(4.0.4でgoogleプレイサービスが利用可能)とavd(4.2.2でgoogle api)をテストする前に誰かが出した質問のように、どちらの場合もlocationclientのgetLastLocation()は常に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()を呼び出しますが、それでも運がありません。間違いはどこにありますか、事前に感謝します。

57
oscarthecat

現在、_Fused Location Provider_は、少なくとも1つのクライアントが接続されている場合にのみバックグラウンド位置を維持します。最初のクライアントが接続すると、すぐに場所を取得しようとします。アクティビティが最初に接続するクライアントであり、getLastLocation()ですぐにonConnected()を呼び出す場合、最初の場所にアクセスするのに十分な時間ではない可能性があります。

51
David

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

解決

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

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

これに:

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

...すぐに場所を取得します。コードを変更する必要はありません(位置情報の更新を聞くため)。

21
Saran

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

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

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

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

うまくいけば、それが助けになります。

19
Tim Hong

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

onConnectedmLocationClient.getLastLocation()を呼び出すか、Google Play Servicesへの接続が確立された後に呼び出します。ロケーションクライアントが接続される前にこのメソッドを呼び出している場合、返されるロケーションはnullになります。

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

お役に立てれば。

7
Rahul Sainani

これは、おそらくわずかに異なる状況で、正確に機能するソリューションです。しかし、誰もが正確な概念を理解できるように、いくつかの小さな説明手順を追加したかったのです。

1)onCreate()of Android Component(Eg、ActivityFragment or Service注:IntentService)ではなく、buildに続いてconnect以下のようにGoogleApiClientを使用します。

buildGoogleApiClient();
mGoogleApiClient.connect();

buildGoogleApiClient()の実装は、

protected synchronized void buildGoogleApiClient() {
        Log.i(TAG, "Building GoogleApiClient");

        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addApi(LocationServices.API)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build();

    }

後でonDestroy()で、GoogleApiClientを次のように切断できます。

@Override
    public void onDestroy() {
        Log.i(TAG, "Service destroyed!");
        mGoogleApiClient.disconnect();
        super.onDestroy();
    }

手順1では、GoogleApiClientをビルドして接続します。

1)GoogleApiClientインスタンスは、onConnected()メソッドで初めて接続されます。これで、次のステップはonConnected()メソッドになります。

@Override
    public void onConnected(@Nullable Bundle bundle) {
        Log.i(TAG, "GoogleApiClient connected!");
        buildLocationSettingsRequest();
        createLocationRequest();
        location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
        Log.i(TAG, " Location: " + location); //may return **null** because, I can't guarantee location has been changed immmediately 
    }

上記では、メソッドcreateLocationRequest()を呼び出してロケーションリクエストを作成しました。メソッドcreateLocationRequest()は次のようになります。

protected void createLocationRequest() {
        //remove location updates so that it resets
        LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this); //Import should not be **Android.Location.LocationListener**
    //import should be **import com.google.Android.gms.location.LocationListener**;

        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(10000);
        mLocationRequest.setFastestInterval(5000);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        //restart location updates with the new interval
        LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);

    }

3)LocationListenerインターフェイスのonLocationChange()コールバックで、新しい場所を取得します。

@Override
    public void onLocationChanged(Location location) {
        Log.i(TAG, "Location Changed!");
        Log.i(TAG, " Location: " + location); //I guarantee,I get the changed location here

    }

Logcatで次のような結果が得られます: 03-22 18:34:17.336 817-817/com.LiveEarthquakesAlerts I/LocationTracker:場所:Location [fused 37.421998、-122.084000 acc = 20 et = + 15m35s840ms alt = 0.0]

これらの3つのステップを実行できるようにするには、build.gradleを以下のように構成しておく必要があります。

 compile 'com.google.Android.gms:play-services-location:10.2.1'
5
Uddhav Gautam

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

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

startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
5
Pitel

Samsung電話でのテストでも同様の問題に直面しました(高度にカスタマイズされたAndroid、開発者サポートなし)。

LocationManagerとLocationClientはプロバイダーからGPSを取得しません。位置情報が必要になるたびにキックスタートする必要があります。 LocationManager.getLastKnownLocation OR LocationClient.getLastLocation]呼び出しの前にこれを実行します。これらのAPIは戻ります。

YOUR_APPLICATION_CONTEXT.getLocationManager().requestLocationUpdates(
    LocationManager.NETWORK_PROVIDER, 0, 0, new 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) {
        }
    });
4
Siddharth

SDKバージョン23で

また、 https://developer.Android.com/training/permissionsに従って、ランタイム中にロケーション許可を明示的に要求する必要があります /requesting.html およびマニフェストファイルに含める。

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

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

3
Mark

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

2
gfhuertac

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

0
user1575120

場所の更新リクエストが必要です。26の場合Android SDKの許可はすべて大丈夫です:

private void setLocation(Context context) {
    GoogleApiClient googleApiClient = new GoogleApiClient.Builder(context)
            .addApi(LocationServices.API).build();
    googleApiClient.connect();

     locationRequest = LocationRequest.create();
    locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    locationRequest.setInterval(2000);
    locationRequest.setFastestInterval(2000);

    LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder().addLocationRequest(locationRequest);
    builder.setAlwaysShow(true);
    PendingResult<LocationSettingsResult> result = LocationServices.SettingsApi.checkLocationSettings(googleApiClient, builder.build());
    result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
        @Override
        public void onResult(LocationSettingsResult result) {
            final Status status = result.getStatus();
            switch (status.getStatusCode()) {
                case LocationSettingsStatusCodes.SUCCESS:
                    showMessage(" All location settings are satisfied.");
                    mGoogleApiClient = new GoogleApiClient.Builder(MainActivity.this)
                            .addApi(LocationServices.API)
                            .addConnectionCallbacks(connectionCallbacks)
                            .addOnConnectionFailedListener(connectionFailedListener)
                            .build();
                            mGoogleApiClient.connect();
                    break;
                case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                    l.a(" Location settings are not satisfied. Show the user a dialog to upgrade location settings ");

                    try {
                        // Show the dialog by calling startResolutionForResult(), and check the result
                        // in onActivityResult().
                        status.startResolutionForResult(MainActivity.this, REQUEST_CHECK_SETTINGS);
                    } catch (IntentSender.SendIntentException e) {
                        showMessage("PendingIntent unable to execute request.");
                    }
                    break;
                case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
                    showMessage("Location settings are inadequate, and cannot be fixed here. Dialog not created.");
                    break;
            }
        }
    });
}

onConnectedコールバックメソッド内:

 @Override
    public void onConnected(@Nullable Bundle bundle) {
        l.a(3232);
        if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) !=
                PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                   return;
        }

            mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
                    mGoogleApiClient);
       if(null==mLastLocation){//  !!!!!!!!!!!! here it can happen !!!!!!!

                    LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, locationRequest, new LocationListener() {
                        @Override
                        public void onLocationChanged(Location location) {
                            mLastLocation = location;
                            locationWasFound = true;
                            sevumPora.setLocation(mLastLocation);
                            mGoogleApiClient.disconnect();
                        }
                    });
                return;
            }
        locationWasFound = true;
        sevumPora.setLocation(mLastLocation);
        mGoogleApiClient.disconnect();
    }
0
CodeToLife