Java FusedLocationProviderClient.RemovelocationUpdate始终返回失败

Java FusedLocationProviderClient.RemovelocationUpdate始终返回失败,java,android,android-location,Java,Android,Android Location,我有一个活动扩展了一个名为LocationAwareActivity的基本类,所有这些LocationAwareActivity活动都是创建一个位置服务客户端 LocationServices.getFusedLocationProviderClient和侦听 位置更新 此活动的来源在此处 当活动被销毁时,它调用removeLocationUpdates。我发现的是 removeLocationUpdate返回一个始终返回not successful的任务 更令人担忧的是,由于没有删除位置活

我有一个
活动
扩展了一个名为
LocationAwareActivity
的基本
,所有这些
LocationAwareActivity
活动都是创建一个位置服务客户端

LocationServices.getFusedLocationProviderClient
侦听
位置更新

此活动的来源在此处

当活动被销毁时,它调用
removeLocationUpdates
。我发现的是

  • removeLocationUpdate
    返回一个始终返回not successful的任务
  • 更令人担忧的是,由于没有删除位置活动,
    活动
    没有被垃圾收集
-因此,如果我启动从
locationawaractivity
继承的任何活动,该活动始终保持在堆上

因此,问题是什么是停止接收位置更新的正确方法,从而允许对
活动
进行垃圾收集


可以在此处访问此项目的整个源代码-

任务对象返回false的原因是在您的
stopLocationUpdates
方法中,您再次创建本地
**LocationCallback**
引用,然后将此引用用作
locationProviderClient.removeLocationUpdates(cL)中的参数
locationProviderClient中从不存在本地LocationCallBack

因此,您需要做的是,不必创建另一个LocationCallBack对象,而必须传递在
startLocationUpdates
方法中实例化的同一个全局对象

您的代码应该是这样的

final Task<Void> voidTask = locationProviderClient.removeLocationUpdates(locationCallback);
final Task voidTask=locationProviderClient.RemovelocationUpdate(locationCallback);

Hi@Subodh Nijsure请检查以下代码并粘贴到您的代码中,检查后:

final Task<Void> voidTask = locationProviderClient.removeLocationUpdates(locationCallback);
                voidTask.addOnCompleteListener(new OnCompleteListener<Void>() {
                    @Override
                    public void onComplete(@NonNull Task<Void> task) {
                        Log.e(TAG, "addOnCompleteListener: "+task.isComplete());
                    }
                });

                voidTask.addOnSuccessListener(new OnSuccessListener<Void>() {
                    @Override
                    public void onSuccess(Void aVoid) {
                        Log.e(TAG, "addOnSuccessListener: " );
                    }
                });

                voidTask.addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        Log.e(TAG, "addOnFailureListener: ");
                    }
                });
final Task voidTask=locationProviderClient.RemovelocationUpdate(locationCallback);
voidTask.addOnCompleteListener(新的OnCompleteListener(){
@凌驾
未完成的公共void(@NonNull任务){
Log.e(标记“addOnCompleteListener:”+task.isComplete());
}
});
voidTask.addOnSuccessListener(新的OnSuccessListener(){
@凌驾
成功时公开作废(作废避免){
Log.e(标记“addOnSuccessListener:”);
}
});
voidTask.addOnFailureListener(新的OnFailureListener(){
@凌驾
public void onFailure(@NonNull异常e){
Log.e(标签“addOnFailureListener:”);
}
});
我认为voidTask.issusccessful()当您当时将此侦听器放入时,此方法不起作用。它工作正常,而且我还看到它在内存中释放了前一个活动时的所有内存

当您重定向到任何活动时,请stopLocationUpdates()调用onPause()一次,并从其他方法(如onDestroy()、onStop()中删除,因为它只停止一次,所以为什么要调用多次呢


希望这对您有所帮助。

RemovelocationUpdate中,您应该通过locationCallback,当前的实现是错误的

不过,还有可能在其他地方发生内存泄漏。你应该尝试在你的应用程序中集成,它可以给你引用树,并告诉你哪个字段或侦听器导致了内存泄漏。 你可以参考

public void stopLocationUpdates(){
if(locationProviderClient!=null){
试一试{
最终任务voidTask=locationProviderClient.RemovelocationUpdate(locationCallback);
if(voidTask.isSuccessful()){
Log.d(标记“StopLocation更新成功!”);
}否则{
Log.d(标记“StopLocation更新不成功!”+voidTask.toString());
}
}
catch(SecurityException exp){
Log.d(标记“RemovelocationUpdate时的安全异常”);
}
}
}

通过查看存储库中的代码,我发现您的设计中存在一些问题,这些问题可能会导致您的
活动泄漏

1) 您正在使用两个不同的
位置回调
。一个在start方法中,一个在stop方法中,但实际上应该使用相同的方法。因此,一次实例化它就足够了,并且在删除
LocationCallback
时,也可能导致
任务的成功

2) 由于您使用
匿名类两次实例化
LocationCallback
,因此即使您完成了包含的类,也会保留内部类的非静态引用,这会导致
内存泄漏
。你可以阅读更多关于这方面的内容

3) IMHO使用单独的manager类来处理位置请求比抽象
活动
更好

说这是我的

解决方案 GpsManager.java

public class GpsManager extends LocationCallback {

    private FusedLocationProviderClient client;
    private Callback callback;

    public interface Callback {
        void onLocationResult(LocationResult locationResult);
    }

    public boolean start(Context context, Callback callback) {
        this.callback = callback;
        client = LocationServices.getFusedLocationProviderClient(context);
        if (!checkLocationPermission(context)) return false;
        client.requestLocationUpdates(getLocationRequest(), this, null);
        return true;
    }

    public void stop() {
        client.removeLocationUpdates(this);
    }

    @Override
    public void onLocationResult(LocationResult locationResult) {
        callback.onLocationResult(locationResult);
    }

    private boolean checkLocationPermission(Context context) {
        int permissionCheck = ContextCompat.checkSelfPermission(
                context, android.Manifest.permission.ACCESS_FINE_LOCATION);
        return permissionCheck == PackageManager.PERMISSION_GRANTED;
    }

    private LocationRequest getLocationRequest() {
        return LocationRequest.create()
                .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
                .setInterval(30_000L)
                .setFastestInterval(20_000L);
    }
}
public class MapsActivity extends AppCompatActivity implements GpsManager.Callback  {

    private static final int PERMISSION_REQUEST_FINE_LOCATION = 1;
    private GpsManager mGpsManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...
        mGpsManager = new GpsManager(getApplicationContext(), this);

        // check if user gave permissions, otherwise ask via dialog
        if (!checkPermission()) {
            getLocationPermissions();
            return;
        }

        mGpsManager.start();
        ...
    }

    @Override
    protected void onStop() {
        super.onStop();
        mGpsManager.stop();
    }

    @Override
    public void onLocationResult(LocationResult locationResult) {
        // do something with the locationResult
    }

    // CHECK PERMISSIONS PART

    private boolean checkPermission() {
        return isGranted(ActivityCompat.checkSelfPermission(this, ACCESS_FINE_LOCATION)) &&
                isGranted(ActivityCompat.checkSelfPermission(this, ACCESS_COARSE_LOCATION));
    }

    @TargetApi(Build.VERSION_CODES.M)
    private void getLocationPermissions() {
        requestPermissions(new String[] {Manifest.permission.ACCESS_FINE_LOCATION},
                PERMISSION_REQUEST_FINE_LOCATION);
    }

    @Override
    public void onRequestPermissionsResult(int code, @Nullable String permissions[], @Nullable int[] results) {
        switch (code) {
            case PERMISSION_REQUEST_FINE_LOCATION:
                if (isPermissionGranted(results)) {
                    getLocationRequest();
                }
        }
    }

    private boolean isPermissionGranted(int[] results) {
        return results != null && results.length > 0 && isGranted(results[0]);
    }

    private boolean isGranted(int permission) {
        return permission == PackageManager.PERMISSION_GRANTED;
    }
}
从你的
活动中调用这个

YourActivity.java

public class GpsManager extends LocationCallback {

    private FusedLocationProviderClient client;
    private Callback callback;

    public interface Callback {
        void onLocationResult(LocationResult locationResult);
    }

    public boolean start(Context context, Callback callback) {
        this.callback = callback;
        client = LocationServices.getFusedLocationProviderClient(context);
        if (!checkLocationPermission(context)) return false;
        client.requestLocationUpdates(getLocationRequest(), this, null);
        return true;
    }

    public void stop() {
        client.removeLocationUpdates(this);
    }

    @Override
    public void onLocationResult(LocationResult locationResult) {
        callback.onLocationResult(locationResult);
    }

    private boolean checkLocationPermission(Context context) {
        int permissionCheck = ContextCompat.checkSelfPermission(
                context, android.Manifest.permission.ACCESS_FINE_LOCATION);
        return permissionCheck == PackageManager.PERMISSION_GRANTED;
    }

    private LocationRequest getLocationRequest() {
        return LocationRequest.create()
                .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
                .setInterval(30_000L)
                .setFastestInterval(20_000L);
    }
}
public class MapsActivity extends AppCompatActivity implements GpsManager.Callback  {

    private static final int PERMISSION_REQUEST_FINE_LOCATION = 1;
    private GpsManager mGpsManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...
        mGpsManager = new GpsManager(getApplicationContext(), this);

        // check if user gave permissions, otherwise ask via dialog
        if (!checkPermission()) {
            getLocationPermissions();
            return;
        }

        mGpsManager.start();
        ...
    }

    @Override
    protected void onStop() {
        super.onStop();
        mGpsManager.stop();
    }

    @Override
    public void onLocationResult(LocationResult locationResult) {
        // do something with the locationResult
    }

    // CHECK PERMISSIONS PART

    private boolean checkPermission() {
        return isGranted(ActivityCompat.checkSelfPermission(this, ACCESS_FINE_LOCATION)) &&
                isGranted(ActivityCompat.checkSelfPermission(this, ACCESS_COARSE_LOCATION));
    }

    @TargetApi(Build.VERSION_CODES.M)
    private void getLocationPermissions() {
        requestPermissions(new String[] {Manifest.permission.ACCESS_FINE_LOCATION},
                PERMISSION_REQUEST_FINE_LOCATION);
    }

    @Override
    public void onRequestPermissionsResult(int code, @Nullable String permissions[], @Nullable int[] results) {
        switch (code) {
            case PERMISSION_REQUEST_FINE_LOCATION:
                if (isPermissionGranted(results)) {
                    getLocationRequest();
                }
        }
    }

    private boolean isPermissionGranted(int[] results) {
        return results != null && results.length > 0 && isGranted(results[0]);
    }

    private boolean isGranted(int permission) {
        return permission == PackageManager.PERMISSION_GRANTED;
    }
}

这只是一个猜测,因为我没有尝试你的代码,但解决方案应该对你有所帮助。如果我错了,请纠正我;)

不,即使调用
locationProviderClient.RemovelocationUpdate(locationCallback),也没有任何区别RemovelociationUpdate继续返回失败,活动继续泄漏。请尝试在RemovelociationUpdate上实现OnCompletelistener。