FusedLocationApi.getLastLocation 始终为空
FusedLocationApi.getLastLocation always null
我只想在我的 Android 项目中检索设备位置,为此我使用播放服务方法:
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder( MainSearchActivity.this )
.addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
@Override
public void onConnected( Bundle bundle ){
Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if( location == null ){
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, new LocationListener() {
@Override
public void onLocationChanged(Location location) {
lastLocation = location;
}
});
}
}
@Override
public void onConnectionSuspended( int i ){
}
})
.addOnConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() {
@Override
public void onConnectionFailed( ConnectionResult connectionResult ){
if( connectionResult.hasResolution() ){
try {
// Start an Activity that tries to resolve the error
connectionResult.startResolutionForResult(MainSearchActivity.this, CONNECTION_FAILURE_RESOLUTION_REQUEST);
}catch( IntentSender.SendIntentException e ){
e.printStackTrace();
}
}else{
Utils.logger("Location services connection failed with code " + connectionResult.getErrorCode(), Utils.LOG_DEBUG );
}
}
})
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
}
public Location retrieveLastLocation(){
Location loc = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if( loc == null)
{
}
return loc; //TODO: What if loc is null?
}
但 loc
变量始终为空。每次都在不同的手机上如此。另外 lastLocation
,我尝试在 onLocationChanged
中分配,永远不会改变。始终为空。
这些是我为应用设置的权限
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="com.vogella.android.locationapi.maps.permission.MAPS_RECEIVE" />
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
我只是不明白:为什么 LocationServices
无法检索位置?我在我测试过的所有三台设备上都启用了所有地理定位设置。
融合 Location Provider
只有在至少有一个客户端连接到它时才会保持后台位置。现在仅仅打开定位服务并不能保证存储最后已知的位置。
第一个客户端连接后,会立即尝试获取位置。如果您的 activity 是第一个连接的客户端并且 getLastLocation()
在 onConnected()
中立即被调用,那么第一个位置可能没有足够的时间到达..
我建议你先启动地图应用,这样至少有一些确认的位置,然后再测试你的应用。
我认为在显示的代码中有一个我看不到的小错误。
mGoogleApiClient
已构建但似乎未构建 connected.You 可以通过调用 mGoogleApiClient.isConnected()
来验证这一点。
您可以覆盖 onStart 方法并在那里调用连接。或者您可以覆盖 onResume()
,以防您希望在您的 activity 可见时访问该位置。
@Override
protected void onStart() {
super.onStart();
if (mGoogleApiClient != null) {
mGoogleApiClient.connect();
}
}
如果 getLastLocation() 始终返回 null,请尝试此 hack。我用它来解决我的问题。在 activity.
中实施 LocationListener(导入 com.google.android.gms.location.LocationListener)
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
Context mContext = this;
manager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
createLocationRequest();
mGoogleApiClient = new GoogleApiClient.Builder(mContext)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
}
private void createLocationRequest(){
mLocationRequest = LocationRequest.create();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(SET_INTERVAL);
mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
}
onStart 或 onResume(我更喜欢 onResume)
@Override
protected void onResume() {
super.onResume();
if (manager.isProviderEnabled(LocationManager.GPS_PROVIDER) ) {
if (mGoogleApiClient != null) {
mGoogleApiClient.connect();
}
}else{
// Showyourmesg();
}
}
@Override
protected void onPause() {
super.onPause();
if (mGoogleApiClient != null) {
mGoogleApiClient.disconnect();
}
}
protected void startLocationUpdates(){
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,
mLocationRequest,this);
}
protected void stopLocationUpdates() {
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient, this);
}
现在,在您的 onLocationChanged 方法中检查 googleApiClient 是否已连接。如果已连接,请断开连接,然后重新连接。
@Override
public void onLocationChanged(Location location) {
Log.d("SplashAct", "LocatinChngListner, loc: " + location.getLatitude() + "," + location.getLongitude());
if (mGoogleApiClient != null)
if (mGoogleApiClient.isConnected() || mGoogleApiClient.isConnecting()){
mGoogleApiClient.disconnect();
mGoogleApiClient.connect();
} else if (!mGoogleApiClient.isConnected()){
mGoogleApiClient.connect();
}
}
最后,在您的 onConntected() 方法中
@Override
public void onConnected(Bundle bundle) {
Log.d("ACTIVITY", "ApiClient: OnConnected");
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
mGoogleApiClient);
if (mLastLocation == null){
startLocationUpdates(); // bind interface if your are not getting the lastlocation. or bind as per your requirement.
}
if (mLastLocation != null){
while (latitude == 0 || longitude == 0){
pDialog.setMessage("Getting Location");
pDialog.show();
latitude = mLastLocation.getLatitude();
longitude = mLastLocation.getLongitude();
if (latitude != 0 && longitude != 0){
stopLocationUpdates(); // unbind the locationlistner here or wherever you want as per your requirement.
pDialog.dismiss(); // location data received, dismiss dialog, call your method or perform your task.
}
}
}
}
我们反复尝试连接到 googleApiClient,即使它已经连接,以便我们可以获得 lastLocation 数据。这将取决于 LocationRequest 间隔。您也可以在 onLocationChanged 中获取位置数据,并从那里执行您的任务。
这与 Amit K. Saha 的回答有关,但对我来说,在我的一个 Lollipop
设备上,我一直收到 null
。所以我打开了地图应用程序,我看到下面的屏幕要求我打开所有爵士乐以改善我的位置。
一旦我这样做了一次,我的设备就能够通过一次调用 getLastLocation()
;
来接收位置
我想,对于那些可能还没有使用过他们的地图应用程序的用户来说,他们必须在安装应用程序时请求这些权限。
首先,创建一个LocationRequest
对象:
// Create the LocationRequest object
mLocationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(10 * 1000) // 10 seconds, in milliseconds
.setFastestInterval(1 * 1000); // 1 second, in milliseconds
然后,确保用户已授予使用位置的权限。如果是这样,从requestLocationUpdates
获取位置如下:
void getLocation() {
Location location = null;
if (ContextCompat.checkSelfPermission(activity, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 1);
/*TODO!! INSERT CODE TO PROMPT USER TO GIVE PERMISSION*/
} else {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
mLastLocation = location;
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient,this);
}
如果您只需要一个位置而不需要持续监控,请务必删除更新。这样,您将永远不会得到 null Location
.
有关详细信息,请转到 http://blog.teamtreehouse.com/beginners-guide-location-android。
如果您使用的是 Android Marshmallow (API 23) 或更新版本的 Android,您可能会遇到同样的问题,因为 未授予权限。您应该在 phone.
上明确 request permission at run time for location or, if it's a test project you can grant location permission from app settings
这里是准确的答案和解释。
LocationClient getLastLocation() return null
正如 post 所说,如果至少有一个客户端连接到它,融合的位置提供者将只维护后台位置。
但我们可以跳过启动 Google 地图应用程序的过程,通过以下方式获取最后位置。
我们需要做的是
- 我们必须从 FusedLocationProviderClient
请求位置更新
- 然后我们可以从FusedLocationProviderClient得到最后一个位置,它不会是空的。
请求位置
LocationRequest mLocationRequest = LocationRequest.create();
mLocationRequest.setInterval(60000);
mLocationRequest.setFastestInterval(5000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
LocationCallback mLocationCallback = new LocationCallback() {
@Override
public void onLocationResult(LocationResult locationResult) {
if (locationResult == null) {
return;
}
for (Location location : locationResult.getLocations()) {
if (location != null) {
//TODO: UI updates.
}
}
}
};
LocationServices.getFusedLocationProviderClient(context).requestLocationUpdates(mLocationRequest, mLocationCallback, null);
获取最后位置
LocationServices.getFusedLocationProviderClient(context).getLastLocation().addOnSuccessListener(new OnSuccessListener<Location>() {
@Override
public void onSuccess(Location location) {
//TODO: UI updates.
}
});
为获得最佳结果,请在 Activity 的 onStart() 中请求位置更新,然后您可以获得最后一个位置。
我正在使用以下代码根据 android 的最新文档获取位置
https://developer.android.com/training/location/retrieve-current https://developer.android.com/training/location/receive-location-updates
MainActivity.java
public class MainActivity extends AppCompatActivity {
private static final int REQUEST_CHECK_SETTINGS = 1;
private static final int REQUEST_GRANT_PERMISSION = 2;
private FusedLocationProviderClient fusedLocationClient;
LocationRequest locationRequest;
private Location currentLocation;
private LocationCallback locationCallback;
Button getUpdates,removeUpdates;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
createLocationRequest();
settingsCheck();
getUpdates = findViewById(R.id.button);
removeUpdates = findViewById(R.id.button2);
getUpdates.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED ) {
ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.ACCESS_FINE_LOCATION},REQUEST_GRANT_PERMISSION);
return;
}
if(locationCallback==null)
buildLocationCallback();
if(currentLocation==null)
fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, Looper.myLooper());
}
});
removeUpdates.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED ) {
ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.ACCESS_FINE_LOCATION},REQUEST_GRANT_PERMISSION);
return;
}
if(locationCallback!=null)
fusedLocationClient.removeLocationUpdates(locationCallback);
}
});
}
protected void createLocationRequest() {
locationRequest = LocationRequest.create();
locationRequest.setInterval(10000);
locationRequest.setFastestInterval(5000);
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
// Check for location settings
public void settingsCheck() {
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(locationRequest);
SettingsClient client = LocationServices.getSettingsClient(this);
Task<LocationSettingsResponse> task = client.checkLocationSettings(builder.build());
task.addOnSuccessListener(this, new OnSuccessListener<LocationSettingsResponse>() {
@Override
public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
// All location settings are satisfied. The client can initialize
// location requests here.
Log.d("TAG", "onSuccess: settingsCheck");
getCurrentLocation();
}
});
task.addOnFailureListener(this, new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
if (e instanceof ResolvableApiException) {
// Location settings are not satisfied, but this can be fixed
// by showing the user a dialog.
Log.d("TAG", "onFailure: settingsCheck");
try {
// Show the dialog by calling startResolutionForResult(),
// and check the result in onActivityResult().
ResolvableApiException resolvable = (ResolvableApiException) e;
resolvable.startResolutionForResult(MainActivity.this,
REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException sendEx) {
// Ignore the error.
}
}
}
});
}
public void getCurrentLocation(){
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.ACCESS_FINE_LOCATION},1);
return;
}
fusedLocationClient.getLastLocation()
.addOnSuccessListener(this, new OnSuccessListener<Location>() {
@Override
public void onSuccess(Location location) {
Log.d("TAG", "onSuccess: getLastLocation");
// Got last known location. In some rare situations this can be null.
if (location != null) {
currentLocation=location;
Log.d("TAG", "onSuccess:latitude "+location.getLatitude());
Log.d("TAG", "onSuccess:longitude "+location.getLongitude());
}else{
Log.d("TAG", "location is null");
buildLocationCallback();
}
}
});
}
private void buildLocationCallback() {
locationCallback = new LocationCallback() {
@Override
public void onLocationResult(LocationResult locationResult) {
if (locationResult == null) {
return;
}
for (Location location : locationResult.getLocations()) {
// Update UI with location data
currentLocation=location;
Log.d("TAG", "onLocationResult: "+currentLocation.getLatitude());
}
};
};
}
//called after user responds to location permission popup
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(requestCode==REQUEST_GRANT_PERMISSION){
getCurrentLocation();
}
}
//called after user responds to location settings popup
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.d("TAG", "onActivityResult: ");
if(requestCode==REQUEST_CHECK_SETTINGS && resultCode==RESULT_OK)
getCurrentLocation();
if(requestCode==REQUEST_CHECK_SETTINGS && resultCode==RESULT_CANCELED)
Toast.makeText(this, "Please enable Location settings...!!!", Toast.LENGTH_SHORT).show();
}}
XML file
<?xml version="1.0" encoding="utf-8"?><android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.locationexample.MainActivity">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="88dp"
android:text="getLocationUpdates"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.502"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="RemoveLocationUpdates"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button"
app:layout_constraintVertical_bias="0.363" /</android.support.constraint.ConstraintLayout>
Manifest File
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.locationexample">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
要发出单个位置请求,您可以使用
方法一->getCurrentLocation()
cancellationTokenSource = CancellationTokenSource()
val currentLocationTask = LocationServices
.getFusedLocationProviderClient(requireContext()).getCurrentLocation(
LocationRequest.PRIORITY_HIGH_ACCURACY,
cancellationTokenSource.token
)
您可以使用
取消请求
cancellationTokenSource.cancel()
方法二->setNumUpdates(1)
mLocationRequest
.setNumUpdates(1)
我的位置信息为空,我发现模拟器上没有安装地图应用程序。我安装了它并启用了设备位置,然后问题解决了
我安装了一个具有 google 播放服务并且可以运行的模拟器
Android - 科特林
If you need to get user location in android, I am using this my
function and suggest it:
// Get user location after getting permission.
private fun findUserLocation() {
if (ActivityCompat.checkSelfPermission(requireContext(),
Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(requireContext(),
Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED
) {
// TODO: Check location permission. Some one is missing.
}
else {
val locationRequest = LocationRequest.create() // Create location request.
locationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY // Set priority.
val locationCallback: LocationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult) {
for (location in locationResult.locations) {
if (location != null) {
// TODO: Show your code here.
// Such as:
val lat = location.latitude
val lon = location.longitude
}
}
}
}
// Create a location provider client and send request for getting location.
val client = LocationServices.getFusedLocationProviderClient(requireContext())
client.requestLocationUpdates(locationRequest, locationCallback, null)
}
}
我只想在我的 Android 项目中检索设备位置,为此我使用播放服务方法:
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder( MainSearchActivity.this )
.addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
@Override
public void onConnected( Bundle bundle ){
Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if( location == null ){
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, new LocationListener() {
@Override
public void onLocationChanged(Location location) {
lastLocation = location;
}
});
}
}
@Override
public void onConnectionSuspended( int i ){
}
})
.addOnConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() {
@Override
public void onConnectionFailed( ConnectionResult connectionResult ){
if( connectionResult.hasResolution() ){
try {
// Start an Activity that tries to resolve the error
connectionResult.startResolutionForResult(MainSearchActivity.this, CONNECTION_FAILURE_RESOLUTION_REQUEST);
}catch( IntentSender.SendIntentException e ){
e.printStackTrace();
}
}else{
Utils.logger("Location services connection failed with code " + connectionResult.getErrorCode(), Utils.LOG_DEBUG );
}
}
})
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
}
public Location retrieveLastLocation(){
Location loc = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if( loc == null)
{
}
return loc; //TODO: What if loc is null?
}
但 loc
变量始终为空。每次都在不同的手机上如此。另外 lastLocation
,我尝试在 onLocationChanged
中分配,永远不会改变。始终为空。
这些是我为应用设置的权限
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="com.vogella.android.locationapi.maps.permission.MAPS_RECEIVE" />
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
我只是不明白:为什么 LocationServices
无法检索位置?我在我测试过的所有三台设备上都启用了所有地理定位设置。
融合 Location Provider
只有在至少有一个客户端连接到它时才会保持后台位置。现在仅仅打开定位服务并不能保证存储最后已知的位置。
第一个客户端连接后,会立即尝试获取位置。如果您的 activity 是第一个连接的客户端并且 getLastLocation()
在 onConnected()
中立即被调用,那么第一个位置可能没有足够的时间到达..
我建议你先启动地图应用,这样至少有一些确认的位置,然后再测试你的应用。
我认为在显示的代码中有一个我看不到的小错误。
mGoogleApiClient
已构建但似乎未构建 connected.You 可以通过调用 mGoogleApiClient.isConnected()
来验证这一点。
您可以覆盖 onStart 方法并在那里调用连接。或者您可以覆盖 onResume()
,以防您希望在您的 activity 可见时访问该位置。
@Override
protected void onStart() {
super.onStart();
if (mGoogleApiClient != null) {
mGoogleApiClient.connect();
}
}
如果 getLastLocation() 始终返回 null,请尝试此 hack。我用它来解决我的问题。在 activity.
中实施 LocationListener(导入 com.google.android.gms.location.LocationListener)protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
Context mContext = this;
manager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
createLocationRequest();
mGoogleApiClient = new GoogleApiClient.Builder(mContext)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
}
private void createLocationRequest(){
mLocationRequest = LocationRequest.create();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(SET_INTERVAL);
mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
}
onStart 或 onResume(我更喜欢 onResume)
@Override
protected void onResume() {
super.onResume();
if (manager.isProviderEnabled(LocationManager.GPS_PROVIDER) ) {
if (mGoogleApiClient != null) {
mGoogleApiClient.connect();
}
}else{
// Showyourmesg();
}
}
@Override
protected void onPause() {
super.onPause();
if (mGoogleApiClient != null) {
mGoogleApiClient.disconnect();
}
}
protected void startLocationUpdates(){
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,
mLocationRequest,this);
}
protected void stopLocationUpdates() {
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient, this);
}
现在,在您的 onLocationChanged 方法中检查 googleApiClient 是否已连接。如果已连接,请断开连接,然后重新连接。
@Override
public void onLocationChanged(Location location) {
Log.d("SplashAct", "LocatinChngListner, loc: " + location.getLatitude() + "," + location.getLongitude());
if (mGoogleApiClient != null)
if (mGoogleApiClient.isConnected() || mGoogleApiClient.isConnecting()){
mGoogleApiClient.disconnect();
mGoogleApiClient.connect();
} else if (!mGoogleApiClient.isConnected()){
mGoogleApiClient.connect();
}
}
最后,在您的 onConntected() 方法中
@Override
public void onConnected(Bundle bundle) {
Log.d("ACTIVITY", "ApiClient: OnConnected");
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
mGoogleApiClient);
if (mLastLocation == null){
startLocationUpdates(); // bind interface if your are not getting the lastlocation. or bind as per your requirement.
}
if (mLastLocation != null){
while (latitude == 0 || longitude == 0){
pDialog.setMessage("Getting Location");
pDialog.show();
latitude = mLastLocation.getLatitude();
longitude = mLastLocation.getLongitude();
if (latitude != 0 && longitude != 0){
stopLocationUpdates(); // unbind the locationlistner here or wherever you want as per your requirement.
pDialog.dismiss(); // location data received, dismiss dialog, call your method or perform your task.
}
}
}
}
我们反复尝试连接到 googleApiClient,即使它已经连接,以便我们可以获得 lastLocation 数据。这将取决于 LocationRequest 间隔。您也可以在 onLocationChanged 中获取位置数据,并从那里执行您的任务。
这与 Amit K. Saha 的回答有关,但对我来说,在我的一个 Lollipop
设备上,我一直收到 null
。所以我打开了地图应用程序,我看到下面的屏幕要求我打开所有爵士乐以改善我的位置。
一旦我这样做了一次,我的设备就能够通过一次调用 getLastLocation()
;
我想,对于那些可能还没有使用过他们的地图应用程序的用户来说,他们必须在安装应用程序时请求这些权限。
首先,创建一个LocationRequest
对象:
// Create the LocationRequest object
mLocationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(10 * 1000) // 10 seconds, in milliseconds
.setFastestInterval(1 * 1000); // 1 second, in milliseconds
然后,确保用户已授予使用位置的权限。如果是这样,从requestLocationUpdates
获取位置如下:
void getLocation() {
Location location = null;
if (ContextCompat.checkSelfPermission(activity, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 1);
/*TODO!! INSERT CODE TO PROMPT USER TO GIVE PERMISSION*/
} else {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
mLastLocation = location;
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient,this);
}
如果您只需要一个位置而不需要持续监控,请务必删除更新。这样,您将永远不会得到 null Location
.
有关详细信息,请转到 http://blog.teamtreehouse.com/beginners-guide-location-android。
如果您使用的是 Android Marshmallow (API 23) 或更新版本的 Android,您可能会遇到同样的问题,因为 未授予权限。您应该在 phone.
上明确 request permission at run time for location or, if it's a test project you can grant location permission from app settings这里是准确的答案和解释。
LocationClient getLastLocation() return null
正如
但我们可以跳过启动 Google 地图应用程序的过程,通过以下方式获取最后位置。
我们需要做的是
- 我们必须从 FusedLocationProviderClient 请求位置更新
- 然后我们可以从FusedLocationProviderClient得到最后一个位置,它不会是空的。
请求位置
LocationRequest mLocationRequest = LocationRequest.create();
mLocationRequest.setInterval(60000);
mLocationRequest.setFastestInterval(5000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
LocationCallback mLocationCallback = new LocationCallback() {
@Override
public void onLocationResult(LocationResult locationResult) {
if (locationResult == null) {
return;
}
for (Location location : locationResult.getLocations()) {
if (location != null) {
//TODO: UI updates.
}
}
}
};
LocationServices.getFusedLocationProviderClient(context).requestLocationUpdates(mLocationRequest, mLocationCallback, null);
获取最后位置
LocationServices.getFusedLocationProviderClient(context).getLastLocation().addOnSuccessListener(new OnSuccessListener<Location>() {
@Override
public void onSuccess(Location location) {
//TODO: UI updates.
}
});
为获得最佳结果,请在 Activity 的 onStart() 中请求位置更新,然后您可以获得最后一个位置。
我正在使用以下代码根据 android 的最新文档获取位置 https://developer.android.com/training/location/retrieve-current https://developer.android.com/training/location/receive-location-updates
MainActivity.java
public class MainActivity extends AppCompatActivity {
private static final int REQUEST_CHECK_SETTINGS = 1;
private static final int REQUEST_GRANT_PERMISSION = 2;
private FusedLocationProviderClient fusedLocationClient;
LocationRequest locationRequest;
private Location currentLocation;
private LocationCallback locationCallback;
Button getUpdates,removeUpdates;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
createLocationRequest();
settingsCheck();
getUpdates = findViewById(R.id.button);
removeUpdates = findViewById(R.id.button2);
getUpdates.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED ) {
ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.ACCESS_FINE_LOCATION},REQUEST_GRANT_PERMISSION);
return;
}
if(locationCallback==null)
buildLocationCallback();
if(currentLocation==null)
fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, Looper.myLooper());
}
});
removeUpdates.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED ) {
ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.ACCESS_FINE_LOCATION},REQUEST_GRANT_PERMISSION);
return;
}
if(locationCallback!=null)
fusedLocationClient.removeLocationUpdates(locationCallback);
}
});
}
protected void createLocationRequest() {
locationRequest = LocationRequest.create();
locationRequest.setInterval(10000);
locationRequest.setFastestInterval(5000);
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
// Check for location settings
public void settingsCheck() {
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(locationRequest);
SettingsClient client = LocationServices.getSettingsClient(this);
Task<LocationSettingsResponse> task = client.checkLocationSettings(builder.build());
task.addOnSuccessListener(this, new OnSuccessListener<LocationSettingsResponse>() {
@Override
public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
// All location settings are satisfied. The client can initialize
// location requests here.
Log.d("TAG", "onSuccess: settingsCheck");
getCurrentLocation();
}
});
task.addOnFailureListener(this, new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
if (e instanceof ResolvableApiException) {
// Location settings are not satisfied, but this can be fixed
// by showing the user a dialog.
Log.d("TAG", "onFailure: settingsCheck");
try {
// Show the dialog by calling startResolutionForResult(),
// and check the result in onActivityResult().
ResolvableApiException resolvable = (ResolvableApiException) e;
resolvable.startResolutionForResult(MainActivity.this,
REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException sendEx) {
// Ignore the error.
}
}
}
});
}
public void getCurrentLocation(){
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.ACCESS_FINE_LOCATION},1);
return;
}
fusedLocationClient.getLastLocation()
.addOnSuccessListener(this, new OnSuccessListener<Location>() {
@Override
public void onSuccess(Location location) {
Log.d("TAG", "onSuccess: getLastLocation");
// Got last known location. In some rare situations this can be null.
if (location != null) {
currentLocation=location;
Log.d("TAG", "onSuccess:latitude "+location.getLatitude());
Log.d("TAG", "onSuccess:longitude "+location.getLongitude());
}else{
Log.d("TAG", "location is null");
buildLocationCallback();
}
}
});
}
private void buildLocationCallback() {
locationCallback = new LocationCallback() {
@Override
public void onLocationResult(LocationResult locationResult) {
if (locationResult == null) {
return;
}
for (Location location : locationResult.getLocations()) {
// Update UI with location data
currentLocation=location;
Log.d("TAG", "onLocationResult: "+currentLocation.getLatitude());
}
};
};
}
//called after user responds to location permission popup
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(requestCode==REQUEST_GRANT_PERMISSION){
getCurrentLocation();
}
}
//called after user responds to location settings popup
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.d("TAG", "onActivityResult: ");
if(requestCode==REQUEST_CHECK_SETTINGS && resultCode==RESULT_OK)
getCurrentLocation();
if(requestCode==REQUEST_CHECK_SETTINGS && resultCode==RESULT_CANCELED)
Toast.makeText(this, "Please enable Location settings...!!!", Toast.LENGTH_SHORT).show();
}}
XML file
<?xml version="1.0" encoding="utf-8"?><android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.locationexample.MainActivity">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="88dp"
android:text="getLocationUpdates"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.502"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="RemoveLocationUpdates"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button"
app:layout_constraintVertical_bias="0.363" /</android.support.constraint.ConstraintLayout>
Manifest File
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.locationexample">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
要发出单个位置请求,您可以使用
方法一->getCurrentLocation()
cancellationTokenSource = CancellationTokenSource()
val currentLocationTask = LocationServices
.getFusedLocationProviderClient(requireContext()).getCurrentLocation(
LocationRequest.PRIORITY_HIGH_ACCURACY,
cancellationTokenSource.token
)
您可以使用
取消请求cancellationTokenSource.cancel()
方法二->setNumUpdates(1)
mLocationRequest
.setNumUpdates(1)
我的位置信息为空,我发现模拟器上没有安装地图应用程序。我安装了它并启用了设备位置,然后问题解决了
我安装了一个具有 google 播放服务并且可以运行的模拟器
Android - 科特林
If you need to get user location in android, I am using this my function and suggest it:
// Get user location after getting permission.
private fun findUserLocation() {
if (ActivityCompat.checkSelfPermission(requireContext(),
Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(requireContext(),
Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED
) {
// TODO: Check location permission. Some one is missing.
}
else {
val locationRequest = LocationRequest.create() // Create location request.
locationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY // Set priority.
val locationCallback: LocationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult) {
for (location in locationResult.locations) {
if (location != null) {
// TODO: Show your code here.
// Such as:
val lat = location.latitude
val lon = location.longitude
}
}
}
}
// Create a location provider client and send request for getting location.
val client = LocationServices.getFusedLocationProviderClient(requireContext())
client.requestLocationUpdates(locationRequest, locationCallback, null)
}
}