如何在超时情况下从 LocationManager 获取单个位置修复?

发布于 2024-12-22 19:05:05 字数 980 浏览 1 评论 0原文

我正在使用 LocationManager 来获取单个位置修复:

public class MyActivity extends Activity {
    private LocationManager lm;
    private ProgressDialog myDialog;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        LocationListener ll = new MyLocationListener();
        lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1, 1, ll);
        myDialog = ProgressDialog.show(this, null , "Determining Your Location", true);
    }

    class MyLocationListener implements LocationListener {
        public void onLocationChanged(Location location) {
            if (location != null) {
                ...

                lm.removeUpdates(this);
                myDialog.dismiss();
            }
        }
    }
}

如果找不到位置修复,则监听位置可能会永远持续下去。我想通过在 60 秒后停止侦听位置并向用户显示错误来说明无法确定其位置来为我的代码添加一些稳健性。

我该怎么做?

I am using LocationManager to get a single location fix:

public class MyActivity extends Activity {
    private LocationManager lm;
    private ProgressDialog myDialog;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        LocationListener ll = new MyLocationListener();
        lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1, 1, ll);
        myDialog = ProgressDialog.show(this, null , "Determining Your Location", true);
    }

    class MyLocationListener implements LocationListener {
        public void onLocationChanged(Location location) {
            if (location != null) {
                ...

                lm.removeUpdates(this);
                myDialog.dismiss();
            }
        }
    }
}

As this stands listening for a location could potentially go on forever if a location fix cannot be found. I want to add some robustness to my code by ceasing to listening for a location after 60 seconds, and displaying an error to the user to saying that their location could not be determined.

How can I do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

拥抱没勇气 2024-12-29 19:05:05

您可以使用 Handler计时器AlarmManager 通过调用LocationManager.removeUpdates停止监听来实现超时。

Timer 创建一个新线程,这可能有点过头了。 AlarmManager 的文档表明“或者正常的计时操作(滴答声、超时等),使用 Handler 更容易、更高效”。 Handler 的文档描述了 Handler 的主要用途之一是“安排消息和可运行对象在未来某个时刻执行(原文如此)”。

所有迹象都表明 Handler 是实现超时的最合适方法。

public class MyActivity extends Activity implements LocationListener {
    private final int TIMEOUT = 60000;

    private LocationManager myLocationManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        myLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        myLocationManager.requestSingleUpdate(LocationManager.NETWORK_PROVIDER,
            this, null);

        Runnable myRunnable = new Runnable() {
            public void run() {
                myLocationManager.removeUpdates(QualityCheckActivity.this);
                // other timeout error code
            }
        };

        Handler myHandler = new Handler();
        myHandler.postDelayed(myRunnable, TIMEOUT);
    }

    @Override
    public void onLocationChanged(Location location) {
        // location fixed code 
    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) { }

    @Override
    public void onProviderEnabled(String provider) { }

    @Override
    public void onProviderDisabled(String provider) { }
}

注意:

TIMEOUT 当然是超时长度(以毫秒为单位)。在本例中为 60,000 毫秒,即 60 秒。

我选择在 MyActivity 本身上实现 LocationListener 接口,以便在 Runnable 中更容易访问 LocationListener

而不是调用 LocationManager.requestLocationUpdates:我正在使用 LocationManager.requestSingleUpdate 它将仅提供一个位置修复。

我故意没有实现 Activity.onPauseActivity.onResume。如果活动暂停,位置侦听和超时都将继续。

You could either user a Handler, Timer or AlarmManager to implement the timeout by calling LocationManager.removeUpdates to stop listening.

A Timer creates an new thread, which may be overkill. The documentation for AlarmManager suggests that "(f)or normal timing operations (ticks, timeouts, etc) it is easier and much more efficient to use Handler". The documentation for Handler describes one of the main uses for a Handler is "to schedule messages and runnables to be executed as (sic) some point in the future."

All signs point to Handler as being the most appropriate method of implementing the timeout.

public class MyActivity extends Activity implements LocationListener {
    private final int TIMEOUT = 60000;

    private LocationManager myLocationManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        myLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        myLocationManager.requestSingleUpdate(LocationManager.NETWORK_PROVIDER,
            this, null);

        Runnable myRunnable = new Runnable() {
            public void run() {
                myLocationManager.removeUpdates(QualityCheckActivity.this);
                // other timeout error code
            }
        };

        Handler myHandler = new Handler();
        myHandler.postDelayed(myRunnable, TIMEOUT);
    }

    @Override
    public void onLocationChanged(Location location) {
        // location fixed code 
    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) { }

    @Override
    public void onProviderEnabled(String provider) { }

    @Override
    public void onProviderDisabled(String provider) { }
}

NOTES:

TIMEOUT is, of course, the timeout length in milliseconds. In this case 60,000 milliseconds, or 60 seconds.

I have chosen to implement the LocationListener interface on MyActivity itself so that the LocationListener is easier to access within the Runnable.

Instead of calling LocationManager.requestLocationUpdates: I'm using LocationManager.requestSingleUpdate which will supply just one location fix.

I deliberately haven't implemented Activity.onPause and Activity.onResume. Both the location listening, and timeout, will continue if the Activity is paused.

夏末的微笑 2024-12-29 19:05:05

一种方法是使用 Handler 并在 60 秒后使用 postDelayed 来停止侦听器。

处理程序 postDelayed

One way would be to use a Handler and use postDelayed after 60 sec to stop the listener.

Handler postDelayed

菊凝晚露 2024-12-29 19:05:05

您也可以使用 Timer 和 TimerTask。当您创建处理程序以利用 postDelayed 时,您应该小心内存泄漏,因为处理程序在完成后仍会引用您的 Activity 或 Service 事件。 PostDelayed 将进入主线程中的消息队列。因此,请将您的处理程序设置为静态或使用弱引用。

您需要考虑以下代码以避免内存泄漏。

public class MyService extends Service {

   private static class MyHandler extends Handler {
      WeakReference<MyService> ref;

      public MyHandler(MyService r) {
         ref = = new WeakReference<MyService>(r);
      }

      public void handleMessage(Message msg) {

         MyService service = ref.get();
         if (servic==null) {
            return;
         }

         //Do something here
     }

   }

}

You can use Timer and TimerTask as well. When you create handler to utilise postDelayed, you should be careful of memory leak because the handler still refer your Activity or Service event after they are already finished. PostDelayed will be going to the message queue in the main thread. So, make your handler as static or use weak reference.

You need to consider following code to avoid the memory leak.

public class MyService extends Service {

   private static class MyHandler extends Handler {
      WeakReference<MyService> ref;

      public MyHandler(MyService r) {
         ref = = new WeakReference<MyService>(r);
      }

      public void handleMessage(Message msg) {

         MyService service = ref.get();
         if (servic==null) {
            return;
         }

         //Do something here
     }

   }

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文