これは、位置情報の更新を受信するためにアプリを登録する方法です:
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
をPRIORITY_HIGH_ACCURACY
に変更しました(24時間)。すべての間隔は同じままでした(更新間隔は10分)。ネットワーク/ SIMカードのない携帯電話でも正確な位置情報が得られますが、バッテリーはすぐに消耗します!バッテリーの履歴を見ると、GPSラジオが常にフルトランスミッションモードになっている!!!!に驚いた。 10分ごとに位置情報をリクエストしたこと(GPSを開いて位置情報を受信する他のインストール済みアプリはありません。
いくつかのデバイス(Moto X 2013、HTC One X、Nexus 5など)で、すべて最新のGoogle Play Services(バージョン6.1.11)およびAndroid KitKat 4.4.4
私のアプリケーションはユーザーの現在の場所に大きく依存しており、ユーザーがログインしている限り、指定された間隔で定期的に場所の更新を受信するため、バッテリーの消耗を防ぐためにPRIORITY_HIGH_ACCURACY
モードを使用しません。
私の質問:
フュージョンロケーションプロバイダーは、PRIORITY_BALANCED_POWER_ACCURACY
で更新を受信するように設定され、WI-FIまたはセルタワー情報がない場合、GPSを使用することを想定していますか?
もしそうなら、私は何を間違っていますか?
なぜこの間違った場所の更新が正しくないのですか? (「さらに大きな問題」セクションで説明したように..
PRIORITY_HIGH_ACCURACY
パラメータを使用したときに10分間隔で開いたのではなく、常にGPS無線が開いているのはなぜですか? (ロケーションの更新をより速くトリガーする他のアプリをインストールしていません。)
指定された質問については、
1.は、_PRIORITY_BALANCED_POWER_ACCURACY
_で更新を受信するように設定されていて、WIがない場合、GPSを使用すると想定される融合ロケーションプロバイダーです。 -FIまたはセルタワー情報? &
2.もしそうなら、何が間違っているのでしょうか?
明らかに、ドキュメント内のどこにも明示的に一意のソースが指定されていないようです。いずれかのPRIORITY
オプションを使用すると、コードを介しても、取得したlocation
の「ソース」は「融合」されます。
[location.getProvider()
戻り値: "fused"]
LocationRequest にPRIORITY_HIGH_ACCURACYがある場合にのみGPSが使用されているのを見ました。そのため、他の条件下ではGPSを使用しません。
4. PRIORITY_HIGH_ACCURACYパラメーターを使用したときにGPS無線が10分間隔で開かれるのではなく、常に開かれるのはなぜですか? (ロケーションの更新をより速くトリガーする他のアプリをインストールしていません。)
最速の間隔は1分間に設定されています。私が理解したことから、最速の間隔の値がsetIntervalの値よりも持続時間が短い場合、- setFastestInterval が setInterval よりも優先されます。
あなたの場合、10分に対して1分。
場所の更新をトリガーする他のインストール済みアプリがないことについては、例として挙げただけで、その場合のみを明示的に指定していません。
これは、アプリケーションが位置の更新を受信する最速の速度を制御します。状況によっては(たとえば、他のアプリケーションが位置の更新をトリガーしている場合)setInterval(long)よりも速い場合があります。
したがって、起こるのは_PRIORITY_HIGH_ACCURACY
_であり、GPS(排他的に)を使用して、最速の間隔セット(1分)でlocation
を要求します。
3.なぜこの間違った場所の更新が正しくないのですか? (「さらに大きな問題」セクションで説明したように..
pendingIntent
メカニズムのコードも確認する必要があります。注意すべきことがいくつかありますが:location.getTime()
を追加して、取得した場所の時刻を確認および検証できます。範囲内にWi-Fiセルタワーがなく、_PRIORITY_BALANCED_POWER_ACCURACY
_が使用されている場合、更新されていない可能性が高いです。
「lastKnown」が呼び出されたときに使用されている、最初の場所のブロックレベルの正確さは役に立ちません。
バッテリー消費は、GPSと1分の更新の組み合わせによるものでした。実装に適している場合は、最速の間隔を5分または10分に設定してみてください。ただし、絶対に正確な場所が必要な場合は_PRIORITY_BALANCED_POWER
_が役に立たない場合があります。通常、onLocationChanged
で取得した場所のチェックを追加し、それに応じてLocationRequestで優先度を切り替えます。 GPSの見通し線がなく、Wi-Fiネットワークがオフになっている建物内にいる場合を除き、一般に場所を取得するのに役立ちます。
AlarmManager
とFusedLocationProvider
を一緒に使用して、位置の更新を開始するビューでAlarmManager
が10分ごとにアラームを発動することをお勧めします。
更新された場所を取得したら、場所クライアントを切断します。 LocationRequest
でインターバル時間を設定することにより、常に実行し続ける必要はありません。代わりに、AlarmManager
を使用して、各時間間隔でプロセスを呼び出すことができます。
この種のメカニズムでは、問題を解決する次の利点があります。
役立つことを願っています。
セルタワーは数マイルのエリアをカバーしているため、場所を取得するには最適ではありません。ロケーションを使用している場合は、ロケーションの精度を確認してください。
@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;
}
}
ネットワークステータスにブロードキャストレシーバーを置くことができ、接続がない場合は、priority_high_accuracyでロケーションプロバイダーを再起動できます。これは、ユーザーがGPSを有効にしている場合にのみGPSを使用します。
<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;
}
GPS座標の更新には、GPSおよびWI-FIプロバイダーも使用できます。位置の更新には、最小距離パラメータも使用します。小さなGPSサービスの例を提供します。
回答:
1)PRIORITY_BALANCED_POWER_ACCURACY do not 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;
}
}