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。