Android一次找到GPS位置,显示加载对话框 [英] Android find GPS location once, show loading dialog

查看:23
本文介绍了Android一次找到GPS位置,显示加载对话框的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个应用程序,它需要用户的当前位置(lastknownlocation 不会很有帮助)并显示从数据库中获取的所有最接近他们的项目"的列表.

I am writing an app that requires the user's current location (lastknownlocation won't be very helpful) and displays a list of all the closest "items" to them taken from the database.

我发现最近的项目运行良好,但暂时只使用硬编码的纬度和经度位置,但现在是时候实施查找实际位置了.

I have got the finding of the closest items working well but only using a hardcoded latitude and longitude location for the time being but now it is time to implement finding the actual location.

谁能提供一个示例,说明如何让应用在后台找到当前的精细位置并让应用等待.我只需要位置一次,不会随着人的移动而更新.我已经实现了一个位置监听器,但是我知道获取 GPS 修复可能会很慢.我已经看到使用最后一个已知位置或实现位置侦听器的其他示例,该侦听器继续运行和更新,但是因为我的 Activity 需要位置坐标才能显示应用程序崩溃的任何内容.我需要在搜索时显示一个进度对话框.

Can anyone provide an example of how to have the app find the current fine location in the background and have the app wait. I only need the location once not updates as the person moves. I have implemented a location listener however I understand getting a GPS fix can be slow. I have seen other examples using last known location or implementing the location listener which continues to run and update however as my Activity needs the location coordinates before it can display anything the app just crashes. I need to show a Progress Dialog while its searching.

如何让 locationlistener 在后台运行一次,然后在找到位置后删除位置更新.我需要应用程序的其余部分等到它有 GPS 位置或在 20-30 秒后超时.我想要一个 ProgressDialog 以便用户知道正在发生的事情,但它必须是旋转加载动画而不是百分比或任何东西.如果可能的话,如果用户厌倦了等待,我希望用户能够取消对话框,然后他们可以通过输入郊区等来进行搜索.

How can I have the locationlistener run once in the background and then remove location updates once it finds the location. I need the rest of the application to wait until it has a GPS location or timeout after say 20-30seconds. I would like a ProgressDialog up so the user knows that something is going on, but it just has to be the spinning loading animation not a percentage or anything. If possible I would like the user to be able to cancel the dialog if they are sick of waiting which then they can search by typing suburb etc instead.

我一直在尝试用线程来做,但它变得比我认为的要复杂得多,而且仍然无法正常工作.在 iPhone 上这要简单得多?

I have been trying to do it with threads but it is getting way more complicated than I feel it should be and still not working anyway. On iPhone this is much more simple?

任何人都可以提供一个很好的方法来做到这一点,我已经为此烦恼了一个星期,这真的让我在应用程序完成日期的剩余时间里落后于计划.

Can anyone provide a nice way of doing this, I have been ripping my hair out for a week on this and it is really putting me behind schedule for the rest of the app completion date.

总之,我想:
* 查找当前坐标
* 获取位置时显示进度对话框
* 应用是否可以等待定位成功或在一定时间后放弃?
* 如果成功:关闭进度对话框并使用坐标运行我的其他方法来查找附近的项目.
* 如果获取位置失败:关闭进度对话框并显示错误消息,并鼓励用户使用菜单转到搜索活动.
* 如果用户从菜单中选择地图视图,则使用这些坐标,以显示地图上的当前位置,并使用数据库中的坐标显示所有附近项目的图钉.

In summary I want to:
* Find current coordinates
* Show Progress Dialog while getting location
* Have app be able to wait for successful location or give up after a certain time?
* If Successful: Dismiss Progress Dialog and use coordinates to run my other methods for finding items closeby.
* If Failed to get location: Dismiss Progress Dialog and show error message, and encourage user to use menu to go to Search Activity.
* Use these coordinates if the user chooses map view from the menu, to show current location on the map and pins dropped at all the nearby items by using their coordinates from the database.

谢谢大家,我希望我已经对自己进行了充分的解释.任何问题只要问,我会定期检查,因为我渴望完成这部分.干杯

Thanks guys, I hope I have explained myself well enough. Any questions just ask, I will be checking back regularly as I am keen to get this part completed. Cheers

编辑
按要求编码

locationList活动文件

protected void onStart()
{
    super.onStart();

    // ....

    new LocationControl().execute(this);
}


private class LocationControl extends AsyncTask<Context, Void, Void>
{
    private final ProgressDialog dialog = new ProgressDialog(branchAtmList.this);

    protected void onPreExecute()
    {
        this.dialog.setMessage("Determining your location...");
        this.dialog.show();
    }

    protected Void doInBackground(Context... params)
    {
        LocationHelper location = new LocationHelper();

        location.getLocation(params[0], locationResult);

        return null;
    }

    protected void onPostExecute(final Void unused)
    {
        if(this.dialog.isShowing())
        {
            this.dialog.dismiss();
        }

        useLocation(); //does the stuff that requires current location
    }

}

public LocationResult locationResult = new LocationResult()
{
    @Override
    public void gotLocation(final Location location)
    {
        currentLocation = location;
    }
};  

LocationHelper 类

    package org.xxx.xxx.utils;

import java.util.Timer;
/*
imports
*/

public class LocationHelper
{
    LocationManager locationManager;
    private LocationResult locationResult;
    boolean gpsEnabled = false;
    boolean networkEnabled = false;

    public boolean getLocation(Context context, LocationResult result)
    {       
        locationResult = result;

        if(locationManager == null)
        {
            locationManager = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
        }
            //exceptions thrown if provider not enabled
            try
            {
                gpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
            }
            catch (Exception ex) {}
            try
            {
                networkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
            }
            catch (Exception ex) {}

            //dont start listeners if no provider is enabled
            if(!gpsEnabled && !networkEnabled)
            {
                return false;
            }

            if(gpsEnabled)
            {
                locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListenerGps);
            }
            if(networkEnabled)
            {
                locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListenerNetwork);
            }


            GetLastLocation();
            return true;
    }

    LocationListener locationListenerGps = new LocationListener() {
        public void onLocationChanged(Location location)
        {
            locationResult.gotLocation(location);
            locationManager.removeUpdates(this);
            locationManager.removeUpdates(locationListenerNetwork);

        }
        public void onProviderDisabled(String provider) {}
        public void onProviderEnabled(String provider) {}
        public void onStatusChanged(String provider, int status, Bundle extra) {}
    };

    LocationListener locationListenerNetwork = new LocationListener() {
        public void onLocationChanged(Location location)
        {
            locationResult.gotLocation(location);
            locationManager.removeUpdates(this);
            locationManager.removeUpdates(locationListenerGps);

        }
        public void onProviderDisabled(String provider) {}
        public void onProviderEnabled(String provider) {}
        public void onStatusChanged(String provider, int status, Bundle extra) {}

    };

    private void GetLastLocation()
    {
            locationManager.removeUpdates(locationListenerGps);
            locationManager.removeUpdates(locationListenerNetwork);

            Location gpsLocation = null;
            Location networkLocation = null;

            if(gpsEnabled)
            {
                gpsLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
            }
            if(networkEnabled)
            {
                networkLocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
            }

            //if there are both values use the latest one
            if(gpsLocation != null && networkLocation != null)
            {
                if(gpsLocation.getTime() > networkLocation.getTime())
                {
                    locationResult.gotLocation(gpsLocation);
                }
                else
                {
                    locationResult.gotLocation(networkLocation);
                }

                return;
            }

            if(gpsLocation != null)
            {
                locationResult.gotLocation(gpsLocation);
                return;
            }

            if(networkLocation != null)
            {
                locationResult.gotLocation(networkLocation);
                return;
            }

            locationResult.gotLocation(null);
    }

    public static abstract class LocationResult
    {
        public abstract void gotLocation(Location location);
    }
}

这似乎真的只是为了获得一次当前位置而付出很大的努力吗?我不需要更新或任何东西?难道没有更简单的方法让应用程序等待结果吗?我在这个问题上卡了这么久.

This really seems like a big effort just to get the current location once? I do not require updates or anything? Is there not a simpler way of having the application wait for a result? I have been stuck on this for so long.

推荐答案

使用一个 AsyncTask 并使用 network_provider 和 gps_provider,这意味着两个监听器.gps 需要更长的时间才能得到修复,有时可能需要一分钟,而且只能在户外工作,而网络可以快速获取位置.

Use an AsyncTask and use both network_provider as well as gps_provider, which means two listeners. gps takes longer to get a fix, maybe sometimes a minute and only works outdoors, while network gets a location pretty fast.

这里有一个很好的代码示例:在 Android 上获取用户当前位置的最简单、最可靠的方法是什么?

A good code example is here: What is the simplest and most robust way to get the user's current location on Android?

对于 AsyncTask,请查看 http://developer.android.com/reference/android/os/AsyncTask.html

For AsyncTask, look http://developer.android.com/reference/android/os/AsyncTask.html

这里也有很多关于它的代码示例,例如这里:Android 显示一个对话框,直到线程完成,然后继续执行程序

There are also many code example here on SO for it, for example here: Android Show a dialog until a thread is done and then continue with the program

代码概念:

添加类变量

boolean hasLocation = false;

调用 onCreate(不在 AsyncTask 中):

call in onCreate (not in AsyncTask):

locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);

然后在 locationListener.onLocationChanged 中,一旦找到位置就更改值:

then in locationListener.onLocationChanged, change the value once a location is found:

boolean hasLocation = false;

异步任务:保持原样,但不要打电话

AsyncTask: leave as it is, but don't call

LocationHelper location = new LocationHelper();
location.getLocation(params[0], locationResult);

在那里,而不是做

Long t = Calendar.getInstance().getTimeInMillies(); 
while (!hasLocation && Calendar.getInstance().getTimeInMillies()-t<30000)) {
    Thread.Sleep(1000); 
};    

之间可能有延迟就足够了.

probably with a delay in between would be sufficient.

这篇关于Android一次找到GPS位置,显示加载对话框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆