如何在 Android 中使用单独的类获取当前位置
Posted
技术标签:
【中文标题】如何在 Android 中使用单独的类获取当前位置【英文标题】:How to get Current Location using seperate class in Android 【发布时间】:2016-07-26 00:05:06 【问题描述】:我需要使用不在 Activity 中的单独类获取当前位置。这是我的代码,它不起作用。任何人都有解决此问题的想法。当我尝试获取位置详细信息时,此应用程序总是崩溃。
package com.example.ishanfx.departmentapp.network;
import android.content.Context;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
public class LocationHandler implements LocationListener,GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener
private LocationManager locationManager;
Location mLastLocation;
LocationRequest mLocationRequest;
private String latitude;
private String longitude;
Context context;
private static GoogleApiClient mGoogleApiClient;
public LocationHandler(Context context)
this.context = context;
locationManager = (LocationManager) context
.getSystemService(Context.LOCATION_SERVICE);
buildGoogleApiClient();
protected synchronized void buildGoogleApiClient()
mGoogleApiClient = new GoogleApiClient.Builder(context)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
private void setMostRecentLocation(Location lastKnownLocation)
public String getLatitude()
return latitude;
public String getLongitude()
return longitude;
@Override
public void onLocationChanged(Location location)
double lon = (double) (location.getLongitude());
double lat = (double) (location.getLatitude());
latitude = lat + "";
longitude = lon + "";
/*
* (non-Javadoc)
*
* @see
* android.location.LocationListener#onProviderDisabled(java.lang.String)
*/
@Override
public void onProviderDisabled(String arg0)
// TODO Auto-generated method stub
/*
* (non-Javadoc)
*
* @see
* android.location.LocationListener#onProviderEnabled(java.lang.String)
*/
@Override
public void onProviderEnabled(String arg0)
// TODO Auto-generated method stub
@Override
public void onStatusChanged(String arg0, int arg1, Bundle arg2)
// TODO Auto-generated method stub
@Override
public void onConnected(Bundle bundle)
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
mGoogleApiClient);
if (mLastLocation != null)
latitude =String.valueOf(mLastLocation.getLatitude());
longitude = String.valueOf(mLastLocation.getLongitude());
@Override
public void onConnectionSuspended(int i)
@Override
public void onConnectionFailed(ConnectionResult connectionResult)
这是mainActivity。当我调用这个应用程序时会崩溃。
LocationHandler appLocationManager = new LocationHandler(HomeActivity.this);
Toast.makeText(getApplicationContext(), appLocationManager.getLatitude().toString(), Toast.LENGTH_SHORT).show();
Toast.makeText(getApplicationContext(), appLocationManager.getLongitude().toString(), Toast.LENGTH_SHORT).show();
这是日志
FATAL EXCEPTION: main
java.lang.NullPointerException
at com.example.ishanfx.departmentapp.HomeActivity.onOptionsItemSelected(HomeActivity.java:172)
at android.app.Activity.onMenuItemSelected(Activity.java:2502)
at android.support.v4.app.FragmentActivity.onMenuItemSelected(FragmentActivity.java:361)
at android.support.v7.app.AppCompatActivity.onMenuItemSelected(AppCompatActivity.java:147)
at android.support.v7.view.WindowCallbackWrapper.onMenuItemSelected(WindowCallbackWrapper.java:100)
at android.support.v7.view.WindowCallbackWrapper.onMenuItemSelected(WindowCallbackWrapper.java:100)
at android.support.v7.app.ToolbarActionBar$2.onMenuItemClick(ToolbarActionBar.java:68)
at android.support.v7.widget.Toolbar$1.onMenuItemClick(Toolbar.java:172)
at android.support.v7.widget.ActionMenuView$MenuBuilderCallback.onMenuItemSelected(ActionMenuView.java:760)
at android.support.v7.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:811)
at android.support.v7.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:152)
at android.support.v7.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:958)
at android.support.v7.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:948)
at android.support.v7.view.menu.MenuPopupHelper.onItemClick(MenuPopupHelper.java:191)
at android.widget.AdapterView.performItemClick(AdapterView.java:292)
at android.widget.AbsListView.performItemClick(AbsListView.java:1065)
at android.widget.AbsListView$PerformClick.run(AbsListView.java:2522)
at android.widget.AbsListView$1.run(AbsListView.java:3183)
at android.os.Handler.handleCallback(Handler.java:605)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4441)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
at dalvik.system.NativeStart.main(Native Method)
【问题讨论】:
什么是 Logcat 输出? 空指针异常@chRyNaN 将整个日志放入您的问题中。这是一个回答 NullPointerException 是什么的链接,***.com/q/218384/1478764 阅读日志,第一行声明:java.lang.NullPointerException at com.example.ishanfx.departmentapp.HomeActivity.onOptionsItemSelected(HomeActivity.java:172)
告诉您您面临的问题是在 HomeActivity 类第 172 行。请参阅我在之前评论中发布的链接,了解 NullPointerException 的含义是。
我认为你有 import android.location.LocationListener;这是错误的。使用 fusedApi locationListener like import com.google.android.gms.location.LocationListener;
【参考方案1】:
我以干净的方式更新了上面的课程。
public class LocationHandler implements LocationListener,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener
private Context mContext;
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
private OnLocationUpdateListener onLocationUpdateListener;
public LocationHandler(Context mContext)
this.mContext = mContext;
buildGoogleApiClient();
createLocationRequest();
protected synchronized void buildGoogleApiClient()
mGoogleApiClient = new GoogleApiClient.Builder(mContext)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
public void startLocationUpdates(Context mContext)
if (ActivityCompat.checkSelfPermission(mContext,
Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(mContext,
Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
return;
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
private void stopLocationUpdate(Context mContext)
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient, this);
//other new Methods but not using right now..
protected void createLocationRequest()
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(10000);//set the interval in which you want to get locations
mLocationRequest.setFastestInterval(5000);//if a location is available sooner you can get it (i.e. another app is using the location services)
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
@Override
public void onConnected(@Nullable Bundle bundle)
startLocationUpdates(mContext);
@Override
public void onConnectionSuspended(int i)
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult)
@Override
public void onLocationChanged(Location location)
if(mGoogleApiClient.isConnected() && onLocationUpdateListener != null)
onLocationUpdateListener.onLocationChange(location);
public void setOnLocationUpdateListener(OnLocationUpdateListener onLocationUpdateListener)
this.onLocationUpdateListener = onLocationUpdateListener;
OnLocationUpdateListener 在哪里
public interface OnLocationUpdateListener
void onLocationChange(Location location);
void onError(EnumUtil.ErrorType errorType);
【讨论】:
是的,它需要一个 context 。只需将服务上下文传递给它。你很高兴【参考方案2】:onConnected 事件触发需要一点时间。 在烤面包之前,你需要给它一点时间。 我会向您的 LocationHandler 类添加一个 isConnected 属性,如下所示:
private boolean isconnected = false;
public boolean isConnected()
return isconnected;
@Override
public void onConnected(Bundle bundle)
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
mGoogleApiClient);
if (mLastLocation != null)
latitude =String.valueOf(mLastLocation.getLatitude());
longitude = String.valueOf(mLastLocation.getLongitude());
this.isconnected = true;
然后在MainActivity中
LocationHandler appLocationManager = new LocationHandler(HomeActivity.this);
while(!appLocationManager.isConnected())
// wait for a bit
if (appLocationManager.isConnected())
Toast.makeText(getApplicationContext(), appLocationManager.getLatitude().toString(), Toast.LENGTH_SHORT).show();
Toast.makeText(getApplicationContext(), appLocationManager.getLongitude().toString(), Toast.LENGTH_SHORT).show();
【讨论】:
它冻结了应用程序。 创建一个接口(回调)并在连接时返回。 appLocationManager .setOnConnectedListener(new OnConnected())【参考方案3】:您必须使用 setter 设置纬度和经度的值,然后使用 getter.. 因为没有设置值,所以 getter 返回空值,因此空指针异常。
【讨论】:
【参考方案4】:这是另一个使用 FusedLocationProviderClient
的解决方案,因为 FusedLocationApi
已弃用。
public class LocationHandler
private Activity activity;
private FusedLocationProviderClient mFusedLocationProviderClient;
private Location mLastKnownLocation;
private LocationCallback mLocationCallback;
private LocationRequest mLocationRequest;
private OnLocationUpdateListener onLocationUpdateListener;
private boolean updateStartedInternally = false;
public LocationHandler(Activity activity, OnLocationUpdateListener onLocationUpdateListener)
this.activity = activity;
this.onLocationUpdateListener = onLocationUpdateListener;
mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(activity);
createLocationRequest();
getDeviceLocation();
mLocationCallback = new LocationCallback()
@Override
public void onLocationResult(LocationResult locationResult)
List<Location> locationList = locationResult.getLocations();
if (locationList.size() > 0)
//The last location in the list is the newest
Location location = locationList.get(locationList.size() - 1);
mLastKnownLocation = location;
if (onLocationUpdateListener != null)
onLocationUpdateListener.onLocationChange(location);
if(updateStartedInternally)
stopLocationUpdate();
;
private void getDeviceLocation()
/*
* Get the best and most recent location of the device, which may be null in rare
* cases when a location is not available.
*/
try
Task locationResult = mFusedLocationProviderClient.getLastLocation();
locationResult.addOnCompleteListener(activity, task ->
if (task.isSuccessful())
// Set the map's camera position to the current location of the device.
mLastKnownLocation = (Location) task.getResult();
if (mLastKnownLocation == null)
updateStartedInternally = true;
mFusedLocationProviderClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.myLooper());
else
onLocationUpdateListener.onLocationChange(mLastKnownLocation);
else
onLocationUpdateListener.onError("Can't get Location");
);
catch (SecurityException e)
Log.e("Exception: %s", e.getMessage());
onLocationUpdateListener.onError(e.getMessage());
public void startLocationUpdates()
if (ActivityCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
return;
updateStartedInternally = false;
mFusedLocationProviderClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.myLooper());
private void stopLocationUpdate()
mFusedLocationProviderClient.removeLocationUpdates(mLocationCallback);
//other new Methods but not using right now..
protected void createLocationRequest()
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(10000);//set the interval in which you want to get locations
mLocationRequest.setFastestInterval(5000);//if a location is available sooner you can get it (i.e. another app is using the location services)
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
OnLocationUpdateListener 在哪里
public interface OnLocationUpdateListener
void onLocationChange(Location location);
void onError(String error);
【讨论】:
以上是关于如何在 Android 中使用单独的类获取当前位置的主要内容,如果未能解决你的问题,请参考以下文章
如何在 php 中获取当前位置 lat -long 值以便在 android 中使用