26

私は、ユーザーの現在の場所を必要とし(lastknownlocationはあまり役に立ちません)、データベースから取得したユーザーに最も近いすべての「アイテム」のリストを表示するアプリを作成しています。

最も近いアイテムの検索はうまく機能していますが、当面はハードコードされた緯度と経度の場所のみを使用しますが、実際の場所の検索を実装するときが来ました。

誰かがアプリにバックグラウンドで現在の細かい場所を見つけてアプリを待たせる方法の例を提供できますか?人が移動しても場所が更新されない場合は、場所が1回だけ必要です。私はロケーションリスナーを実装しましたが、GPS修正の取得が遅くなる可能性があることを理解しています。最後の既知の場所を使用したり、実行と更新を継続する場所リスナーを実装したりする他の例を見てきましたが、アクティビティがアプリのクラッシュを表示する前に場所の座標が必要なためです。検索中に進行状況ダイアログを表示する必要があります。

locationlistenerをバックグラウンドで1回実行し、場所が見つかったら場所の更新を削除するにはどうすればよいですか。アプリケーションの残りの部分は、GPSの位置がわかるまで待つか、たとえば20〜30秒後にタイムアウトする必要があります。ProgressDialogを上げて、ユーザーが何かが起こっていることを認識できるようにしたいのですが、それはパーセンテージなどではなく、回転する読み込みアニメーションである必要があります。可能であれば、ユーザーが待つことにうんざりしている場合はダイアログをキャンセルできるようにしたいと思います。その場合は、代わりにsuburbなどと入力して検索できます。

私はスレッドでそれをやろうとしていましたが、それは私が思っているよりもずっと複雑になっていて、それでもとにかく機能していません。iPhoneではこれははるかに簡単ですか?

誰かがこれを行うための良い方法を提供できますか?私はこれで1週間髪を引き裂いていて、アプリの残りの完了日のスケジュールを本当に遅らせています。

要約すると、次のことを行います。
*現在の座標を検索する
*位置情報の取得中に進行状況ダイアログを表示する
*アプリは、位置情報が成功するのを待つか、一定時間後にあきらめることができますか?
*成功した場合:[進行状況]ダイアログを閉じ、座標を使用して、近くのアイテムを見つけるための他のメソッドを実行します。
*場所の取得に失敗した場合:進行状況ダイアログを閉じてエラーメッセージを表示し、メニューを使用して検索アクティビティに移動するようにユーザーに促します。
*ユーザーがメニューからマップビューを選択した場合は、これらの座標を使用して、データベースからの座標を使用して、マップ上の現在の場所と、近くのすべてのアイテムにドロップされたピンを表示します。

みんなありがとう、私は私が自分自身を十分に説明したことを望みます。ご不明な点がございましたら、この部分を完成させたいと思っているので、定期的に確認します。乾杯


要求に応じてコードを編集

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

これは、現在の場所を一度取得するだけの大きな努力のように思えますか?更新などは必要ありませんか?アプリケーションに結果を待たせる簡単な方法はありませんか?私はこれに長い間立ち往生しています。

4

3 に答える 3

16

AsyncTask を使用し、network_providerとgps_provider の両方を使用します。これは 2 つのリスナーを意味します。GPSは修正に時間がかかり、場合によっては1分ほどかかり、屋外でしか機能しませんが、ネットワークは非常に高速に場所を取得します.

良いコード例は次のとおりです: Android でユーザーの現在の場所を取得する最も簡単で最も堅牢な方法は何ですか?

AsyncTask については、http://developer.android.com/reference/android/os/AsyncTask.html を参照してください

SO には多くのコード例もあります。たとえば、次のとおりです。 Android スレッドが完了するまでダイアログを表示し、プログラムを続行します

編集: コードの概念:

クラス変数を追加

boolean hasLocation = false;

onCreate で呼び出します (AsyncTask ではありません):

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

次に、locationListener.onLocationChanged で、場所が見つかったら値を変更します。

boolean hasLocation = false;

AsyncTask: そのままにしておくが、呼び出さない

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

そこで、代わりに

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

おそらくその間に遅延があれば十分でしょう。

于 2010-08-15T04:53:02.157 に答える
12

私はまだこれがどのように機能するかがまったく好きではなく、本来よりもはるかに複雑に見えますが、誰かがより良い方法を提供するまで、私は今のところそれを機能させています...

誰かがこれに出くわし、ユーザーの現在の位置座標を一度だけ取得するためのはるかにクリーンな結果を提案した場合は、見るのをやめてください。

private LocationControl locationControlTask;
private boolean hasLocation = false;
LocationHelper locHelper;

onCreate()から呼び出します

locHelper = new LocationHelper();
locHelper.getLocation(context, locationResult);
locationControlTask = new LocationControl();
locationControlTask.execute(this);

次に、プライベートクラスLocationControlがあります

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

        protected void onPreExecute()
        {
            this.dialog.setMessage("Searching");
            this.dialog.show();
        }

        protected Void doInBackground(Context... params)
        {
            //Wait 10 seconds to see if we can get a location from either network or GPS, otherwise stop
            Long t = Calendar.getInstance().getTimeInMillis();
            while (!hasLocation && Calendar.getInstance().getTimeInMillis() - t < 15000) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            };
            return null;
        }

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

            if (currentLocation != null)
            {
                useLocation();
            }
            else
            {
                //Couldn't find location, do something like show an alert dialog
            }
        }
    }

次に、locationResult。。

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

また、私が長年行っていたように髪の毛を抜くのを避けるために、誰かがアクティビティを早く離れた場合は位置制御タスクを停止し、ユーザーが離れたときにGPSの実行を停止するために位置の更新を停止することを忘れないでください。onStop()で、次のようにします。

locHelper.stopLocationUpdates();
locationControlTask.cancel(true);

また、Location HelperクラスのstopLocationUpdatesは、次のことを行います。

public void stopLocationUpdates()
{
locationManager.removeUpdates(locationListenerGps);
locationManager.removeUpdates(locationListenerNetwork);
}

それで頑張ってください、私はそれが必要でした...

于 2010-11-03T05:01:31.263 に答える
0

AsyncTask を作成する代わりに、ProgressDialog ボックスを作成してそれを閉じなかったのはなぜpublic void gotLocation(final Location location){}ですか? また、ProgressDialog ボックスに onCancelListener を追加して、現在の場所のリクエストをキャンセルすることもできます。

于 2011-04-05T14:46:27.327 に答える