Как получить текущее местоположение, используя отдельный класс в Android

Мне нужно получить текущее местоположение, используя отдельный класс, которого нет в 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)

person Ishan Fernando    schedule 05.04.2016    source источник
comment
Что такое вывод Logcat?   -  person chRyNaN    schedule 05.04.2016
comment
Исключение нулевого указателя @chRyNaN   -  person Ishan Fernando    schedule 05.04.2016
comment
Поместите все журналы в свой вопрос. Вот ссылка, отвечающая на вопрос, что такое NullPointerException, stackoverflow.com/q/218384/1478764   -  person chRyNaN    schedule 05.04.2016
comment
Прочитайте журналы, первая строка гласит: java.lang.NullPointerException at com.example.ishanfx.departmentapp.HomeActivity.onOptionsItemSelected(HomeActivity.java:172), которая сообщает вам, что проблема, с которой вы столкнулись, находится в строке 172 класса HomeActivity. Обратитесь к ссылке, которую я разместил в предыдущем комментарии, чтобы узнать, что такое NullPointerException.   -  person chRyNaN    schedule 06.04.2016
comment
Я думаю, у вас есть import android.location.LocationListener; что неправильно. Используйте fusedApi locationListener, например import com.google.android.gms.location.LocationListener;   -  person AndroidGeek    schedule 27.01.2017


Ответы (4)


Я обновил класс выше чистым способом.

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);
}
person AndroidGeek    schedule 01.02.2017
comment
Да, это требует контекста. просто передайте ему контекст службы. и ты можешь идти - person AndroidGeek; 26.04.2019

Для запуска события onConnected требуется некоторое время. Вы должны дать ему немного времени, прежде чем делать тосты. Я бы добавил свойство isConnected в ваш класс LocationHandler следующим образом:

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();
}
person Alexander Hart    schedule 05.04.2016
comment
Это замораживает приложение. - person Ishan Fernando; 06.04.2016
comment
создать интерфейс (обратный вызов) и при подключении он возвращает. appLocationManager .setOnConnectedListener (новый OnConnected(){}) - person AndroidGeek; 27.01.2017

Вы должны установить значение широты и долготы с помощью установщика, а затем получить использование геттера.. поскольку значение не устанавливается, геттер возвращает нулевое значение, таким образом, исключение нулевого указателя.

person andy bit1    schedule 02.07.2018

Вот еще одно решение с 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);
}
person AbuBakar Siddiq    schedule 03.04.2019