ネクサス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()
を呼び出しますが、それでも運がありません。間違いはどこにありますか、事前に感謝します。
現在、_Fused Location Provider
_は、少なくとも1つのクライアントが接続されている場合にのみバックグラウンド位置を維持します。最初のクライアントが接続すると、すぐに場所を取得しようとします。アクティビティが最初に接続するクライアントであり、getLastLocation()
ですぐにonConnected()
を呼び出す場合、最初の場所にアクセスするのに十分な時間ではない可能性があります。
チュートリアル の指示に従うと、同じ問題が発生しました。電話では機能し、(Genymotion)エミュレーターでは機能しませんでした。
AndroidManifest.xmlで、これを変更します。
<uses-permission Android:name="Android.permission.ACCESS_COARSE_LOCATION" />
これに:
<uses-permission Android:name="Android.permission.ACCESS_FINE_LOCATION" />
...すぐに場所を取得します。コードを変更する必要はありません(位置情報の更新を聞くため)。
この問題は、お使いのデバイスで「Wi-Fiとモバイルネットワークの場所」が有効になっていない場合にも発生する可能性があります。
LocationClient(融合ロケーションプロバイダー)は、GPSとWiFiの両方を使用します。 Wi-Fiの方がはるかに高速ですが、GPSは現在地を見つけるのに時間がかかります。ただし、これら2つのサービスのいずれかが接続されている場合、コールバックメソッドonConnectedが呼び出されます。また、onConnectedメソッドでLocationClient.getLastLocation()をすぐに呼び出そうとしている場合、ほとんどの場合、wifiロケーションサービスが無効になっているとnull値を取得します。それは単にGPSが十分に速くないからです。
ローカルで問題を解決するには、「Wi-Fiとモバイルネットワークの場所」を有効にします。 [設定]> [個人]> [位置情報へのアクセス]> [Wi-Fiとモバイルネットワークの場所]に移動します。
ただし、アプリのユーザーの問題を解決する場合は、getLastLocation()がnullを返すかどうかを確認することをお勧めします。存在する場合は、Googleマップと同じようにユーザーにサービスを有効にするよう促します。
うまくいけば、それが助けになります。
私は同様の問題に直面していました。
onConnected
でmLocationClient.getLastLocation()
を呼び出すか、Google Play Servicesへの接続が確立された後に呼び出します。ロケーションクライアントが接続される前にこのメソッドを呼び出している場合、返されるロケーションはnull
になります。
ロケーションクライアントがmLocationClient.isConnected()
によって接続されているかどうかを確認できます。
お役に立てれば。
これは、おそらくわずかに異なる状況で、正確に機能するソリューションです。しかし、誰もが正確な概念を理解できるように、いくつかの小さな説明手順を追加したかったのです。
1)onCreate()of Android Component(Eg、Activity、Fragment 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'
ユーザーがWi-Fi/GSMまたはGPS経由で位置情報を有効にしているかどうかを確認する必要があります。利用可能なロケーションプロバイダーがない場合は、null
を取得します。
このコードは、場所の設定とともに画面を表示します。
startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
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) {
}
});
また、 https://developer.Android.com/training/permissionsに従って、ランタイム中にロケーション許可を明示的に要求する必要があります /requesting.html およびマニフェストファイルに含める。
実行時に権限がない場合、明示的なエラーは発生しません。ロケーションプロバイダーは単にnullを返します。
Googleがこれを文書化するのに役立ち、nullを返すだけでなく、例外もスローします。 nullを返すことは、この状況で行うのに最も役に立たないことです。
私も自分のアプリで同じ問題に直面していましたが、唯一欠けているのは、アプリがACCESS_FINE_LOCATIONではなくACCESS_COARSE_LOCATIONのみを要求したことです。後で許可を追加すると、すべてが正常に機能しました。
Google Playサービスのジオロケーションは、インターネット接続なしでは機能しません。GPSとは無関係です。そのため、モバイルデータをオンにしてアプリを確認してください。
場所の更新リクエストが必要です。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();
}