Android中的位置侦听器的后台服务

我正在创build一个将在其自己的进程中运行的后台服务。 它应该允许我听,如果设备的位置已经改变。 我应该可以在通知UI之前更改移动距离等标准。

我怎么能这样做? 我对服务和LocationListener实现有一点了解。 任何围绕networking的教程将不胜感激。

我从堆栈溢出中得到一个反向链接 ,但是我不太了解它。

首先你需要创build一个Service 。 在该Service ,创build一个扩展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(); locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 4000, 0, 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); } } 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(); } public void onStatusChanged(String provider, int status, Bundle extras) { } } } 

添加此项Service在您的项目中的任何地方,你想要的方式! 🙂

我知道我发布这个答案有点晚,但我觉得这是值得使用谷歌的保险丝位置提供商服务来获取当前的位置。

这个API的主要特点是:

1.简单的API:让您select您的准确性水平以及功耗。

2.立即可用:让您的应用程序立即访问最佳,最近的位置。

3.功率效率:select最有效的方式获得功耗更低的位置

4.灵活性:满足从需要高度准确定位的前台使用到需要周期性定位更新且功率影响可忽略的背景使用的广泛需求。

在位置更新时也是灵活的。 如果您只希望当前位置在您的应用程序启动时,您可以使用getLastLocation(GoogleApiClient)方法。

如果你想不断更新你的位置,那么你可以使用requestLocationUpdates(GoogleApiClient,LocationRequest, LocationListener)

你可以在这里find一个关于保险丝位置的非常好的博客,还可以在这里find保险丝位置的Google文档。

更新

根据从Android O开始的开发人员文档,他们添加了对后台位置的新限制。

如果您的应用程序正在后台运行,则位置系统服务每小时只能为您的应用计算一次新的位置。 甚至当您的应用程序请求更频繁的位置更新时也是如此。 但是,如果您的应用在前台运行,与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> 

很容易不需要创build类扩展LocationListener 1-variables

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