【问题标题】:Requesting location updates using FusedLocationProviderClient is not working, callback is never called使用 FusedLocationProviderClient 请求位置更新不起作用,永远不会调用回调
【发布时间】:2018-08-24 12:36:13
【问题描述】:

我正在尝试使用 Firebase Cloud Messaging 向我的 Android 应用发送命令,提示它确定当前的 location。这是在 FCMService 类中完成的。

SingleShotLocationProvider 然后通过使用FusedLocationProviderClient 请求location 更新来执行实际工作。然而,回调fusedTrackerCallback 永远不会被调用,尽管必要的permissions 被授予并且GPS 被打开。为什么?

FCMService 类

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.");
            }

        }
    }

}

SingleShotLocationProvider 类

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);
    }
}

输出为:

//Message received
//GPS is enabled.
//Permission granted.
//Requested single location update.

但仅此而已。为什么?是不是因为permission 是通过service application context 授予的?

【问题讨论】:

  • 您是否在清单中添加了位置权限访问?
  • 您是否尝试在requestSingleUpdate 末尾添加Looper.loop();
  • @droidev 当然,我将 ACCESS_COARSE_LOCATION 和 ACCESS_FINE_LOCATION 添加到清单中,在 manifest 标记内,但在 application 标记之外。
  • 没错。还是行不通?检查您的 logcat 中是否有任何内容
  • @LevonPetrosyan 第三个参数应该是Looper 类型,但Looper.loop()void 类型。文档还说,如果你留下第三个参数null,调用线程会处理它。这应该不是问题,除非调用线程(FCM 服务)以某种方式无法存活足够长的时间来等待回调。

标签: java android gps location fusedlocationproviderclient


【解决方案1】:

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

@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());
}

如果你想在 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());
}

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

【讨论】:

  • 非常感谢!事实上,运行位置请求的线程是问题所在。您的解决方案无需任何进一步调整即可立即生效。
  • 谢谢。一段时间以来,我一直在为位置问题而苦苦挣扎。话题就是答案!
  • 你好。非常非常感谢你!你节省了我的时间。
猜你喜欢
  • 2023-03-08
  • 1970-01-01
  • 1970-01-01
  • 2012-02-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-06
  • 2017-07-26
相关资源
最近更新 更多