独自のプロセスで実行されるバックグラウンドサービスを作成しています。デバイスの場所が変更された場合にリッスンできるようにする必要があります。 UIに通知する前に、移動距離などの基準を変更できるはずです。
どうすれば同じことができますか?私はサービスとLocationListener
実装について少し知識があります。ネットに関するあらゆるチュートリアルを歓迎します。
スタックオーバーフローから back-link を受け取りましたが、あまり理解していませんでした。
まず、Service
を作成する必要があります。そのService
で、LocationListener
を拡張するクラスを作成します。これには、Service
の次のコードスニペットを使用します。
public class LocationService extends Service {
public static final String BROADCAST_ACTION = "Hello World";
private static final int TWO_MINUTES = 1000 * 60 * 2;
public LocationManager locationManager;
public MyLocationListener listener;
public Location previousBestLocation = null;
Intent intent;
int counter = 0;
@Override
public void onCreate() {
super.onCreate();
intent = new Intent(BROADCAST_ACTION);
}
@Override
public void onStart(Intent intent, int startId) {
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
listener = new MyLocationListener();
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 4000, 0, (LocationListener) listener);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 4000, 0, listener);
}
@Override
public IBinder onBind(Intent intent)
{
return null;
}
protected boolean isBetterLocation(Location location, Location currentBestLocation) {
if (currentBestLocation == null) {
// A new location is always better than no location
return true;
}
// Check whether the new location fix is newer or older
long timeDelta = location.getTime() - currentBestLocation.getTime();
boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
boolean isNewer = timeDelta > 0;
// If it's been more than two minutes since the current location, use the new location
// because the user has likely moved
if (isSignificantlyNewer) {
return true;
// If the new location is more than two minutes older, it must be worse
} else if (isSignificantlyOlder) {
return false;
}
// Check whether the new location fix is more or less accurate
int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
boolean isLessAccurate = accuracyDelta > 0;
boolean isMoreAccurate = accuracyDelta < 0;
boolean isSignificantlyLessAccurate = accuracyDelta > 200;
// Check if the old and new location are from the same provider
boolean isFromSameProvider = isSameProvider(location.getProvider(),
currentBestLocation.getProvider());
// Determine location quality using a combination of timeliness and accuracy
if (isMoreAccurate) {
return true;
} else if (isNewer && !isLessAccurate) {
return true;
} else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
return true;
}
return false;
}
/** Checks whether two providers are the same */
private boolean isSameProvider(String provider1, String provider2) {
if (provider1 == null) {
return provider2 == null;
}
return provider1.equals(provider2);
}
@Override
public void onDestroy() {
// handler.removeCallbacks(sendUpdatesToUI);
super.onDestroy();
Log.v("STOP_SERVICE", "DONE");
locationManager.removeUpdates(listener);
}
public static Thread performOnBackgroundThread(final Runnable runnable) {
final Thread t = new Thread() {
@Override
public void run() {
try {
runnable.run();
} finally {
}
}
};
t.start();
return t;
}
public class MyLocationListener implements LocationListener
{
public void onLocationChanged(final Location loc)
{
Log.i("*****", "Location changed");
if(isBetterLocation(loc, previousBestLocation)) {
loc.getLatitude();
loc.getLongitude();
intent.putExtra("Latitude", loc.getLatitude());
intent.putExtra("Longitude", loc.getLongitude());
intent.putExtra("Provider", loc.getProvider());
sendBroadcast(intent);
}
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
public void onProviderDisabled(String provider)
{
Toast.makeText( getApplicationContext(), "Gps Disabled", Toast.LENGTH_SHORT ).show();
}
public void onProviderEnabled(String provider)
{
Toast.makeText( getApplicationContext(), "Gps Enabled", Toast.LENGTH_SHORT).show();
}
}
このService
をプロジェクトのどこにでも好きなように追加してください! :)
少し遅れてこの回答を投稿していることは知っていますが、GoogleのFuseロケーションプロバイダーサービスを使用して現在の位置を取得する価値があると感じました。
このAPIの主な機能は次のとおりです。
1.Simple APIs:消費電力と同様に精度レベルを選択できます。
2。即時利用可能:アプリに、最適な最新の場所にすぐにアクセスできるようにします。
.Power-efficiency:より少ない電力消費で位置を取得する最も効率的な方法を選択します
4.Versatility:非常に正確な位置を必要とするフォアグラウンドの使用から、電力への影響が無視できる定期的な位置の更新を必要とするバックグラウンドの使用まで、幅広いニーズに対応します。
ロケーションの更新も柔軟に行えます。アプリの起動時にのみ現在の場所が必要な場合は、getLastLocation(GoogleApiClient)
メソッドを使用できます。
現在地を継続的に更新する場合は、requestLocationUpdates(GoogleApiClient,LocationRequest, LocationListener)
を使用できます
Fuseの場所に関する非常に素晴らしいブログを見つけることができます here とFuseの場所に関するgoogle docも見つけることができます here 。
更新
Android O以降の開発者ドキュメントによると、彼らはバックグラウンドの場所に新しい制限を追加しました。
アプリがバックグラウンドで実行されている場合、ロケーションシステムサービスはアプリの新しい場所を1時間に数回しか計算しません。これは、アプリがより頻繁に位置情報の更新を要求している場合でも同様です。ただし、アプリがフォアグラウンドで実行されている場合、Android 7.1.1(APIレベル25)と比較してロケーションサンプリングレートに変更はありません。
バックグラウンドロケーションサービス。アプリを終了した後でも再起動されます。
MainActivity.Java
public class MainActivity extends AppCompatActivity {
AlarmManager alarmManager;
Button stop;
PendingIntent pendingIntent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (alarmManager == null) {
alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, AlarmReceive.class);
pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 30000,
pendingIntent);
}
}
}
BookingTrackingService.Java
public class BookingTrackingService extends Service implements LocationListener {
private static final String TAG = "BookingTrackingService";
private Context context;
boolean isGPSEnable = false;
boolean isNetworkEnable = false;
double latitude, longitude;
LocationManager locationManager;
Location location;
private Handler mHandler = new Handler();
private Timer mTimer = null;
long notify_interval = 30000;
public double track_lat = 0.0;
public double track_lng = 0.0;
public static String str_receiver = "servicetutorial.service.receiver";
Intent intent;
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
mTimer = new Timer();
mTimer.schedule(new TimerTaskToGetLocation(), 5, notify_interval);
intent = new Intent(str_receiver);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
this.context = this;
return START_NOT_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
Log.e(TAG, "onDestroy <<");
if (mTimer != null) {
mTimer.cancel();
}
}
private void trackLocation() {
Log.e(TAG, "trackLocation");
String TAG_TRACK_LOCATION = "trackLocation";
Map<String, String> params = new HashMap<>();
params.put("latitude", "" + track_lat);
params.put("longitude", "" + track_lng);
Log.e(TAG, "param_track_location >> " + params.toString());
stopSelf();
mTimer.cancel();
}
@Override
public void onLocationChanged(Location location) {
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onProviderDisabled(String provider) {
}
/******************************/
private void fn_getlocation() {
locationManager = (LocationManager) getApplicationContext().getSystemService(LOCATION_SERVICE);
isGPSEnable = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
isNetworkEnable = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (!isGPSEnable && !isNetworkEnable) {
Log.e(TAG, "CAN'T GET LOCATION");
stopSelf();
} else {
if (isNetworkEnable) {
location = null;
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000, 0, this);
if (locationManager != null) {
location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (location != null) {
Log.e(TAG, "isNetworkEnable latitude" + location.getLatitude() + "\nlongitude" + location.getLongitude() + "");
latitude = location.getLatitude();
longitude = location.getLongitude();
track_lat = latitude;
track_lng = longitude;
// fn_update(location);
}
}
}
if (isGPSEnable) {
location = null;
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, this);
if (locationManager != null) {
location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (location != null) {
Log.e(TAG, "isGPSEnable latitude" + location.getLatitude() + "\nlongitude" + location.getLongitude() + "");
latitude = location.getLatitude();
longitude = location.getLongitude();
track_lat = latitude;
track_lng = longitude;
// fn_update(location);
}
}
}
Log.e(TAG, "START SERVICE");
trackLocation();
}
}
private class TimerTaskToGetLocation extends TimerTask {
@Override
public void run() {
mHandler.post(new Runnable() {
@Override
public void run() {
fn_getlocation();
}
});
}
}
// private void fn_update(Location location) {
//
// intent.putExtra("latutide", location.getLatitude() + "");
// intent.putExtra("longitude", location.getLongitude() + "");
// sendBroadcast(intent);
// }
}
AlarmReceive.Java(BroadcastReceiver)
public class AlarmReceive extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.e("Service_call_" , "You are in AlarmReceive class.");
Intent background = new Intent(context, BookingTrackingService.class);
// Intent background = new Intent(context, GoogleService.class);
Log.e("AlarmReceive ","testing called broadcast called");
context.startService(background);
}
}
AndroidManifest.xml
<uses-permission Android:name="Android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission Android:name="Android.permission.ACCESS_FINE_LOCATION" />
<service
Android:name=".ServiceAndBroadcast.BookingTrackingService"
Android:enabled="true" />
<receiver
Android:name=".ServiceAndBroadcast.AlarmReceive"
Android:exported="false">
<intent-filter>
<action Android:name="Android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
非常に簡単にクラスを作成する必要はありませんLocationListener 1-変数を拡張します
private LocationManager mLocationManager;
private LocationListener mLocationListener;
private static double currentLat =0;
private static double currentLon =0;
2- onStartService()
@Override public void onStartService() {
addListenerLocation();
}
3-メソッドaddListenerLocation()
private void addListenerLocation() {
mLocationManager = (LocationManager)
getSystemService(Context.LOCATION_SERVICE);
mLocationListener = new LocationListener() {
@Override
public void onLocationChanged(Location location) {
currentLat = location.getLatitude();
currentLon = location.getLongitude();
Toast.makeText(getBaseContext(),currentLat+"-"+currentLon, Toast.LENGTH_SHORT).show();
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
Location lastKnownLocation = mLocationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if(lastKnownLocation!=null){
currentLat = lastKnownLocation.getLatitude();
currentLon = lastKnownLocation.getLongitude();
}
}
@Override
public void onProviderDisabled(String provider) {
}
};
mLocationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER, 500, 10, mLocationListener);
}
4- onDestroy()
@Override
public void onDestroy() {
super.onDestroy();
mLocationManager.removeUpdates(mLocationListener);
}