From 7f169e5b61312d3aff06bf425b3b94f76fd8f354 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mieszko=20Wrzeszczy=C5=84ski?= Date: Mon, 31 Dec 2018 17:25:06 +0100 Subject: [PATCH 1/2] Choose only fused location --- app/src/main/AndroidManifest.xml | 7 +- .../findmytutor/activity/TutorsListTab.java | 46 +++ .../BackgroundLocalizationService.java | 62 +--- .../service/BackgroundService.java | 264 ++++++++++++++++++ app/src/main/res/layout/tutors_list_tabs.xml | 56 ++++ 5 files changed, 373 insertions(+), 62 deletions(-) create mode 100644 app/src/main/java/com/uam/wmi/findmytutor/activity/TutorsListTab.java create mode 100644 app/src/main/java/com/uam/wmi/findmytutor/service/BackgroundService.java create mode 100644 app/src/main/res/layout/tutors_list_tabs.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 5ccbfb9..03c49a3 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -53,12 +53,17 @@ android:name=".activity.SettingsActivity" android:screenOrientation="portrait" android:configChanges="keyboardHidden|orientation|screenSize"/> - + { try { mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this); - initializeLocationManager(); getLocalizationFromListeners(); - changeBackgroundMode(); } finally { mFusedLocationClient = null; destroyLocationListeners(); @@ -192,10 +190,6 @@ public class BackgroundLocalizationService extends Service { return; } - List providers1 = mLocationManager.getProviders(true); - Location bestLocation = null; - AtomicReference triggerAnotherLocationListener = new AtomicReference<>(false); - mFusedLocationClient.getLastLocation().addOnSuccessListener( location -> { if (location != null) { @@ -204,24 +198,8 @@ public class BackgroundLocalizationService extends Service { sendCoordinateToBackend(location); } - triggerAnotherLocationListener.set(true); }); - if (triggerAnotherLocationListener.get()) { - for (String provider : providers1) { - Location location = mLocationManager.getLastKnownLocation(provider); - - if (location == null) { - continue; - } - if (bestLocation == null || location.getAccuracy() < bestLocation.getAccuracy()) { - bestLocation = location; - } - } - - coordinatesHistory.add(bestLocation); - } - } private void sendCoordinateToBackend(Location location) { @@ -238,48 +216,10 @@ public class BackgroundLocalizationService extends Service { } private void destroyLocationListeners(){ - if (mLocationManager != null) { - for (LocationListener listener : mLocationListeners) { - try { - if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { - return; - } - mLocationManager.removeUpdates(listener); - } catch (Exception ex) { - Log.i(TAG, "fail to remove location listener, ignore", ex); - } - } - } + } - private void initializeLocationManager() { - Log.e(TAG, "initializeLocationManager - LOCATION_INTERVAL: " + notify_interval + " LOCATION_DISTANCE: " + LOCATION_DISTANCE); - - if (mLocationManager == null) { - mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE); - } - - Integer providerIndex = 0; - - for (LocationListener listener : mLocationListeners) { - try { - mLocationManager.requestLocationUpdates( - providers.get(providerIndex), - notify_interval, - LOCATION_DISTANCE, - listener - ); - - } 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()); - } - - providerIndex++; - } - } private class LocationListener implements android.location.LocationListener { diff --git a/app/src/main/java/com/uam/wmi/findmytutor/service/BackgroundService.java b/app/src/main/java/com/uam/wmi/findmytutor/service/BackgroundService.java new file mode 100644 index 0000000..23f25f2 --- /dev/null +++ b/app/src/main/java/com/uam/wmi/findmytutor/service/BackgroundService.java @@ -0,0 +1,264 @@ +package com.uam.wmi.findmytutor.service; + +import android.Manifest; +import android.annotation.SuppressLint; +import android.app.Service; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.location.Location; +import android.location.LocationListener; +import android.os.Binder; +import android.os.Bundle; +import android.os.IBinder; +import android.os.PowerManager; +import android.provider.SyncStateContract; +import android.support.v4.app.ActivityCompat; +import android.util.Log; + +import com.google.android.gms.common.ConnectionResult; +import com.google.android.gms.common.GooglePlayServicesUtil; +import com.google.android.gms.common.api.GoogleApiClient; +import com.google.android.gms.location.LocationRequest; +import com.google.android.gms.location.LocationServices; + +import java.text.DateFormat; +import java.util.Date; + +import static com.uam.wmi.findmytutor.utils.Const.onlineBackgroundLocationInterval; + + +public class BackgroundService extends Service implements + GoogleApiClient.ConnectionCallbacks, + GoogleApiClient.OnConnectionFailedListener, + LocationListener { + + IBinder mBinder = new LocalBinder(); + private static final String TAG = "MyLocationService"; + + private GoogleApiClient mGoogleApiClient; + private PowerManager.WakeLock mWakeLock; + private LocationRequest mLocationRequest; + // Flag that indicates if a request is underway. + private boolean mInProgress; + private static long notify_interval = onlineBackgroundLocationInterval; + + private Boolean servicesAvailable = false; + + public class LocalBinder extends Binder { + public BackgroundService getServerInstance() { + return BackgroundService.this; + } + } + + @Override + public void onCreate() { + super.onCreate(); + + + mInProgress = false; + // Create the LocationRequest object + mLocationRequest = LocationRequest.create(); + // Use high accuracy + mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY); + // Set the update interval to 5 seconds + mLocationRequest.setInterval(notify_interval); + // Set the fastest update interval to 1 second + mLocationRequest.setFastestInterval(notify_interval); + + servicesAvailable = servicesConnected(); + + /* + * Create a new location client, using the enclosing class to + * handle callbacks. + */ + setUpLocationClientIfNeeded(); + + + } + + /* + * Create a new location client, using the enclosing class to + * handle callbacks. + */ + protected synchronized void buildGoogleApiClient() { + this.mGoogleApiClient = new GoogleApiClient.Builder(this) + .addConnectionCallbacks(this) + .addOnConnectionFailedListener(this) + .addApi(LocationServices.API) + .build(); + } + + private boolean servicesConnected() { + + // Check that Google Play services is available + int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this); + + // If Google Play services is available + if (ConnectionResult.SUCCESS == resultCode) { + + return true; + } else { + + return false; + } + } + + @SuppressLint("InvalidWakeLockTag") + public int onStartCommand(Intent intent, int flags, int startId) { + super.onStartCommand(intent, flags, startId); + + PowerManager mgr = (PowerManager) getSystemService(Context.POWER_SERVICE); + + /* + WakeLock is reference counted so we don't want to create multiple WakeLocks. So do a check before initializing and acquiring. + + This will fix the "java.lang.Exception: WakeLock finalized while still held: MyWakeLock" error that you may find. + */ + /* if (this.mWakeLock == null) { //**Added this + this.mWakeLock = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyWakeLock"); + } + + if (!this.mWakeLock.isHeld()) { //**Added this + this.mWakeLock.acquire(10*60*1000L *//*10 minutes*//*); + }*/ + + if (!servicesAvailable || mGoogleApiClient.isConnected() || mInProgress) + return START_STICKY; + + setUpLocationClientIfNeeded(); + if (!mGoogleApiClient.isConnected() || !mGoogleApiClient.isConnecting() && !mInProgress) { + mInProgress = true; + mGoogleApiClient.connect(); + } + + return START_STICKY; + } + + + private void setUpLocationClientIfNeeded() { + if (mGoogleApiClient == null) + buildGoogleApiClient(); + } + + // Define the callback method that receives location updates + @Override + public void onLocationChanged(Location location) { + // Report to the UI that the location was updated + String msg = Double.toString(location.getLatitude()) + "," + + Double.toString(location.getLongitude()); + Log.d("debug", msg); + Log.e(TAG, "onLocationChanged: " + location); + + // Toast.makeText(this, msg, Toast.LENGTH_SHORT).show(); + } + + @Override + public void onStatusChanged(String s, int i, Bundle bundle) { + + } + + @Override + public void onProviderEnabled(String s) { + + } + + @Override + public void onProviderDisabled(String s) { + + } + + @Override + public IBinder onBind(Intent intent) { + return mBinder; + } + + @Override + public void onDestroy() { + // Turn off the request flag + this.mInProgress = false; + + if (this.servicesAvailable && this.mGoogleApiClient != null) { + this.mGoogleApiClient.unregisterConnectionCallbacks(this); + this.mGoogleApiClient.unregisterConnectionFailedListener(this); + this.mGoogleApiClient.disconnect(); + // Destroy the current location client + this.mGoogleApiClient = null; + } + // Display the connection status + // Toast.makeText(this, DateFormat.getDateTimeInstance().format(new Date()) + ": + // Disconnected. Please re-connect.", Toast.LENGTH_SHORT).show(); + + if (this.mWakeLock != null) { + this.mWakeLock.release(); + this.mWakeLock = null; + } + + super.onDestroy(); + } + + /* + * Called by Location Services when the request to connect the + * client finishes successfully. At this point, you can + * request the current location or start periodic updates + */ + @Override + public void onConnected(Bundle bundle) { + + // Request location updates using static settings + //Intent intent = new Intent(this, LocationReceiver.class); + 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. + return; + } + + LocationServices.getFusedLocationProviderClient(this); + LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, (com.google.android.gms.location.LocationListener) this); + + /* .requestLocationUpdates(this.mGoogleApiClient, + mLocationRequest, (com.google.android.gms.location.LocationListener) this); // This is the changed line.*/ + + } + + /* + * Called by Location Services if the connection to the + * location client drops because of an error. + */ + @Override + public void onConnectionSuspended(int i) { + // Turn off the request flag + mInProgress = false; + // Destroy the current location client + mGoogleApiClient = null; + // Display the connection status + // Toast.makeText(this, DateFormat.getDateTimeInstance().format(new Date()) + ": Disconnected. Please re-connect.", Toast.LENGTH_SHORT).show(); + } + + /* + * Called by Location Services if the attempt to + * Location Services fails. + */ + @Override + public void onConnectionFailed(ConnectionResult connectionResult) { + mInProgress = false; + + /* + * Google Play services can resolve some errors it detects. + * If the error has a resolution, try sending an Intent to + * start a Google Play services activity that can resolve + * error. + */ + if (connectionResult.hasResolution()) { + + // If no resolution is available, display an error dialog + } else { + + } + } +} diff --git a/app/src/main/res/layout/tutors_list_tabs.xml b/app/src/main/res/layout/tutors_list_tabs.xml new file mode 100644 index 0000000..c09a3b2 --- /dev/null +++ b/app/src/main/res/layout/tutors_list_tabs.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 18547a3c52d17fa2d079ad94625ff15f585cf771 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mieszko=20Wrzeszczy=C5=84ski?= Date: Tue, 1 Jan 2019 20:03:30 +0100 Subject: [PATCH 2/2] Remove unnecessary code --- .../service/BackgroundLocalizationService.java | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/app/src/main/java/com/uam/wmi/findmytutor/service/BackgroundLocalizationService.java b/app/src/main/java/com/uam/wmi/findmytutor/service/BackgroundLocalizationService.java index aedb4bc..3419925 100644 --- a/app/src/main/java/com/uam/wmi/findmytutor/service/BackgroundLocalizationService.java +++ b/app/src/main/java/com/uam/wmi/findmytutor/service/BackgroundLocalizationService.java @@ -25,7 +25,6 @@ import android.util.Log; import com.annimon.stream.Stream; import com.google.android.gms.location.FusedLocationProviderClient; import com.google.android.gms.location.LocationServices; -import com.jakewharton.retrofit2.adapter.rxjava2.HttpException; import com.mapbox.geojson.Point; import com.mapbox.mapboxsdk.geometry.LatLng; import com.uam.wmi.findmytutor.model.Coordinate; @@ -33,21 +32,17 @@ import com.uam.wmi.findmytutor.network.ApiClient; import com.uam.wmi.findmytutor.utils.ApproximatedLocalization; import com.uam.wmi.findmytutor.utils.MapUtils; import com.uam.wmi.findmytutor.utils.PrefUtils; -import com.uam.wmi.findmytutor.utils.RestApiHelper; import com.uam.wmi.findmytutor.utils.SharingLevel; import org.apache.commons.collections4.queue.CircularFifoQueue; import java.util.ArrayList; import java.util.List; -import java.util.concurrent.atomic.AtomicReference; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.CompositeDisposable; import io.reactivex.observers.DisposableCompletableObserver; -import io.reactivex.observers.DisposableSingleObserver; import io.reactivex.schedulers.Schedulers; -import okhttp3.ResponseBody; import static com.uam.wmi.findmytutor.utils.Const.offlineBackgroundLocationInterval; import static com.uam.wmi.findmytutor.utils.Const.onlineBackgroundLocationInterval; @@ -60,18 +55,14 @@ import static java.lang.String.valueOf; public class BackgroundLocalizationService extends Service { private static final String TAG = "MyLocationService"; - private static final float LOCATION_DISTANCE = 1f; private static long notify_interval = onlineBackgroundLocationInterval; private static long notify_interval_inside_building = onlineBackgroundLocationInterval; private static long notify_interval_outside_building = offlineBackgroundLocationInterval; private static int coordinatesHistoryLength = 5; - private static final Long LOCATION_INTERVAL = notify_interval; private Location mLastLocation; private Boolean stopService = false; private ArrayList providers = new ArrayList(); - private LocationListener[] mLocationListeners; private CircularFifoQueue coordinatesHistory = new CircularFifoQueue(coordinatesHistoryLength); - private LocationManager mLocationManager = null; private Handler mHandler = new Handler(); private Runnable mStatusChecker; private FusedLocationProviderClient mFusedLocationClient; @@ -80,12 +71,6 @@ public class BackgroundLocalizationService extends Service { providers.add(LocationManager.GPS_PROVIDER); providers.add(LocationManager.NETWORK_PROVIDER); providers.add(LocationManager.PASSIVE_PROVIDER); - - mLocationListeners = new LocationListener[]{ - new LocationListener(LocationManager.GPS_PROVIDER), - new LocationListener(LocationManager.NETWORK_PROVIDER), - new LocationListener(LocationManager.PASSIVE_PROVIDER) - }; } @Override @@ -130,6 +115,7 @@ public class BackgroundLocalizationService extends Service { try { mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this); getLocalizationFromListeners(); + changeBackgroundMode(); } finally { mFusedLocationClient = null; destroyLocationListeners();