无法使用 Google 的融合位置 API 获取位置
Posted
技术标签:
【中文标题】无法使用 Google 的融合位置 API 获取位置【英文标题】:Unable to get location using Google's fused location API 【发布时间】:2016-09-01 12:07:34 【问题描述】:我正在尝试使用 Google 的融合位置 API 获取我的位置。为此,我创建了两个类。一个是 MainActivity,第二个是 FusedLocationService,其中 MainActivity 是主类。但我将经度和纬度设为 0.0。所以请帮助我。
这是我的 MainActivity 代码:-
public class MainActivity extends AppCompatActivity
TextView tvLocation;
FusedLocationService fusedLocationService;
double latitude;
double longitude;
String locationResult = "";
Location location;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvLocation = (TextView) findViewById(R.id.tvLocation);
fusedLocationService = new FusedLocationService(this);
location = fusedLocationService.getLocation();
if (null != location)
latitude = location.getLatitude();
longitude = location.getLongitude();
locationResult = "Latitude: " + latitude + "\n" +
"Longitude: " + longitude + "\n";
else
Timber.e("-error-%s", "Location Not Available!");
locationResult = "Location Not Available!";
Log.e("Lati ", String.valueOf(latitude));
Log.e("longi ", String.valueOf(longitude));
tvLocation.setText(locationResult);
这是我的 FusedLocationService 类:-
public class FusedLocationService implements LocationListener, GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener
private static final long INTERVAL = 1000 * 30; //30sec
private static final long FASTEST_INTERVAL = 1000 * 5; // 5sec
Activity mActivity;
public LocationRequest locationRequest;
public GoogleApiClient googleApiClient;
public Location location;
public FusedLocationProviderApi fusedLocationProviderApi = LocationServices.FusedLocationApi;
public FusedLocationService(Activity activity)
Timber.plant(new Timber.DebugTree());
locationRequest = LocationRequest.create();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(INTERVAL);
locationRequest.setFastestInterval(FASTEST_INTERVAL);
mActivity = activity;
googleApiClient = new GoogleApiClient.Builder(mActivity)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
if (googleApiClient != null)
googleApiClient.connect();
@Override
public void onConnected(Bundle connectionHint)
Log.e("-onConnected-", "connected now");
location = fusedLocationProviderApi.getLastLocation(googleApiClient);
fusedLocationProviderApi.requestLocationUpdates(googleApiClient, locationRequest, this);
@Override
public void onLocationChanged(Location location)
public Location getLocation()
return location;
@Override
public void onConnectionSuspended(int i)
@Override
public void onConnectionFailed(ConnectionResult connectionResult)
我已在 gradle 文件夹中的清单和 lib 中包含权限。 所以请帮忙。提前谢谢你
【问题讨论】:
在onConnected
方法中检查此代码googleApiClient.isConnected()
。如果它返回false,那么应该有一个禁用位置的情况,可能是在电话或谷歌服务的设置中。
【参考方案1】:
缺少对新位置的引用:
@Override
public void onLocationChanged(Location location)
this.location = location;
位置更新也是异步。因此,您需要类似活动的回调。
编辑:
还要检查 Google Play 服务是否可用。你可以像这样创建一个方法:
public boolean checkPlayServices()
return GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context) == ConnectionResult.SUCCESS;
见Google documentation
【讨论】:
感谢您的回答,但在添加 this.location = location 到 onLocationChanged @momo 后仍然是同样的问题 不要在Activity
的onCreate()
中调用location = fusedLocationService.getLocation();
。这不起作用,因为该位置不是立即可用的。事实上,不要做任何需要onCreate()
中的位置的事情。当人们解释时,您只有在 onLocationChanged(Location location)
被调用后才有位置。重新设计您的代码,以便处理位置的任何内容仅在调用 onLocationChanged()
后运行。【参考方案2】:
简短说明
您正在获取全局纬度和经度变量的默认值
double latitude;
double longitude;
详细解释
当你实例化 FusedLocationService 类时
fusedLocationService = new FusedLocationService(this);
它构建 google api 客户端然后尝试连接
public FusedLocationService(Activity activity)
...
googleApiClient = new GoogleApiClient.Builder(mActivity)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
if (googleApiClient != null)
googleApiClient.connect();
连接成功后,发出定位请求
@Override
public void onConnected(Bundle connectionHint)
Log.e("-onConnected-", "connected now");
location = fusedLocationProviderApi.getLastLocation(googleApiClient);
fusedLocationProviderApi.requestLocationUpdates(googleApiClient, locationRequest, this);
连接google api,接收位置是异步操作。
这意味着,你必须倾向于他们的回调
但是在初始化 FusedLocationService 类之后,您正在使用纬度经度变量。所以这就是为什么你得到 0.0 作为纬度和经度。
Log.e("Lati ", String.valueOf(latitude));
Log.e("longi ", String.valueOf(longitude));
tvLocation.setText(locationResult);
编辑——收尾工作
首先,您可以删除或移动这些代码。您正在处理异步操作。
Log.e("Lati ", String.valueOf(latitude));
Log.e("longi ", String.valueOf(longitude));
tvLocation.setText(locationResult);
当 google api 连接时,检查之前收到的位置并更新你的用户界面(如果有)
@Override
public void onConnected(Bundle connectionHint)
...
Location location = fusedLocationProviderApi.getLastLocation(googleApiClient);
// Provider could return null, because it tries to get location if any
if(location != null)
// UPDATE YOUR UI
fusedLocationProviderApi.requestLocationUpdates(googleApiClient, locationRequest, this);
收到新位置后,更新您的用户界面
@Override
public void onLocationChanged(Location location)
// You have received fresh location
// UPDATE YOUR UI
还可以查看link,您会更好地理解我提到的各个方面。
【讨论】:
感谢您的解释。那么你能给我提供解决这个问题的方法吗?【参考方案3】:我创建了一个名为 LocationActivity 的类
public class LocationActivitity extends AppCompatActivity
implements LocationListener,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener
final String TAG = "GPS";
private long UPDATE_INTERVAL = 2 * 1000; /* 10 secs */
private long FASTEST_INTERVAL = 2000; /* 2 sec */
static final int MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION = 1;
GoogleApiClient gac;
LocationRequest locationRequest;
public String tvLatitude, tvLongitude, tvTime;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
isGooglePlayServicesAvailable();
if(!isLocationEnabled())
showAlert();
locationRequest = new LocationRequest();
locationRequest.setInterval(UPDATE_INTERVAL);
locationRequest.setFastestInterval(FASTEST_INTERVAL);
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
gac = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
@Override
protected void onStart()
gac.connect();
super.onStart();
@Override
protected void onStop()
gac.disconnect();
super.onStop();
@Override
public void onLocationChanged(Location location)
if (location != null)
updateUI(location);
@Override
public void onConnected(@Nullable Bundle bundle)
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,
MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
return;
Log.d(TAG, "onConnected");
Location ll = LocationServices.FusedLocationApi.getLastLocation(gac);
Log.d(TAG, "LastLocation: " + (ll == null ? "NO LastLocation" : ll.toString()));
LocationServices.FusedLocationApi.requestLocationUpdates(gac, locationRequest, this);
@Override
public void onRequestPermissionsResult(
int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)
switch (requestCode)
case MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION:
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
Toast.makeText(this, "Permission was granted!", Toast.LENGTH_LONG).show();
try
LocationServices.FusedLocationApi.requestLocationUpdates(
gac, locationRequest, this);
catch (SecurityException e)
Toast.makeText(this, "SecurityException:\n" + e.toString(), Toast.LENGTH_LONG).show();
else
Toast.makeText(this, "Permission denied!", Toast.LENGTH_LONG).show();
return;
@Override
public void onConnectionSuspended(int i)
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult)
Toast.makeText(this, "onConnectionFailed: \n" + connectionResult.toString(),
Toast.LENGTH_LONG).show();
Log.d("DDD", connectionResult.toString());
private void updateUI(Location loc)
Log.d(TAG, "updateUI");
tvLatitude=loc.getLatitude()+"";
tvLongitude=loc.getLongitude()+"";
//tvTime.setText(DateFormat.getTimeInstance().format(loc.getTime()));
private boolean isLocationEnabled()
LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) ||
locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
private boolean isGooglePlayServicesAvailable()
final int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;
GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance();
int resultCode = apiAvailability.isGooglePlayServicesAvailable(this);
if (resultCode != ConnectionResult.SUCCESS)
if (apiAvailability.isUserResolvableError(resultCode))
apiAvailability.getErrorDialog(this, resultCode, PLAY_SERVICES_RESOLUTION_REQUEST)
.show();
else
Log.d(TAG, "This device is not supported.");
finish();
return false;
Log.d(TAG, "This device is supported.");
return true;
private void showAlert()
final AlertDialog.Builder dialog = new AlertDialog.Builder(this);
dialog.setTitle("Enable Location")
.setMessage("Your Locations Settings is set to 'Off'.\nPlease Enable Location to " +
"use this app")
.setPositiveButton("Location Settings", new DialogInterface.OnClickListener()
@Override
public void onClick(DialogInterface paramDialogInterface, int paramInt)
Intent myIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(myIntent);
finish();
)
.setNegativeButton("Cancel", new DialogInterface.OnClickListener()
@Override
public void onClick(DialogInterface paramDialogInterface, int paramInt)
);
dialog.show();
这是获取位置的方法 updateUI(Location loc)。
【讨论】:
以上是关于无法使用 Google 的融合位置 API 获取位置的主要内容,如果未能解决你的问题,请参考以下文章
使用 Google Play 服务我可以在离线模式下获取最新位置吗(FusedLocationProvider Api)
Google Maps API v3和fusion图层:获取行数据