Лучший способ получить местоположение пользователя GPS в фоновом режиме в Android
в моем приложении для android я хочу получать текущее местоположение пользователя каждые несколько минут и обновлять его на моем центральном сервере с помощью веб-службы. В настоящее время я использую Fused Location Provide для получения текущего местоположения пользователя, см. ссылке
теперь я хочу знать, каков наилучший способ часто получать местоположение пользователя и вызывать веб-службу.
ниже мой код, который дает мне текущее местоположение пользователя: -
locationrequest = LocationRequest.create();
locationrequest.setInterval(10000);
locationclient.requestLocationUpdates(locationrequest,new com.google.android.gms.location.LocationListener() {
@Override
public void onLocationChanged(Location location) {
Log.i(TAG, "Last Known Location :" + location.getLatitude() + "," + location.getLongitude());
}
});
теперь, откуда я должен это назвать код. Могу ли я использовать это в фоновом режиме или где-то еще.
пожалуйста, предоставьте свою идею.
ТИА.
13 ответов:
вы должны использовать
Service
:import android.app.Service; import android.content.Context; import android.content.Intent; import android.location.Location; import android.location.LocationManager; import android.os.Bundle; import android.os.IBinder; import android.util.Log; public class MyService extends Service { private static final String TAG = "BOOMBOOMTESTGPS"; private LocationManager mLocationManager = null; private static final int LOCATION_INTERVAL = 1000; private static final float LOCATION_DISTANCE = 10f; private class LocationListener implements android.location.LocationListener { Location mLastLocation; public LocationListener(String provider) { Log.e(TAG, "LocationListener " + provider); mLastLocation = new Location(provider); } @Override public void onLocationChanged(Location location) { Log.e(TAG, "onLocationChanged: " + location); mLastLocation.set(location); } @Override public void onProviderDisabled(String provider) { Log.e(TAG, "onProviderDisabled: " + provider); } @Override public void onProviderEnabled(String provider) { Log.e(TAG, "onProviderEnabled: " + provider); } @Override public void onStatusChanged(String provider, int status, Bundle extras) { Log.e(TAG, "onStatusChanged: " + provider); } } LocationListener[] mLocationListeners = new LocationListener[] { new LocationListener(LocationManager.GPS_PROVIDER), new LocationListener(LocationManager.NETWORK_PROVIDER) }; @Override public IBinder onBind(Intent arg0) { return null; } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.e(TAG, "onStartCommand"); super.onStartCommand(intent, flags, startId); return START_STICKY; } @Override public void onCreate() { Log.e(TAG, "onCreate"); initializeLocationManager(); try { mLocationManager.requestLocationUpdates( LocationManager.NETWORK_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE, mLocationListeners[1]); } catch (java.lang.SecurityException ex) { Log.i(TAG, "fail to request location update, ignore", ex); } catch (IllegalArgumentException ex) { Log.d(TAG, "network provider does not exist, " + ex.getMessage()); } try { mLocationManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE, mLocationListeners[0]); } catch (java.lang.SecurityException ex) { Log.i(TAG, "fail to request location update, ignore", ex); } catch (IllegalArgumentException ex) { Log.d(TAG, "gps provider does not exist " + ex.getMessage()); } } @Override public void onDestroy() { Log.e(TAG, "onDestroy"); super.onDestroy(); if (mLocationManager != null) { for (int i = 0; i < mLocationListeners.length; i++) { try { mLocationManager.removeUpdates(mLocationListeners[i]); } catch (Exception ex) { Log.i(TAG, "fail to remove location listners, ignore", ex); } } } } private void initializeLocationManager() { Log.e(TAG, "initializeLocationManager"); if (mLocationManager == null) { mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE); } } }
код
AndroidManifest.xml
будет выглядеть примерно так:<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <activity android:label="@string/app_name" android:name=".LocationCheckerActivity" > <intent-filter > <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <service android:name=".MyService" android:process=":my_service" /> </application>
ни один из остальных ответов использовать:
com.google.android.gms.location.FusedLocationProviderClient
который является поставщиком Fused Location и основной точкой входа для взаимодействия с поставщиком fused location от Google, и очень трудно найти хороший пример. Это было выпущено в середине 2017 года Google.
Google играть услуг, расположение интерфейсов являются предпочтительными на Андроид API расположения фреймворка (android.местоположение)
если вы в настоящее время используете Android framework location APIs, вам настоятельно рекомендуется как можно скорее переключиться на Google Play services location APIs.
чтобы вы могли использовать Google Location API, сначала добавьте это в свой
build.gradle
compile 'com.google.android.gms:play-services:11.0.0'
затем вы можете использовать этот класс
Wherebouts.java
:import android.location.Location; import android.os.Looper; import android.util.Log; import com.google.android.gms.location.FusedLocationProviderClient; import com.google.android.gms.location.LocationCallback; import com.google.android.gms.location.LocationRequest; import com.google.android.gms.location.LocationResult; import com.google.android.gms.location.LocationServices; import com.google.android.gms.location.LocationSettingsRequest; /** * Uses Google Play API for obtaining device locations * Created by alejandro.tkachuk * alejandro@calculistik.com * www.calculistik.com Mobile Development */ public class Wherebouts { private static final Wherebouts instance = new Wherebouts(); private static final String TAG = Wherebouts.class.getSimpleName(); private FusedLocationProviderClient mFusedLocationClient; private LocationCallback locationCallback; private LocationRequest locationRequest; private LocationSettingsRequest locationSettingsRequest; private Workable<GPSPoint> workable; private static final long UPDATE_INTERVAL_IN_MILLISECONDS = 1000; private static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = 1000; private Wherebouts() { this.locationRequest = new LocationRequest(); this.locationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS); this.locationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS); this.locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder(); builder.addLocationRequest(this.locationRequest); this.locationSettingsRequest = builder.build(); this.locationCallback = new LocationCallback() { @Override public void onLocationResult(LocationResult locationResult) { super.onLocationResult(locationResult); // why? this. is. retarded. Android. Location currentLocation = locationResult.getLastLocation(); GPSPoint gpsPoint = new GPSPoint(currentLocation.getLatitude(), currentLocation.getLongitude()); Log.i(TAG, "Location Callback results: " + gpsPoint); if (null != workable) workable.work(gpsPoint); } }; this.mFusedLocationClient = LocationServices.getFusedLocationProviderClient(MainApplication.getAppContext()); this.mFusedLocationClient.requestLocationUpdates(this.locationRequest, this.locationCallback, Looper.myLooper()); } public static Wherebouts instance() { return instance; } public void onChange(Workable<GPSPoint> workable) { this.workable = workable; } public LocationSettingsRequest getLocationSettingsRequest() { return this.locationSettingsRequest; } public void stop() { Log.i(TAG, "stop() Stopping location tracking"); this.mFusedLocationClient.removeLocationUpdates(this.locationCallback); } }
из вашей деятельности, вы можете использовать его так, передав
скачать исходный код (Получить Текущее Местоположение С Помощью Фоновой Службы)
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="servicetutorial.service"> <uses-permission android:name="android.permission.INTERNET"></uses-permission> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity" android:theme="@android:style/Theme.Translucent.NoTitleBar"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <service android:name=".GoogleService"></service> </application> </manifest>
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:background="#ffffff" android:layout_height="match_parent"> <TextView android:layout_width="match_parent" android:layout_height="50dp" android:background="#3F51B5" android:text="Location using service" android:textColor="#ffffff" android:textSize="20dp" android:gravity="center"/> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerInParent="true" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:orientation="horizontal" android:layout_height="50dp"> <TextView android:layout_width="150dp" android:layout_height="wrap_content" android:text="Latitude" android:layout_gravity="center_vertical" android:layout_marginLeft="10dp" android:textColor="#000000" android:textSize="20dp"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="" android:id="@+id/tv_latitude" android:layout_gravity="center_vertical" android:layout_marginLeft="10dp" android:textColor="#000000" android:textSize="20dp"/> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:orientation="horizontal" android:layout_height="50dp"> <TextView android:layout_width="150dp" android:layout_height="wrap_content" android:text="Longitude" android:layout_gravity="center_vertical" android:layout_marginLeft="10dp" android:textColor="#000000" android:textSize="20dp"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="" android:id="@+id/tv_longitude" android:layout_gravity="center_vertical" android:layout_marginLeft="10dp" android:textColor="#000000" android:textSize="20dp"/> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:orientation="horizontal" android:layout_height="50dp"> <TextView android:layout_width="150dp" android:layout_height="wrap_content" android:text="Address" android:layout_gravity="center_vertical" android:layout_marginLeft="10dp" android:textColor="#000000" android:textSize="20dp"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="" android:id="@+id/tv_address" android:layout_gravity="center_vertical" android:layout_marginLeft="10dp" android:textColor="#000000" android:textSize="20dp"/> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:orientation="horizontal" android:layout_height="50dp"> <TextView android:layout_width="150dp" android:layout_height="wrap_content" android:text="Area" android:layout_gravity="center_vertical" android:layout_marginLeft="10dp" android:textColor="#000000" android:textSize="20dp"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="" android:id="@+id/tv_area" android:layout_gravity="center_vertical" android:layout_marginLeft="10dp" android:textColor="#000000" android:textSize="20dp"/> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:orientation="horizontal" android:layout_height="50dp"> <TextView android:layout_width="150dp" android:layout_height="wrap_content" android:text="Locality" android:layout_gravity="center_vertical" android:layout_marginLeft="10dp" android:textColor="#000000" android:textSize="20dp"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="" android:id="@+id/tv_locality" android:layout_gravity="center_vertical" android:layout_marginLeft="10dp" android:textColor="#000000" android:textSize="20dp"/> </LinearLayout> </LinearLayout> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/btn_start" android:text="Get Location" android:layout_alignParentBottom="true"/> </RelativeLayout>
MainActivity.java
package servicetutorial.service; import android.*; import android.app.Activity; import android.app.ActivityManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.location.Address; import android.location.Geocoder; import android.preference.PreferenceManager; import android.renderscript.Double2; import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import java.io.IOException; import java.util.List; import java.util.Locale; public class MainActivity extends Activity { Button btn_start; private static final int REQUEST_PERMISSIONS = 100; boolean boolean_permission; TextView tv_latitude, tv_longitude, tv_address,tv_area,tv_locality; SharedPreferences mPref; SharedPreferences.Editor medit; Double latitude,longitude; Geocoder geocoder; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn_start = (Button) findViewById(R.id.btn_start); tv_address = (TextView) findViewById(R.id.tv_address); tv_latitude = (TextView) findViewById(R.id.tv_latitude); tv_longitude = (TextView) findViewById(R.id.tv_longitude); tv_area = (TextView)findViewById(R.id.tv_area); tv_locality = (TextView)findViewById(R.id.tv_locality); geocoder = new Geocoder(this, Locale.getDefault()); mPref = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); medit = mPref.edit(); btn_start.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (boolean_permission) { if (mPref.getString("service", "").matches("")) { medit.putString("service", "service").commit(); Intent intent = new Intent(getApplicationContext(), GoogleService.class); startService(intent); } else { Toast.makeText(getApplicationContext(), "Service is already running", Toast.LENGTH_SHORT).show(); } } else { Toast.makeText(getApplicationContext(), "Please enable the gps", Toast.LENGTH_SHORT).show(); } } }); fn_permission(); } private void fn_permission() { if ((ContextCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED)) { if ((ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, android.Manifest.permission.ACCESS_FINE_LOCATION))) { } else { ActivityCompat.requestPermissions(MainActivity.this, new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION }, REQUEST_PERMISSIONS); } } else { boolean_permission = true; } } @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); switch (requestCode) { case REQUEST_PERMISSIONS: { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { boolean_permission = true; } else { Toast.makeText(getApplicationContext(), "Please allow the permission", Toast.LENGTH_LONG).show(); } } } } private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { latitude = Double.valueOf(intent.getStringExtra("latutide")); longitude = Double.valueOf(intent.getStringExtra("longitude")); List<Address> addresses = null; try { addresses = geocoder.getFromLocation(latitude, longitude, 1); String cityName = addresses.get(0).getAddressLine(0); String stateName = addresses.get(0).getAddressLine(1); String countryName = addresses.get(0).getAddressLine(2); tv_area.setText(addresses.get(0).getAdminArea()); tv_locality.setText(stateName); tv_address.setText(countryName); } catch (IOException e1) { e1.printStackTrace(); } tv_latitude.setText(latitude+""); tv_longitude.setText(longitude+""); tv_address.getText(); } }; @Override protected void onResume() { super.onResume(); registerReceiver(broadcastReceiver, new IntentFilter(GoogleService.str_receiver)); } @Override protected void onPause() { super.onPause(); unregisterReceiver(broadcastReceiver); } }
GoogleService.java
package servicetutorial.service; import android.app.Service; import android.content.Context; import android.content.Intent; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.support.annotation.Nullable; import android.util.Log; import java.util.Timer; import java.util.TimerTask; /** * Created by deepshikha on 24/11/16. */ public class GoogleService extends Service implements LocationListener{ 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 = 1000; public static String str_receiver = "servicetutorial.service.receiver"; Intent intent; public GoogleService() { } @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); // fn_getlocation(); } @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){ }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("latitude",location.getLatitude()+""); Log.e("longitude",location.getLongitude()+""); latitude = location.getLatitude(); longitude = location.getLongitude(); 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("latitude",location.getLatitude()+""); Log.e("longitude",location.getLongitude()+""); latitude = location.getLatitude(); longitude = location.getLongitude(); fn_update(location); } } } } } 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); } }
добавить эту зависимость
compile 'com.google.android.gms:play-services:9.4.0'
использование : GCM Network Manager
запустите это, чтобы запустить периодическую задачу, которая будет выполняться даже после перезагрузки:
PeriodicTask task = new PeriodicTask.Builder() .setService(MyLocationService.class) .setTag("periodic") .setPeriod(30L) .setPersisted(true) .build(); mGcmNetworkManager.schedule(task);
затем в onRunTask() получить текущее местоположение и использовать его (в этом примере событие отправляется в конце, чтобы пользовательский интерфейс знал, что местоположение было найдено):
public void getLastKnownLocation() { Location lastKnownGPSLocation; Location lastKnownNetworkLocation; String gpsLocationProvider = LocationManager.GPS_PROVIDER; String networkLocationProvider = LocationManager.NETWORK_PROVIDER; try { locationManager = (LocationManager) App.get().getSystemService(Context.LOCATION_SERVICE); lastKnownNetworkLocation = locationManager.getLastKnownLocation(networkLocationProvider); lastKnownGPSLocation = locationManager.getLastKnownLocation(gpsLocationProvider); if (lastKnownGPSLocation != null) { Log.i(TAG, "lastKnownGPSLocation is used."); this.mCurrentLocation = lastKnownGPSLocation; } else if (lastKnownNetworkLocation != null) { Log.i(TAG, "lastKnownNetworkLocation is used."); this.mCurrentLocation = lastKnownNetworkLocation; } else { Log.e(TAG, "lastLocation is not known."); return; } LocationChangedEvent event = new LocationChangedEvent(); event.setLocation(mCurrentLocation); EventHelper.publishEvent(event); } catch (SecurityException sex) { Log.e(TAG, "Location permission is not granted!"); } return; }
MyLocationService в целом:
public class MyLocationService extends GcmTaskService { private static final String TAG = MyLocationService.class.getSimpleName(); private LocationManager locationManager; private Location mCurrentLocation; public static final String TASK_GET_LOCATION_ONCE="location_oneoff_task"; public static final String TASK_GET_LOCATION_PERIODIC="location_periodic_task"; private static final int RC_PLAY_SERVICES = 123; @Override public void onInitializeTasks() { // When your package is removed or updated, all of its network tasks are cleared by // the GcmNetworkManager. You can override this method to reschedule them in the case of // an updated package. This is not called when your application is first installed. // // This is called on your application's main thread. startPeriodicLocationTask(TASK_GET_LOCATION_PERIODIC, 30L, null); } @Override public int onRunTask(TaskParams taskParams) { Log.d(TAG, "onRunTask: " + taskParams.getTag()); String tag = taskParams.getTag(); Bundle extras = taskParams.getExtras(); // Default result is success. int result = GcmNetworkManager.RESULT_SUCCESS; switch (tag) { case TASK_GET_LOCATION_ONCE: getLastKnownLocation(); break; case TASK_GET_LOCATION_PERIODIC: getLastKnownLocation(); break; } return result; } public void getLastKnownLocation() { Location lastKnownGPSLocation; Location lastKnownNetworkLocation; String gpsLocationProvider = LocationManager.GPS_PROVIDER; String networkLocationProvider = LocationManager.NETWORK_PROVIDER; try { locationManager = (LocationManager) App.get().getSystemService(Context.LOCATION_SERVICE); lastKnownNetworkLocation = locationManager.getLastKnownLocation(networkLocationProvider); lastKnownGPSLocation = locationManager.getLastKnownLocation(gpsLocationProvider); if (lastKnownGPSLocation != null) { Log.i(TAG, "lastKnownGPSLocation is used."); this.mCurrentLocation = lastKnownGPSLocation; } else if (lastKnownNetworkLocation != null) { Log.i(TAG, "lastKnownNetworkLocation is used."); this.mCurrentLocation = lastKnownNetworkLocation; } else { Log.e(TAG, "lastLocation is not known."); return; } LocationChangedEvent event = new LocationChangedEvent(); event.setLocation(mCurrentLocation); EventHelper.publishEvent(event); } catch (SecurityException sex) { Log.e(TAG, "Location permission is not granted!"); } return; } public static void startOneOffLocationTask(String tag, Bundle extras) { Log.d(TAG, "startOneOffLocationTask"); GcmNetworkManager mGcmNetworkManager = GcmNetworkManager.getInstance(App.get()); OneoffTask.Builder taskBuilder = new OneoffTask.Builder() .setService(MyLocationService.class) .setTag(tag); if (extras != null) taskBuilder.setExtras(extras); OneoffTask task = taskBuilder.build(); mGcmNetworkManager.schedule(task); } public static void startPeriodicLocationTask(String tag, Long period, Bundle extras) { Log.d(TAG, "startPeriodicLocationTask"); GcmNetworkManager mGcmNetworkManager = GcmNetworkManager.getInstance(App.get()); PeriodicTask.Builder taskBuilder = new PeriodicTask.Builder() .setService(MyLocationService.class) .setTag(tag) .setPeriod(period) .setPersisted(true) .setRequiredNetwork(Task.NETWORK_STATE_CONNECTED); if (extras != null) taskBuilder.setExtras(extras); PeriodicTask task = taskBuilder.build(); mGcmNetworkManager.schedule(task); } public static boolean checkPlayServicesAvailable(Activity activity) { GoogleApiAvailability availability = GoogleApiAvailability.getInstance(); int resultCode = availability.isGooglePlayServicesAvailable(App.get()); if (resultCode != ConnectionResult.SUCCESS) { if (availability.isUserResolvableError(resultCode)) { // Show dialog to resolve the error. availability.getErrorDialog(activity, resultCode, RC_PLAY_SERVICES).show(); } return false; } else { return true; } }
также добавьте эти 2 к AndroidManifest.XML-код:
<manifest... <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <application... <service android:name=".api.location.MyLocationService" android:exported="true" android:permission="com.google.android.gms.permission.BIND_NETWORK_TASK_SERVICE"> <intent-filter> <action android:name="com.google.android.gms.gcm.ACTION_TASK_READY" /> </intent-filter> </service>
вы должны создать услуги.Эта служба должна реализовать LocationListener. Затем вы должны использовать AlarmManager для повторного вызова службы с определенным ограничением по времени.
Я надеюсь, что это поможет вам:)
С помощью API LocationServices GoogleApiClient мы можем получить текущее местоположение пользователя/устройства в определенном временном интервале. Это можно добавить в фоновую службу, которая обновляет активность, когда onLocationChanged обратные вызовы
фоновая служба будет продолжать работать до тех пор, пока приложение существует в памяти и прилипает к ящику уведомлений. Служба обрабатывает следующее функциональные возможности,
- подключение к Google LocationServices API
- получение текущего местоположения
- совместное использование результата деятельности
Сервис С Location Listener
public class LocationMonitoringService extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener { ... ... ... @Override public int onStartCommand(Intent intent, int flags, int startId) { mLocationClient = new GoogleApiClient.Builder(this) .addConnectionCallbacks(this) .addOnConnectionFailedListener(this) .addApi(LocationServices.API) .build(); mLocationRequest.setInterval(10000); //10 secs mLocationRequest.setFastestInterval(5000); //5 secs int priority = LocationRequest.PRIORITY_HIGH_ACCURACY; //by default //PRIORITY_BALANCED_POWER_ACCURACY, PRIORITY_LOW_POWER, PRIORITY_NO_POWER are the other priority modes mLocationRequest.setPriority(priority); mLocationClient.connect(); //Make it stick to the notification panel so it is less prone to get cancelled by the Operating System. return START_STICKY; } @Nullable @Override public IBinder onBind(Intent intent) { return null; } /* * LOCATION CALLBACKS */ @Override public void onConnected(Bundle dataBundle) { if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { // TODO: Consider calling // ActivityCompat#requestPermissions // here to request the missing permissions, and then overriding // public void onRequestPermissionsResult(int requestCode, String[] permissions, // int[] grantResults) // to handle the case where the user grants the permission. See the documentation // for ActivityCompat#requestPermissions for more details. Log.d(TAG, "== Error On onConnected() Permission not granted"); //Permission not granted by user so cancel the further execution. return; } LocationServices.FusedLocationApi.requestLocationUpdates(mLocationClient, mLocationRequest, this); Log.d(TAG, "Connected to Google API"); } /* * Called by Location Services if the connection to the * location client drops because of an error. */ @Override public void onConnectionSuspended(int i) { Log.d(TAG, "Connection suspended"); } @Override public void onConnectionFailed(ConnectionResult connectionResult) { Log.d(TAG, "Failed to connect to Google API"); } //to get the location change @Override public void onLocationChanged(Location location) { Log.d(TAG, "Location changed"); if (location != null) { //Do something with the location details, if (location != null) { //call your API callAPI(String.valueOf(location.getLatitude()), String.valueOf(location.getLongitude())); } } } }
Смотрите полный учебник с исходным кодом и объяснением подробно >>
У меня есть попробовать мой код и получил успех попробовать это
package com.mobeyosoft.latitudelongitude; import android.app.Service; import android.content.Context; import android.content.Intent; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.os.Bundle; import android.os.IBinder; import android.util.Log; import android.widget.Toast; /** * Created by 5943 6417 on 14-09-2016. */ public class LocationService extends Service { public static final String BROADCAST_ACTION = "Hello World"; private static final int TWO_MINUTES = 1000 * 60 * 1; public LocationManager locationManager; public MyLocationListener listener; public Location previousBestLocation = null; Context context; Intent intent; int counter = 0; @Override public void onCreate() { super.onCreate(); intent = new Intent(BROADCAST_ACTION); context=this; } @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(); Toast.makeText(context, "Latitude" + loc.getLatitude() + "\nLongitude"+loc.getLongitude(),Toast.LENGTH_SHORT).show(); 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) { } } }
import android.app.Service; import android.content.Context; import android.content.Intent; import android.hardware.GeomagneticField; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.os.Bundle; import android.os.IBinder; import android.provider.Settings; import android.widget.Toast; public class LocationService extends Service { private static final int MINUTES = 1000 * 60 * 2; public LocationManager locationManager; public MyLocationListener listener; public Location previousBestLocation = null; Context mContext; private boolean isGpsEnabled = false; private boolean isNetworkEnabled = false; private GeomagneticField geoField; private double latitude = 0.0; private double longitude = 0.0; @Override public void onCreate() { super.onCreate(); mContext = getApplicationContext(); if (locationManager == null) { locationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE); } getCurrentLocation(); } private void getCurrentLocation() { try { assert locationManager != null; isGpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER); } catch (Exception ex) { ex.printStackTrace(); } if (!isGpsEnabled && !isNetworkEnabled) { showSettingsAlert(); } listener = new MyLocationListener(); try { locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10000, 0, listener); locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 10000, 0, listener); } catch (SecurityException e) { e.printStackTrace(); } } private void showSettingsAlert() { Toast.makeText(mContext, "GPS is disabled in your device. Please Enable it ?", Toast.LENGTH_LONG).show(); Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); mContext.startActivity(intent); } @Override public int onStartCommand(Intent intent, int flags, int startId) { return START_STICKY; } @Override public IBinder onBind(Intent intent) { return null; } protected boolean isBetterLocation(Location location, Location currentBestLocation) { if (currentBestLocation == null) { return true; } long timeDelta = location.getTime() - currentBestLocation.getTime(); boolean isSignificantlyNewer = timeDelta > MINUTES; boolean isSignificantlyOlder = timeDelta < -MINUTES; boolean isNewer = timeDelta > 0; if (isSignificantlyNewer) { return true; } else if (isSignificantlyOlder) { return false; } int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy()); boolean isLessAccurate = accuracyDelta > 0; boolean isMoreAccurate = accuracyDelta < 0; boolean isSignificantlyLessAccurate = accuracyDelta > 200; boolean isFromSameProvider = isSameProvider(location.getProvider(), currentBestLocation.getProvider()); if (isMoreAccurate) { return true; } else if (isNewer && !isLessAccurate) { return true; } else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) { return true; } return false; } private boolean isSameProvider(String provider1, String provider2) { if (provider1 == null) { return provider2 == null; } return provider1.equals(provider2); } @Override public void onDestroy() { super.onDestroy(); locationManager.removeUpdates(listener); } private void setupFinalLocationData(Location mLocation) { if (mLocation != null) { geoField = new GeomagneticField( Double.valueOf(mLocation.getLatitude()).floatValue(), Double.valueOf(mLocation.getLongitude()).floatValue(), Double.valueOf(mLocation.getAltitude()).floatValue(), System.currentTimeMillis() ); latitude = mLocation.getLatitude(); longitude = mLocation.getLongitude(); //Update latitude and longtitude in SharedPreference... } } public class MyLocationListener implements LocationListener { public void onLocationChanged(final Location loc) { if (isBetterLocation(loc, previousBestLocation)) { setupFinalLocationData(loc); } } public void onProviderDisabled(String provider) { } public void onProviderEnabled(String provider) { } public void onStatusChanged(String provider, int status, Bundle extras) { } } }
вы можете архивировать его с помощью диспетчера службы и сигнализации, но будьте осторожны с этим, потому что если вы установите высокий приоритет, вы собираетесь разрядить батарею телефона, с другой стороны, вам действительно нужно уведомлять о местоположении каждую минуту? Это потому, что единственный способ увидеть значительное изменение местоположения пользователя, это путешествие в автомобиле или поезде. Я только спрашиваю, потому что это будет зависеть от вашего приложения и требования отслеживания.
Ну создать класс расширения службы, эта служба будет содержать ваш класс location listener (Fused Location Provider) цель этой службы состоит в том, чтобы периодически получать местоположение, что-то вроде этого
public class LocationGetter extends Service { ...... public class MyLocationListener implements GooglePlayServicesClient.ConnectionCallbacks,GooglePlayServicesClient.OnConnectionFailedListener,LocationListener, com.google.android.gms.location.LocationListener { //your fused Location provider code } ...... }
затем создайте класс, расширяющий широковещательный приемник, таким образом, чтобы цель этого широковещательного приемника состояла в том, чтобы проверить, жив ли сервис, если не перезапустить сервис даже во время включения/выключения телефона ....
Регистрация приемника в активности ur, прослушивание трансляций , приемник unregeister в зависимости от потребности ur...
-- Kotlin Version
package com.ps.salestrackingapp.Services import android.app.Service import android.content.Context import android.content.Intent import android.location.Location import android.location.LocationManager import android.os.Bundle import android.os.IBinder import android.util.Log class LocationService : Service() { private var mLocationManager: LocationManager? = null var mLocationListeners = arrayOf(LocationListener(LocationManager.GPS_PROVIDER), LocationListener(LocationManager.NETWORK_PROVIDER)) class LocationListener(provider: String) : android.location.LocationListener { internal var mLastLocation: Location init { Log.e(TAG, "LocationListener $provider") mLastLocation = Location(provider) } override fun onLocationChanged(location: Location) { Log.e(TAG, "onLocationChanged: $location") mLastLocation.set(location) Log.v("LastLocation", mLastLocation.latitude.toString() +" " + mLastLocation.longitude.toString()) } override fun onProviderDisabled(provider: String) { Log.e(TAG, "onProviderDisabled: $provider") } override fun onProviderEnabled(provider: String) { Log.e(TAG, "onProviderEnabled: $provider") } override fun onStatusChanged(provider: String, status: Int, extras: Bundle) { Log.e(TAG, "onStatusChanged: $provider") } } override fun onBind(arg0: Intent): IBinder? { return null } override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { Log.e(TAG, "onStartCommand") super.onStartCommand(intent, flags, startId) return Service.START_STICKY } override fun onCreate() { Log.e(TAG, "onCreate") initializeLocationManager() try { mLocationManager!!.requestLocationUpdates( LocationManager.NETWORK_PROVIDER, LOCATION_INTERVAL.toLong(), LOCATION_DISTANCE, mLocationListeners[1]) } catch (ex: java.lang.SecurityException) { Log.i(TAG, "fail to request location update, ignore", ex) } catch (ex: IllegalArgumentException) { Log.d(TAG, "network provider does not exist, " + ex.message) } try { mLocationManager!!.requestLocationUpdates( LocationManager.GPS_PROVIDER, LOCATION_INTERVAL.toLong(), LOCATION_DISTANCE, mLocationListeners[0]) } catch (ex: java.lang.SecurityException) { Log.i(TAG, "fail to request location update, ignore", ex) } catch (ex: IllegalArgumentException) { Log.d(TAG, "gps provider does not exist " + ex.message) } } override fun onDestroy() { Log.e(TAG, "onDestroy") super.onDestroy() if (mLocationManager != null) { for (i in mLocationListeners.indices) { try { mLocationManager!!.removeUpdates(mLocationListeners[i]) } catch (ex: Exception) { Log.i(TAG, "fail to remove location listners, ignore", ex) } } } } private fun initializeLocationManager() { Log.e(TAG, "initializeLocationManager") if (mLocationManager == null) { mLocationManager = applicationContext.getSystemService(Context.LOCATION_SERVICE) as LocationManager } } companion object { private val TAG = "BOOMBOOMTESTGPS" private val LOCATION_INTERVAL = 1000 private val LOCATION_DISTANCE = 0f } }
чтобы получить обратный вызов на LocationChange
определить интерфейс
public interface LocationCallback { public void locationChanged(Location location); }
обратный вызов в вашей деятельности
public static LocationCallback callback; public void getUserLocation() { callback = new LocationCallback() { @Override public void locationChanged(Location location) { Toast.makeText(getApplicationContext(), location.getLatitude() + "," + location.getLongitude(), Toast.LENGTH_SHORT).show(); } }; Intent service_intent = new Intent(this, GPSService.class); startService(service_intent); }
изменить метод onLocationChange на
@Override public void onLocationChanged(Location location) { Log.e(TAG, "onLocationChanged: " + location); MapsActivity.callback.locationChanged(location); mLastLocation.set(location); }
для отслеживания местоположения каждые 10 минут(по требованию), пожалуйста, перейдите по этой ссылке он работает нормально, без каких-либо проблем
https://github.com/safetysystemtechnology/location-tracker-background