From f96d7e908fcf3613546ebf57b3f1b76fd3bd8b27 Mon Sep 17 00:00:00 2001 From: paroca72 Date: Sun, 7 Aug 2016 14:06:20 +0700 Subject: [PATCH] Improved the ScLocationService class --- .idea/dictionaries/Samuele.xml | 3 - .idea/misc.xml | 19 -- .idea/vcs.xml | 2 +- README.md | 2 +- ScLocationService.md | 17 ++ app/build.gradle | 3 +- .../utils/demo/LocationChecker.java | 13 + .../res/layout/activity_location_checker.xml | 127 +++++---- gradle.properties | 1 + library/build.gradle | 8 +- library/src/main/AndroidManifest.xml | 4 + .../sccomponents/utils/ScLocationService.java | 246 +++++++++++++++++- 12 files changed, 359 insertions(+), 86 deletions(-) delete mode 100644 .idea/dictionaries/Samuele.xml diff --git a/.idea/dictionaries/Samuele.xml b/.idea/dictionaries/Samuele.xml deleted file mode 100644 index c9d9f74..0000000 --- a/.idea/dictionaries/Samuele.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index f0ee78c..5d19981 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -27,25 +27,6 @@ - - - - - - - - - Spelling - - - - - SpellCheckingInspection - - - - - diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 94a25f7..35eb1dd 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/README.md b/README.md index 1d14862..c1f3007 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ Add the dependency ```java dependencies { ... - compile 'com.github.paroca72:sc-utils:1.2.1' + compile 'com.github.paroca72:sc-utils:1.2.5' } ``` diff --git a/ScLocationService.md b/ScLocationService.md index 0a1bef6..1f38215 100644 --- a/ScLocationService.md +++ b/ScLocationService.md @@ -2,8 +2,11 @@ This class can be used for retrieve the location manager and for maintain checked the location accessibility. This class inherit from the [ScChecker](ScChecker.md).
+Now base on FusedLocationApi can tracking the location updates using startLocationTracking(...) method. +
Through the listener implementation you can know when the location accessibility status changed. + #### Methods - **ConnectivityManager getConnectivityManager()**
Return the connectivity manager when available. @@ -13,6 +16,20 @@ Return the connectivity manager when available. true if able to find the location by the GPS. - **boolean check()**
true if is possible to retrieve the current location. +- **boolean isLocationTrackerEnabled()**
+Check if the location tracker is enabled +- **boolean isGoogleAPIAvailable()**
+Check is the google API is available. +The google API needed for the focused location tracker. +- **void startLocationTracking(LocationListener listener)**
+Start the location tracking. +- **void stopLocationTracking()**
+Stop the location tracking. +- **Location getLocation()**
+Get the last known location. +- **LocationRequest getLocationRequest()**
+Get the location request settings object. + ### Example For an example please take a look the demo section in the project structure. diff --git a/app/build.gradle b/app/build.gradle index 8604f90..aa9d89a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'com.android.application' android { compileSdkVersion 23 - buildToolsVersion "23.0.2" + buildToolsVersion '24.0.1' defaultConfig { applicationId "com.sccomponents.utils.demo" @@ -10,6 +10,7 @@ android { targetSdkVersion 23 versionCode 1 versionName "1.0" + multiDexEnabled true } buildTypes { release { diff --git a/app/src/main/java/com/sccomponents/utils/demo/LocationChecker.java b/app/src/main/java/com/sccomponents/utils/demo/LocationChecker.java index 5fcd1c3..0772f91 100644 --- a/app/src/main/java/com/sccomponents/utils/demo/LocationChecker.java +++ b/app/src/main/java/com/sccomponents/utils/demo/LocationChecker.java @@ -1,9 +1,11 @@ package com.sccomponents.utils.demo; +import android.location.Location; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.widget.TextView; +import com.google.android.gms.location.LocationListener; import com.sccomponents.utils.ScChecker; import com.sccomponents.utils.ScLocationService; @@ -37,6 +39,17 @@ public void onChangeState(boolean result) { LocationChecker.this.write(); } }); + this.mService.startLocationTracking(new LocationListener() { + @Override + public void onLocationChanged(Location location) { + TextView text = (TextView) LocationChecker.this.findViewById(R.id.txtLocation); + if (location == null) { + text.setText("Unknown location"); + } else { + text.setText(location.getLatitude() + " : " + location.getLongitude()); + } + } + }); // Write this.write(); diff --git a/app/src/main/res/layout/activity_location_checker.xml b/app/src/main/res/layout/activity_location_checker.xml index 13593a6..ef8d74e 100644 --- a/app/src/main/res/layout/activity_location_checker.xml +++ b/app/src/main/res/layout/activity_location_checker.xml @@ -1,69 +1,106 @@ - + android:paddingTop="@dimen/activity_vertical_margin"> + android:text="Check every 1 seconds the ability to find the current location" /> - - - + android:orientation="horizontal"> - + - + - + + + + + + + + + + + + + + + android:gravity="center_vertical|center_horizontal" + android:orientation="vertical"> - + + + + + + + diff --git a/gradle.properties b/gradle.properties index 1d3591c..7f722e5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,6 +11,7 @@ # The setting is particularly useful for tweaking memory settings. # Default value: -Xmx10248m -XX:MaxPermSize=256m # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 +org.gradle.jvmargs=-Xmx2048m # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit diff --git a/library/build.gradle b/library/build.gradle index 09957da..c4499d4 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -5,12 +5,13 @@ group='com.github.Paroca72' android { compileSdkVersion 23 - buildToolsVersion "23.0.2" + buildToolsVersion '24.0.1' defaultConfig { minSdkVersion 15 targetSdkVersion 23 - versionCode 5 - versionName '1.2.1' + versionCode 10 + versionName '1.2.5' + multiDexEnabled true } buildTypes { release { @@ -24,4 +25,5 @@ android { dependencies { compile fileTree(include: ['*.jar'], dir: 'libs') + compile 'com.google.android.gms:play-services:9.4.0' } diff --git a/library/src/main/AndroidManifest.xml b/library/src/main/AndroidManifest.xml index 38e3f25..645a994 100644 --- a/library/src/main/AndroidManifest.xml +++ b/library/src/main/AndroidManifest.xml @@ -1,6 +1,10 @@ + + + + + * v2.0.0 */ -@SuppressWarnings("unused") -public class ScLocationService extends ScChecker { +public class ScLocationService + extends ScChecker { - /** + /********************************************************************************** * Static and privates variables */ - // Location service manager - private static LocationManager mManager = null; - // The context holder - private Context mContext = null; + public final static int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000; // Define a request code to send to Google Play services + public static final int REQUEST_PERMISSION_ID = 9001; // Request permission key + + private Context mContext; // The context holder + private static LocationManager mManager; // Location service manager + private static GoogleApiClient mGoogleApiClient; // Google API client + private LocationRequest mLocationRequest; // Location request settings + private LocationListener mLocationListener; // Location listener + private boolean mStartingLocationTracking; // Trigger for hold the request to starting + // location tracking - /** + + /********************************************************************************** * Constructor */ public ScLocationService(Context context) { - // Save the context reference + // Define this.mContext = context; + this.mLocationRequest = new LocationRequest(); + this.mStartingLocationTracking = false; + + // Request the permission + this.requestPermissions(); + // Initialize the google API client + this.initializeGoogleAPIClient(); + } + + + /********************************************************************************** + * Private methods + */ + + // Request user permission + private void requestPermissions() { + // If version if minor than M we need to have an explicit permission from the user + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && + this.mContext != null && this.mContext instanceof Activity) { + // Get the activity + Activity activity = (Activity) this.mContext; + // Check the permission + if (activity.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED && + activity.checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { + // If requested show a popup to the have the user permission + String permissions[] = new String[]{ + Manifest.permission.ACCESS_COARSE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION + }; + activity.requestPermissions(permissions, ScLocationService.REQUEST_PERMISSION_ID); + } + } + } + + // Start the location tracking + public void internalStartLocationTracking() { + // Check for empty value and if the service is connected + if (this.mLocationListener != null && this.mStartingLocationTracking && + ScLocationService.mGoogleApiClient.isConnected()) + try { + // Set the trigger + this.mStartingLocationTracking = false; + + // Start the service + LocationServices.FusedLocationApi + .requestLocationUpdates( + ScLocationService.mGoogleApiClient, + this.mLocationRequest, + this.mLocationListener + ); + + } catch (SecurityException e) { + // NOP + } } + // Stop the location tracking + public void internalStopLocationTracking() { + try { + // Set the trigger + this.mStartingLocationTracking = false; + // Start the service + LocationServices.FusedLocationApi + .removeLocationUpdates( + ScLocationService.mGoogleApiClient, + this.mLocationListener + ); - /** + } catch (SecurityException e) { + // NOP + } + } + + // Try to initialize the google API client + private void initializeGoogleAPIClient() { + // Initialize the google API client is needed + if (ScLocationService.mGoogleApiClient == null && this.mContext != null) { + ScLocationService.mGoogleApiClient = new GoogleApiClient.Builder(this.mContext) + .addApi(LocationServices.API) + .addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() { + @Override + public void onConnected(@Nullable Bundle bundle) { + // if have a request to start tracking try to activate the service + ScLocationService.this.internalStartLocationTracking(); + } + + @Override + public void onConnectionSuspended(int i) { + // Do nothing + } + }) + .build(); + } + } + + + /********************************************************************************** * Public methods */ @@ -70,11 +183,118 @@ public LocationManager getLocationManager() { return ScLocationService.mManager; } + + /********************************************************************************** + * Location tracking + */ + + // Check if the location tracker is enabled + @SuppressWarnings("unused") + public boolean isLocationTrackerEnabled() { + // Check for empty value + if (ScLocationService.mGoogleApiClient != null) { + return ScLocationService.mGoogleApiClient.isConnected(); + } + // Return false + return false; + } + + /* + * Check is the google API is available. + * The google API needed for the focused location tracker. + */ + @SuppressWarnings("unused") + public boolean isGoogleAPIAvailable() { + // Check for empty values + if (this.mContext == null) return false; + + // Get the google API checker + GoogleApiAvailability googleAPI = GoogleApiAvailability.getInstance(); + // Request if the play service is available and hold the result + int result = googleAPI.isGooglePlayServicesAvailable(this.mContext); + // If success + if (result == ConnectionResult.SUCCESS) { + // Continue + return true; + } + // If not available + else { + // Check if possible to have a resolution + if (googleAPI.isUserResolvableError(result) && this.mContext instanceof Activity) { + // Open the error dialog + googleAPI.getErrorDialog( + (Activity) this.mContext, + result, + ScLocationService.CONNECTION_FAILURE_RESOLUTION_REQUEST + ).show(); + } + // Return + return false; + } + } + + // Start the location tracking + @SuppressWarnings("unused") + public void startLocationTracking(LocationListener listener) { + // Hold the listener and set the trigger + this.mLocationListener = listener; + this.mStartingLocationTracking = true; + + // Check for the connection + if (!ScLocationService.mGoogleApiClient.isConnected()) { + // Try to connect and the tracker will attached once the connection will done + ScLocationService.mGoogleApiClient.connect(); + } + // Else attach the location tracker directly + else { + this.internalStartLocationTracking(); + } + } + + // Stop the location tracking + @SuppressWarnings("unused") + public void stopLocationTracking() { + // Stop the tracking + this.internalStopLocationTracking(); + // Stop the service + ScLocationService.mGoogleApiClient.disconnect(); + } + + // Get the last known location + @SuppressWarnings("unused") + public Location getLocation() { + try { + // Check for connection + if (ScLocationService.mGoogleApiClient.isConnected()) { + // Try to get the last location + return LocationServices.FusedLocationApi + .getLastLocation(ScLocationService.mGoogleApiClient); + } + + } catch (SecurityException e) { + // NOP + } + // In error case return null + return null; + } + + // Get the location request object + @SuppressWarnings("unused") + public LocationRequest getLocationRequest() { + return this.mLocationRequest; + } + + + /********************************************************************************** + * Override + */ + // Override the check function. // As this class extend the ScChecker this methods can be auto-checked periodically. @Override @SuppressWarnings("unused") public boolean check() { + // Return the current status return this.isGPSEnabled() || this.isNetworkEnabled(); }