当前位置: 首页 > 知识库问答 >
问题:

FusedLocationProviderClient。RemovelocationUpdate总是返回失败

秦才良
2023-03-14

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

LocationServices。getFusedLocationProviderClient侦听位置更新。

这项活动的来源在这里https://github.com/snijsure/MultiActivity/blob/master/app/src/main/java/com/example/subodhnijsure/multiactivity/LocationAwareActivity.java

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

  • removeLocationUpdate返回的任务总是返回not successful

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

此项目的完整来源可在此处访问-https://github.com/snijsure/MultiActivity


共有3个答案

闻人哲茂
2023-03-14
匿名用户

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

1)您正在使用两个不同的LocationCallback。一个在开始,一个在停止方法中,但是您实际上应该使用相同的方法。所以一次实例化它就足够了,并且在删除LocationCallback时可能也会导致您的任务的成功结果。

2)由于您使用匿名类实例化了LocationCallback两次,因此即使您完成了包含类,您也保留了内部类的非静态引用,这会导致您的Memory Leak。您可以在这里阅读更多信息。

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

这是我的。。。

GPS管理员。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);
    }
}

从你的活动这样调用这个

你的活动。JAVA

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

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

梁丘招
2023-03-14

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

我认为这是一项艰巨的任务。isSuccessful()当你把这个监听器放在那个时候,这个方法就不起作用了,它工作得很好,我还看到它在内存中释放了所有的内存,当它进入前一个活动时。

当您重定向到任何活动时,请将一次调用的停止位置更新()转移到onPance()中,并从其他方法中删除,如onDevroy(),onStation(),因为它停止一次,所以为什么我们要调用多次时间。

希望这对你有帮助。

鲁涵意
2023-03-14

在RemovelocationUpdate中,您应该传递locationCallback,因为当前的实现是错误的。

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

public void stopLocationUpdates() {
        if (locationProviderClient != null) {
            try {
                final Task<Void> voidTask = locationProviderClient.removeLocationUpdates(locationCallback);
                if (voidTask.isSuccessful()) {
                    Log.d(TAG,"StopLocation updates successful! ");
                } else {
                    Log.d(TAG,"StopLocation updates unsuccessful! " + voidTask.toString());
                }
            }
            catch (SecurityException exp) {
                Log.d(TAG, " Security exception while removeLocationUpdates");
            }
        }
    }
 类似资料:
  • 问题内容: 我遵循此处给出的建议,以便使用elasticsearch查找部分单词: ElasticSearchn-gram令牌过滤器未找到部分单词 我创建了一个简单的bash脚本,尝试运行该脚本的一个版本: 运行此脚本后,前两个命令(倾销产品,然后设置索引)似乎可以正常工作: 然后它在映射调用之后给我以下错误: 有人可以看到我在做什么吗?搜索谷歌开始自动完成“映射未找到elasticsearch”

  • 问题内容: 结果始终为1: 我在phpMyAdmin中运行了$ sql查询,它返回3,所以查询不是问题。$ vote_total全局初始化为0,因此1来自某个地方。我还需要提供什么其他信息来帮助我? 谢谢,瑞安 问题答案: 返回选定的行数,而不是特定行的字段。使用来获取您与您的查询选择的行: 您还可以用来获取一行并获取特定字段: 这将获取第一行(从零开始)并返回第一字段(从零开始)。

  • 问题内容: 我已经写了这段简单的代码: 在我的情况当属。谁能建议/建议出什么问题了? 问题答案: 错误检查和处理是程序员的朋友。检查初始化和执行cURL函数的返回值。并在失败的情况下包含更多信息: *在 手动状态: 成功返回cURL句柄,错误返回 FALSE 。 我观察到该函数在您使用其参数且无法解析域时会返回。如果未使用该参数,则该函数 可能 永远不会返回。但是,请务必始终进行检查,因为该手册并

  • 我使用Ehcache 2.6.8作为Spring Boot应用程序的一部分,作为Hibernate 4.3.11的二级缓存。我有一个JMX MBean,它允许我检查缓存的内容(如果您感兴趣,可以在这里查看)。 首先,我使用CacheManager名称来获取缓存列表。这很好。我可以用返回缓存。然后我调用。这很好,cacheName是“com.myapp.DomainObjectName”,键被列为“

  • 我试图打开一个文件进行解析(一个二进制文件),但是无论什么fopen()总是返回NULL。 我已经排除了几乎所有的东西,我有一个简单的测试脚本: trigger_error(var_export())的输出;是: 无论我为第二个fopen()选项指定什么标志,我都会得到相同的结果。 现在,明显的问题是该文件是否存在,以及我是否拥有读取该文件的权限?这两个问题的答案都是肯定的。我使用了相对路径和绝对

  • 在fetchplaces方法中,新的window.google.maps.places.PlacesService(map)总是返回null,并且Service.NearbySearch不会引发函数错误。 请帮忙。