Requesting location updates using FusedLocationProviderClient is not working, callback is never called

DeB*_*kIt 3 java gps android location fusedlocationproviderclient

I'm trying to use Firebase Cloud Messaging to send a command to my Android app that prompts it to determine its current location. This is done in the class FCMService.

The class SingleShotLocationProvider then performs the actual work by requesting location updates using the FusedLocationProviderClient. However, the callback fusedTrackerCallback is never called ever, although the necessary permissions are granted and GPS is switched on. Why?

FCMService class

public class FCMService extends FirebaseMessagingService {

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        Log.d("FCMService", "Message received");

            if(remoteMessage.getData().containsKey("command") && remoteMessage.getData().get("command").equalsIgnoreCase("locate")) {
                // get current location
                SingleShotLocationProvider locProv = new SingleShotLocationProvider(getApplicationContext());
                locProv.requestSingleUpdate();
                System.out.println("Requested single location update.");
            }

        }
    }

}
Run Code Online (Sandbox Code Playgroud)

SingleShotLocationProvider class

public class SingleShotLocationProvider {

    private Context context;

    final LocationManager locManager;
    private FusedLocationProviderClient mFusedLocationClient;
    private LocationCallback fusedTrackerCallback;

    public SingleShotLocationProvider(Context context) {
        this.context = context;
        mFusedLocationClient = LocationServices.getFusedLocationProviderClient(context);

        locManager = (LocationManager) context.getSystemService( Context.LOCATION_SERVICE );
        if (locManager != null && !locManager.isProviderEnabled(LocationManager.GPS_PROVIDER)){
            Log.e("SiSoLocProvider", "GPS IS NOT enabled.");
        } else {
            Log.d("SiSoLocProvider", "GPS is enabled.");
        }
    }

    @TargetApi(16)
    public void requestSingleUpdate() {
        Looper.prepare();

        // only works with SDK Version 23 or higher
        if (android.os.Build.VERSION.SDK_INT >= 23) {
            if (context.checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED || context.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                // permission is not granted
                Log.e("SiSoLocProvider", "Permission not granted.");
                return;
            } else {
                Log.d("SiSoLocProvider", "Permission granted.");
            }
        } else {
            Log.d("SiSoLocProvider", "SDK < 23, checking permissions should not be necessary");
        }

        final long startTime = System.currentTimeMillis();
        fusedTrackerCallback = new LocationCallback(){
            @Override
            public void onLocationResult(LocationResult locationResult) {
                if((locationResult.getLastLocation() != null) && (System.currentTimeMillis() <= startTime+30*1000)) {
                    System.out.println("LOCATION: " + locationResult.getLastLocation().getLatitude() + "|" + locationResult.getLastLocation().getLongitude());
                    System.out.println("ACCURACY: " + locationResult.getLastLocation().getAccuracy());
                    mFusedLocationClient.removeLocationUpdates(fusedTrackerCallback);
                } else {
                    System.out.println("LastKnownNull? :: " + (locationResult.getLastLocation() == null));
                    System.out.println("Time over? :: " + (System.currentTimeMillis() > startTime+30*1000));
                }
            }
        };

        LocationRequest req = new LocationRequest();
        req.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        req.setFastestInterval(2000);
        req.setInterval(2000);
        mFusedLocationClient.requestLocationUpdates(req, fusedTrackerCallback, null);
    }
}
Run Code Online (Sandbox Code Playgroud)

Output is:

//Message received
//GPS is enabled.
//Permission granted.
//Requested single location update.
Run Code Online (Sandbox Code Playgroud)

But nothing more then. Why? Is it perhaps because the permission was granted via the service application context?

Nhấ*_*ang 6

从您的代码中,我猜您想在后台线程中获取位置并接收结果。这是一个解决方案。

@TargetApi(16)
public void requestSingleUpdate() {
    // TODO: Comment-out this line.
    // Looper.prepare();

    // only works with SDK Version 23 or higher
    if (android.os.Build.VERSION.SDK_INT >= 23) {
        if (context.checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED || context.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            // permission is not granted
            Log.e("SiSoLocProvider", "Permission not granted.");
            return;
        } else {
            Log.d("SiSoLocProvider", "Permission granted.");
        }
    } else {
        Log.d("SiSoLocProvider", "SDK < 23, checking permissions should not be necessary");
    }

    // TODO: Start a background thread to receive location result.
    final HandlerThread handlerThread = new HandlerThread("RequestLocation");
    handlerThread.start();

    final long startTime = System.currentTimeMillis();
    fusedTrackerCallback = new LocationCallback() {
        @Override
        public void onLocationResult(LocationResult locationResult) {
            // TODO: Those lines of code will run on the background thread.
            if ((locationResult.getLastLocation() != null) && (System.currentTimeMillis() <= startTime + 30 * 1000)) {
                System.out.println("LOCATION: " + locationResult.getLastLocation().getLatitude() + "|" + locationResult.getLastLocation().getLongitude());
                System.out.println("ACCURACY: " + locationResult.getLastLocation().getAccuracy());
                mFusedLocationClient.removeLocationUpdates(fusedTrackerCallback);
            } else {
                System.out.println("LastKnownNull? :: " + (locationResult.getLastLocation() == null));
                System.out.println("Time over? :: " + (System.currentTimeMillis() > startTime + 30 * 1000));
            }
            // TODO: After receiving location result, remove the listener.
            mFusedLocationClient.removeLocationUpdates(this);

            // Release the background thread which receive the location result.
            handlerThread.quit();
        }
    };

    LocationRequest req = new LocationRequest();
    req.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    req.setFastestInterval(2000);
    req.setInterval(2000);
    // TODO: Pass looper of background thread indicates we want to receive location result in a background thread instead of UI thread.
    mFusedLocationClient.requestLocationUpdates(req, fusedTrackerCallback, handlerThread.getLooper());
}
Run Code Online (Sandbox Code Playgroud)

如果您想在 UI 线程上接收位置结果。

@TargetApi(16)
public void requestSingleUpdate() {
    // TODO: Comment-out this line.
    // Looper.prepare();

    // only works with SDK Version 23 or higher
    if (android.os.Build.VERSION.SDK_INT >= 23) {
        if (context.checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED || context.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            // permission is not granted
            Log.e("SiSoLocProvider", "Permission not granted.");
            return;
        } else {
            Log.d("SiSoLocProvider", "Permission granted.");
        }
    } else {
        Log.d("SiSoLocProvider", "SDK < 23, checking permissions should not be necessary");
    }

    final long startTime = System.currentTimeMillis();
    fusedTrackerCallback = new LocationCallback() {
        @Override
        public void onLocationResult(LocationResult locationResult) {
            // TODO: These lines of code will run on UI thread.
            if ((locationResult.getLastLocation() != null) && (System.currentTimeMillis() <= startTime + 30 * 1000)) {
                System.out.println("LOCATION: " + locationResult.getLastLocation().getLatitude() + "|" + locationResult.getLastLocation().getLongitude());
                System.out.println("ACCURACY: " + locationResult.getLastLocation().getAccuracy());
                mFusedLocationClient.removeLocationUpdates(fusedTrackerCallback);
            } else {
                System.out.println("LastKnownNull? :: " + (locationResult.getLastLocation() == null));
                System.out.println("Time over? :: " + (System.currentTimeMillis() > startTime + 30 * 1000));
            }

            // TODO: After receiving location result, remove the listener.
            mFusedLocationClient.removeLocationUpdates(this);
        }
    };

    LocationRequest req = new LocationRequest();
    req.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    req.setFastestInterval(2000);
    req.setInterval(2000);
    // Receive location result on UI thread.
    mFusedLocationClient.requestLocationUpdates(req, fusedTrackerCallback, Looper.getMainLooper());
}
Run Code Online (Sandbox Code Playgroud)

我添加了以TODO:关键字开头的每条评论来解释我的意图。

  • 非常感谢!事实上,运行位置请求的线程是问题所在。您的解决方案立即生效,无需任何进一步调整。 (3认同)
  • 谢谢你。一段时间以来,我一直在为位置问题而苦苦挣扎。线程就是答案! (2认同)