30

これは、位置情報の更新を受信するためにアプリを登録する方法です。

mLocationRequest = LocationRequest.create();
mLocationRequest.setInterval(Consts.ONE_MINUTE * 10);
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
mLocationRequest.setFastestInterval(Consts.ONE_MINUTE);

Builder builder = new GoogleApiClient.Builder(context);
builder.addApi(ActivityRecognition.API);

mGoogleApiClient = builder.addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .build();

mGoogleApiClient.connect();

....
....

@Override
public void onConnected(Bundle connectionHint) {
   LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, locationUpdatespendingInent);
}

私の保留中のインテントは、ほぼ正確に要求された間隔でバックグラウンドで呼び出されました...

ここまでは順調ですね。

問題: WIFI が無効になっている/ネットワークに接続されていない場合、または 3G/4G ネットワーク データが有効になっていない場合 - 融合された位置情報プロバイダーが新しい位置情報の更新を提供しない!!

位置情報アクセス設定がオンになり、GPS 衛星と WI-FI & モバイル ネットワークの位置情報がチェックされます。

さらに大きな問題:その場合、保留中のインテントを介して位置情報の更新のコールバックを受信することがありますが、それが最後に認識した位置 (1 時間前であっても、その場所から何マイルも離れていたとしても)

のドキュメントによるとPRIORITY_BALANCED_POWER_ACCURACY

「ブロック」レベルの精度を要求するために setPriority(int) とともに使用されます。ブロック レベルの精度は、約 100 メートルの精度と見なされます。このような粗い精度を使用すると、多くの場合、消費電力が少なくなります。

融合された位置プロバイダーは、他に選択の余地がない場合に GPS を開くか、少なくとも新しい位置情報の更新がない場合は提供しないことを期待しています。

別の予測不可能で気がかりな問題:

それがどのように動作するかを確認するために変更PRIORITY_BALANCED_POWER_ACCURACYしました(24時間)。PRIORITY_HIGH_ACCURACYすべての間隔は同じままでした (更新間の間隔は 10 分)。ネットワーク/SIMカードのない電話でも正確な位置情報を受信しましたが、バッテリーがすぐに消耗しました! バッテリーの履歴を見てみると、GPS電波がずっとフル送信モードになっていてビックリ!!! また、10 分ごとに位置情報を要求したにもかかわらず、1 分ごとに位置情報が受信されたこともログで確認しました (GPS を開いて位置情報を受信するアプリは他にインストールされていません..)

いくつかのデバイス (Moto X 2013、HTC One X、Nexus 5 など) でこの動作に気付きました。すべて最新の Google Play サービス (バージョン 6.1.11) と android KITKAT 4.4.4 を搭載しています。

私のアプリケーションは、ユーザーの現在の場所に大きく依存し、ユーザーがログインしている限り、指定された間隔で定期的に場所の更新を受信PRIORITY_HIGH_ACCURACYするため、バッテリーの消耗を防ぐためにモードを使用したくありません..

私の質問:

  • 更新を受信するように設定されてPRIORITY_BALANCED_POWER_ACCURACYいて、WI-FIまたはセルタワーの情報がない場合、融合されたロケーションプロバイダーはGPSを使用することを想定していますか?

  • もしそうなら、私は何が間違っていますか?

  • 正しくない、誤解を招くような現在地の更新情報が表示されるのはなぜですか? (「さらに大きな問題」セクションで説明したように..

  • PRIORITY_HIGH_ACCURACYパラメータを使用したときに、GPS ラジオが 10 分間隔で開かれるのではなく、常に開かれるのはなぜですか? (位置情報の更新をより速くトリガーするアプリを他にインストールしていません..)

4

4 に答える 4

20

指定された質問に対して、

1.PRIORITY_BALANCED_POWER_ACCURACY更新を受信するように設定されていて、WI-FI や携帯電話基地局の情報がない場合、フュージョン ロケーション プロバイダーは GPS を使用することを前提と&
2.もしそうなら、何が間違っているのですか?

ドキュメント内のどこにも明示的に一意のソースが指定されていないようです。どちらPRIORITYのオプションでも、コードを介しても、取得されたの「ソース」locationは「融合」されます。
[location.getProvider()戻り値 :"fusion"] LocationRequestが PRIORITY_HIGH_ACCURACY
の場合にのみ GPS が使用されているのを見てきました。そのため、他の条件下では GPS を使用しません。

4. PRIORITY_HIGH_ACCURACY パラメーターを使用したときに、GPS ラジオが 10 分間隔で開かれるのではなく、常に開かれるのはなぜですか? (位置情報の更新をより速くトリガーするアプリを他にインストールしていません..)

最速のインターバルは 1 分に設定されています。私が理解したことから、最速の間隔の値がsetIntervalの値よりも短い場合、 setFastestIntervalはsetIntervalよりも優先されます。
あなたの場合、10に対して1分です。
位置情報の更新をトリガーする他のアプリがインストールされていないことについては、例として与えられたものであり、その場合のみを明示的に指定していません。

これは、アプリケーションが位置情報の更新を受信する最速のレートを制御します。これは、状況によっては setInterval(long) よりも高速になる場合があります (たとえば、他のアプリケーションが位置情報の更新をトリガーしている場合)。

そのため、何が起こるかというと、 GPS (排他的) を使用して、設定された最速の間隔 (1 分) PRIORITY_HIGH_ACCURACYで要求します。location

3.正しくない、誤解を招くような現在地の更新が表示されるのはなぜですか? (「さらに大きな問題」セクションで説明したように..

pendingIntentメカニズムのコードも確認する必要があります。注意すべき点がいくつかあります
が、 を追加しlocation.getTime()て、取得した場所の時刻を確認および確認できます。範囲内に Wi-Fi セル タワーがなく、PRIORITY_BALANCED_POWER_ACCURACY使用されている場合は、更新されていない可能性が非常に高くなります。
そもそも、「lastKnown」が呼び出されたときに使用されるブロック レベルの位置精度は役に立ちません。

バッテリーの消費は、GPS と 1 分更新の組み合わせによるものです。実装に適している場合は、最速の間隔を 5 分または 10 分に設定してみてくださいPRIORITY_BALANCED_POWER。私は通常、取得した位置のチェックを追加し、onLocationChangedそれに応じて LocationRequest の優先度を切り替えます。確かに、GPSの見通しのない建物の中にいて、Wifiネットワークがオフになっていない限り、一般的に場所を取得するのに役立ちます.

于 2014-10-08T06:40:10.813 に答える
3

基地局は数マイルの範囲をカバーするため、場所を特定するには最適ではありません。位置を操作するときは、位置の精度を確認してください。

@Override
public void onLocationChanged(Location location) {
    //it happens
    if (location == null) {
        return;
    }
    // all locations should have an accuracy
    if (!location.hasAccuracy()) {
        return;
    }
    // if its not accurate enough don't use it
    // this value is in meters
    if (location.getAccuracy() > 200) {
        return;
    }
}

ブロードキャストレシーバーをネットワークステータスに置くことができ、接続がない場合は、ユーザーがGPSを有効にしている場合にのみGPSを使用するpriority_high_accuracyでロケーションプロバイダーを再起動できます。それ以外の場合はwifiとセルタワーにフォールバックします.

<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>

/** Checks whether the device currently has a network connection */

private boolean isDeviceOnline() {
    ConnectivityManager connMgr = (ConnectivityManager) activity
            .getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
    if (networkInfo != null && networkInfo.isConnected()) {
        return true;
    }
    return false;
}
于 2014-10-07T20:29:52.360 に答える
0

GPS 座標の更新には、GPS および WI-FI プロバイダーも使用できます。位置の更新には、最小距離パラメータも使用します。小さな GPS サービスの例を紹介します。

答え:

1) PRIORITY_BALANCED_POWER_ACCURACY はGPS を使用しません。

2) GPS と WI-FI を使用して位置を検出します。

3) PRIORITY_BALANCED_POWER_ACCURACY は、おそらくエリア内に WI-FI がないためです。

コード例:

public class GPSservice extends Service implements LocationListener {


    private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 2;

    private static final long MIN_TIME_BW_UPDATES = 1000 * 1;

    double latitude, longitude;

    boolean isGPSEnabled = false;

    boolean isNetworkEnabled = false;

    boolean canGetLocation = false;

    Location location;

    protected LocationManager locationManager;

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }


    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        getLocation();

        return super.onStartCommand(intent, flags, startId);
    }


    @Override
    public void onLocationChanged(Location location) {
        new LocationReceiver(location, getApplicationContext());
    }


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

    }

    @Override
    public void onProviderEnabled(String provider) {

    }

    @Override
    public void onProviderDisabled(String provider) {

    }

    public Location getLocation() {
        try {
            locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);

            // getting GPS status
            isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);

            isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);

            if (!isGPSEnabled && !isNetworkEnabled) {
                Log.d("Network", "NO network");
            } else {
                this.canGetLocation = true;
                if (isNetworkEnabled) {
                    locationManager.requestLocationUpdates(
                            LocationManager.NETWORK_PROVIDER,
                            MIN_TIME_BW_UPDATES,
                            MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                    Log.d("Network", "Network");
                    if (locationManager != null) {
                        location = locationManager
                                .getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
                        if (location != null) {
                            latitude = location.getLatitude();
                            longitude = location.getLongitude();
                        }
                    }
                }
                if (isGPSEnabled) {
                    if (location == null) {
                        locationManager.requestLocationUpdates(
                                LocationManager.GPS_PROVIDER,
                                MIN_TIME_BW_UPDATES,
                                MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                        Log.d("GPS Enabled", "GPS Enabled");
                        if (locationManager != null) {
                            location = locationManager
                                    .getLastKnownLocation(LocationManager.GPS_PROVIDER);
                            if (location != null) {
                                latitude = location.getLatitude();
                                longitude = location.getLongitude();
                            }
                        }
                    }
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        return location;
    }
}
于 2014-10-05T08:09:42.883 に答える