diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 0345846..b4d963a 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -22,6 +22,6 @@ jobs: - name: Build with Gradle run: ./gradlew build jacocoTestReport assembleAndroidTest - name: Codecov - uses: codecov/codecov-action@v1.0.7 + uses: codecov/codecov-action@v3.1.4 diff --git a/.travis.yml b/.travis.yml index a1bbc03..293b929 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,8 +12,8 @@ android: components: - tools - platform-tools - - build-tools-29.0.0 - - android-29 + - build-tools-33.0.2 + - android-33 - extra-google-google_play_services - extra-google-m2repository @@ -23,7 +23,7 @@ android: - 'android-sdk-license-.+' before_install: - - yes | sdkmanager "platforms;android-29" + - yes | sdkmanager "platforms;android-33" script: - ./gradlew clean check --stacktrace --no-daemon diff --git a/app/build.gradle b/app/build.gradle index 40f8379..0b8e537 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,6 +1,8 @@ apply plugin: 'com.android.application' android { + namespace 'com.yayandroid.locationmanager.sample' + compileSdkVersion versions.compileSdkVersion buildToolsVersion versions.buildToolsVersion diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d7c8a1c..7f1a35e 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -18,7 +18,8 @@ android:theme="@style/AppTheme" tools:ignore="GoogleAppIndexingWarning" > - + diff --git a/build.gradle b/build.gradle index bc9b12e..3cab3eb 100644 --- a/build.gradle +++ b/build.gradle @@ -3,45 +3,44 @@ buildscript { repositories { google() - jcenter() + mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:3.5.3' - classpath 'com.dicedmelon.gradle:jacoco-android:0.1.4' + classpath 'com.android.tools.build:gradle:8.1.1' + classpath 'org.jacoco:org.jacoco.core:0.8.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } } -task clean(type: Delete) { +tasks.register('clean', Delete) { delete rootProject.buildDir } - allprojects { repositories { google() - jcenter() + mavenCentral() } project.ext { versions = [ minSdkVersion : 14, - compileSdkVersion: 29, - targetSdkVersion : 29, - buildToolsVersion: '29.0.0' + compileSdkVersion: 33, + targetSdkVersion : 33, + buildToolsVersion: '33.0.2' ] libraries = [ - appCompat : 'androidx.appcompat:appcompat:1.1.0', - googlePlayServices: 'com.google.android.gms:play-services-location:17.0.0', + appCompat : 'androidx.appcompat:appcompat:1.6.1', + googlePlayServices: 'com.google.android.gms:play-services-location:21.0.1', junit : 'junit:junit:4.12', assertJ : 'com.squareup.assertj:assertj-android:1.1.1', - mockito : 'org.mockito:mockito-core:2.7.2', + mockito : 'org.mockito:mockito-core:4.2.0', - leakcanary : 'com.squareup.leakcanary:leakcanary-android:2.4' + leakcanary : 'com.squareup.leakcanary:leakcanary-android:2.12' ] } } \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e4b3b1d..3a02907 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,5 @@ -#Sat Feb 01 14:17:05 CET 2020 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip diff --git a/library/build.gradle b/library/build.gradle index 402f583..b4fe676 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -1,7 +1,9 @@ apply plugin: 'com.android.library' -apply plugin: 'jacoco-android' +apply plugin: 'jacoco' android { + namespace 'com.yayandroid.locationmanager' + compileSdkVersion versions.compileSdkVersion buildToolsVersion versions.buildToolsVersion diff --git a/library/gradle.properties b/library/gradle.properties index a9c2e68..f407197 100644 --- a/library/gradle.properties +++ b/library/gradle.properties @@ -20,8 +20,8 @@ POM_NAME=LocationManager Library POM_ARTIFACT_ID=LocationManager POM_PACKAGING=aar -VERSION_NAME=2.4.1 -VERSION_CODE=29 +VERSION_NAME=2.5.0 +VERSION_CODE=30 GROUP=com.yayandroid POM_DESCRIPTION=LocationManager Library diff --git a/library/maven_push.gradle b/library/maven_push.gradle index 2f96fe1..c64fa40 100644 --- a/library/maven_push.gradle +++ b/library/maven_push.gradle @@ -14,7 +14,7 @@ * limitations under the License. */ -apply plugin: 'maven' +apply plugin: 'maven-publish' apply plugin: 'signing' def isReleaseBuild() { @@ -39,74 +39,73 @@ def getRepositoryPassword() { return hasProperty('NEXUS_PASSWORD') ? NEXUS_PASSWORD : "" } -afterEvaluate { project -> - uploadArchives { - repositories { - mavenDeployer { - beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } +publishing { + publications { + maven(MavenPublication) { - pom.groupId = GROUP - pom.artifactId = POM_ARTIFACT_ID - pom.version = VERSION_NAME + groupId = GROUP + artifactId = POM_ARTIFACT_ID + version = VERSION_NAME - repository(url: getReleaseRepositoryUrl()) { - authentication(userName: getRepositoryUsername(), password: getRepositoryPassword()) - } - snapshotRepository(url: getSnapshotRepositoryUrl()) { - authentication(userName: getRepositoryUsername(), password: getRepositoryPassword()) - } + pom { + name.set(POM_NAME) + packaging POM_PACKAGING + description POM_DESCRIPTION + url.set(POM_URL) - pom.project { - name POM_NAME - packaging POM_PACKAGING - description POM_DESCRIPTION - url POM_URL - - scm { - url POM_SCM_URL - connection POM_SCM_CONNECTION - developerConnection POM_SCM_DEV_CONNECTION - } + scm { + url.set(POM_SCM_URL) + connection.set(POM_SCM_CONNECTION) + developerConnection.set(POM_SCM_DEV_CONNECTION) + } - licenses { - license { - name POM_LICENCE_NAME - url POM_LICENCE_URL - distribution POM_LICENCE_DIST - } + licenses { + license { + name.set(POM_LICENCE_NAME) + url.set(POM_LICENCE_URL) + distribution.set(POM_LICENCE_DIST) } + } - developers { - developer { - id POM_DEVELOPER_ID - name POM_DEVELOPER_NAME - } + developers { + developer { + id.set(POM_DEVELOPER_ID) + name.set(POM_DEVELOPER_NAME) } } } } } - - signing { - required { isReleaseBuild() && gradle.taskGraph.hasTask("uploadArchives") } - sign configurations.archives + repositories { + maven { + url = version.endsWith("SNAPSHOT") ? getSnapshotRepositoryUrl() : getReleaseRepositoryUrl() + credentials { + username getRepositoryUsername() + password getRepositoryPassword() + } + } } +} - //task androidJavadocs(type: Javadoc) { - //source = android.sourceSets.main.allJava - //} +signing { + required { isReleaseBuild() && gradle.taskGraph.hasTask("uploadArchives") } + sign configurations.archives +} - //task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) { - //classifier = 'javadoc' - //from androidJavadocs.destinationDir - //} +//task androidJavadocs(type: Javadoc) { +//source = android.sourceSets.main.allJava +//} - task androidSourcesJar(type: Jar) { - classifier = 'sources' - from android.sourceSets.main.java.sourceFiles - } +//task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) { +//classifier = 'javadoc' +//from androidJavadocs.destinationDir +//} - artifacts { - archives androidSourcesJar - } +tasks.register('androidSourcesJar', Jar) { + archiveClassifier.set("sources") + from android.sourceSets.main.java.sourceFiles +} + +artifacts { + archives androidSourcesJar } \ No newline at end of file diff --git a/library/src/main/AndroidManifest.xml b/library/src/main/AndroidManifest.xml index c4ce8bb..cc9c995 100644 --- a/library/src/main/AndroidManifest.xml +++ b/library/src/main/AndroidManifest.xml @@ -1,2 +1,5 @@ - \ No newline at end of file + + + \ No newline at end of file diff --git a/library/src/main/java/com/yayandroid/locationmanager/LocationManager.java b/library/src/main/java/com/yayandroid/locationmanager/LocationManager.java index b6f48cf..dcfcc40 100644 --- a/library/src/main/java/com/yayandroid/locationmanager/LocationManager.java +++ b/library/src/main/java/com/yayandroid/locationmanager/LocationManager.java @@ -22,15 +22,15 @@ public class LocationManager implements PermissionListener { - private LocationListener listener; - private LocationConfiguration configuration; - private LocationProvider activeProvider; - private PermissionProvider permissionProvider; + private final LocationListener listener; + private final LocationConfiguration configuration; + private final LocationProvider activeProvider; + private final PermissionProvider permissionProvider; /** * Library tries to log as much as possible in order to make it transparent to see what is actually going on * under the hood. You can enable it for debug purposes, but do not forget to disable on production. - * + *

* Log is disabled as default. */ public static void enableLog(boolean enable) { @@ -60,7 +60,7 @@ private LocationManager(Builder builder) { public static class Builder { - private ContextProcessor contextProcessor; + private final ContextProcessor contextProcessor; private LocationListener listener; private LocationConfiguration configuration; private LocationProvider activeProvider; @@ -159,7 +159,7 @@ public LocationConfiguration getConfiguration() { /** * Google suggests to stop location updates when the activity is no longer in focus - * http://developer.android.com/training/location/receive-location-updates.html#stop-updates + * ... */ public void onPause() { activeProvider.onPause(); @@ -240,7 +240,7 @@ void askForPermission() { LogUtils.logI("Waiting until we receive any callback from PermissionProvider..."); } else { LogUtils.logI("Couldn't get permission, Abort!"); - failed(FailType.PERMISSION_DENIED); + failed(); } } } @@ -255,9 +255,9 @@ private void permissionGranted(boolean alreadyHadPermission) { activeProvider.get(); } - private void failed(@FailType int type) { + private void failed() { if (listener != null) { - listener.onLocationFailed(type); + listener.onLocationFailed(FailType.PERMISSION_DENIED); } } @@ -268,6 +268,6 @@ public void onPermissionsGranted() { @Override public void onPermissionsDenied() { - failed(FailType.PERMISSION_DENIED); + failed(); } } \ No newline at end of file diff --git a/library/src/main/java/com/yayandroid/locationmanager/base/LocationBaseFragment.java b/library/src/main/java/com/yayandroid/locationmanager/base/LocationBaseFragment.java index d6d59d5..a5309e4 100644 --- a/library/src/main/java/com/yayandroid/locationmanager/base/LocationBaseFragment.java +++ b/library/src/main/java/com/yayandroid/locationmanager/base/LocationBaseFragment.java @@ -1,5 +1,6 @@ package com.yayandroid.locationmanager.base; +import android.content.Context; import android.content.Intent; import android.os.Bundle; @@ -35,11 +36,14 @@ protected void getLocation() { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - locationManager = new LocationManager.Builder(getContext().getApplicationContext()) - .configuration(getLocationConfiguration()) - .fragment(this) - .notify(this) - .build(); + Context context = getContext(); + if (context != null) { + locationManager = new LocationManager.Builder(context.getApplicationContext()) + .configuration(getLocationConfiguration()) + .fragment(this) + .notify(this) + .build(); + } } @CallSuper diff --git a/library/src/main/java/com/yayandroid/locationmanager/configuration/Configurations.java b/library/src/main/java/com/yayandroid/locationmanager/configuration/Configurations.java index c41af07..78cd2b1 100644 --- a/library/src/main/java/com/yayandroid/locationmanager/configuration/Configurations.java +++ b/library/src/main/java/com/yayandroid/locationmanager/configuration/Configurations.java @@ -25,7 +25,7 @@ public static LocationConfiguration silentConfiguration() { * Returns a LocationConfiguration that will never ask user anything and will try to use whatever possible options * that application has to obtain location. If there is no sufficient permission, provider, etc... then * LocationManager will call {@linkplain LocationListener#onLocationFailed(int)} silently - * + *

* # Best use case of this configuration is within Service implementations */ public static LocationConfiguration silentConfiguration(boolean keepTracking) { diff --git a/library/src/main/java/com/yayandroid/locationmanager/configuration/DefaultProviderConfiguration.java b/library/src/main/java/com/yayandroid/locationmanager/configuration/DefaultProviderConfiguration.java index f026b8b..8133e66 100644 --- a/library/src/main/java/com/yayandroid/locationmanager/configuration/DefaultProviderConfiguration.java +++ b/library/src/main/java/com/yayandroid/locationmanager/configuration/DefaultProviderConfiguration.java @@ -156,7 +156,7 @@ public Builder gpsMessage(String gpsMessage) { * implementation of {@linkplain DialogProvider} and manager will use that implementation to display the dialog. * Important, if you set your own implementation, please make sure to handle gpsMessage as well. * Because {@linkplain DefaultProviderConfiguration.Builder#gpsMessage} will be ignored in that case. - * + *

* If you don't specify any dialogProvider implementation {@linkplain SimpleMessageDialogProvider} will be used with * given {@linkplain DefaultProviderConfiguration.Builder#gpsMessage} */ diff --git a/library/src/main/java/com/yayandroid/locationmanager/configuration/Defaults.java b/library/src/main/java/com/yayandroid/locationmanager/configuration/Defaults.java index 94c32c4..33ec7aa 100644 --- a/library/src/main/java/com/yayandroid/locationmanager/configuration/Defaults.java +++ b/library/src/main/java/com/yayandroid/locationmanager/configuration/Defaults.java @@ -9,11 +9,11 @@ public final class Defaults { private static final int SECOND = 1000; private static final int MINUTE = 60 * SECOND; - static final int WAIT_PERIOD = 20 * SECOND; - static final int TIME_PERIOD = 5 * MINUTE; + public static final long WAIT_PERIOD = 20 * SECOND; + public static final int TIME_PERIOD = 5 * MINUTE; - static final int LOCATION_DISTANCE_INTERVAL = 0; - static final int LOCATION_INTERVAL = 5 * MINUTE; + public static final int LOCATION_DISTANCE_INTERVAL = 0; + public static final int LOCATION_INTERVAL = 5 * MINUTE; static final float MIN_ACCURACY = 5.0f; diff --git a/library/src/main/java/com/yayandroid/locationmanager/configuration/GooglePlayServicesConfiguration.java b/library/src/main/java/com/yayandroid/locationmanager/configuration/GooglePlayServicesConfiguration.java index 0b7d912..9fe86f5 100644 --- a/library/src/main/java/com/yayandroid/locationmanager/configuration/GooglePlayServicesConfiguration.java +++ b/library/src/main/java/com/yayandroid/locationmanager/configuration/GooglePlayServicesConfiguration.java @@ -101,7 +101,7 @@ public Builder fallbackToDefault(boolean fallbackToDefault) { * Set true to ask user handle when there is some resolvable error * on connection GooglePlayServices, if you don't want to bother user * to configure Google Play Services to receive location then set this as false. - * + *

* Default is False. */ public Builder askForGooglePlayServices(boolean askForGooglePlayServices) { @@ -115,7 +115,7 @@ public Builder askForGooglePlayServices(boolean askForGooglePlayServices) { * Then if this flag is on it will ask user to turn them on, again, via GooglePlayServices * by displaying a system dialog if not it will directly try to receive location * -which probably not going to return any values. - * + *

* Default is True. */ public Builder askForSettingsApi(boolean askForSettingsApi) { @@ -128,7 +128,7 @@ public Builder askForSettingsApi(boolean askForSettingsApi) { * to switch necessary providers on, or when there is an error displaying the dialog. * If the flag is on, then manager will setDialogListener listener as location failed, * otherwise it will try to get location anyway -which probably not gonna happen. - * + *

* Default is False. -Because after GooglePlayServices Provider it might switch * to default providers, if we fail here then those provider will never trigger. */ @@ -140,10 +140,10 @@ public Builder failOnSettingsApiSuspended(boolean failOnSettingsApiSuspended) { /** * GooglePlayServices Api returns the best most recent location currently available. It is highly recommended to * use this functionality unless your requirements are really specific and precise. - * + *

* Default is False. So GooglePlayServices Api will return immediately if there is location already. - * - * https://developers.google.com/android/reference/com/google/android/gms/location/FusedLocationProviderApi.html + *

+ * ... * #getLastLocation(com.google.android.gms.common.api.GoogleApiClient) */ public Builder ignoreLastKnowLocation(boolean ignore) { @@ -153,7 +153,7 @@ public Builder ignoreLastKnowLocation(boolean ignore) { /** * Indicates waiting time period for GooglePlayServices before switching to next possible provider. - * + *

* Default values are {@linkplain Defaults#WAIT_PERIOD} */ public Builder setWaitPeriod(long milliseconds) { diff --git a/library/src/main/java/com/yayandroid/locationmanager/configuration/PermissionConfiguration.java b/library/src/main/java/com/yayandroid/locationmanager/configuration/PermissionConfiguration.java index fd10207..de1da97 100644 --- a/library/src/main/java/com/yayandroid/locationmanager/configuration/PermissionConfiguration.java +++ b/library/src/main/java/com/yayandroid/locationmanager/configuration/PermissionConfiguration.java @@ -28,7 +28,7 @@ public static class Builder { /** * Indicates what to display when user needs to see a rational dialog for RuntimePermission. * There is no default value, so if you do not set this, user will not see any rationale dialog. - * + *

* And if you set {@linkplain PermissionConfiguration.Builder#rationaleDialogProvider(DialogProvider)} then this * field will be ignored. Please make sure you handled in your custom dialogProvider implementation. */ @@ -56,7 +56,7 @@ public Builder requiredPermissions(String[] permissions) { * implementation of {@linkplain DialogProvider} and manager will use that implementation to display the dialog. * Important, if you set your own implementation, please make sure to handle rationaleMessage as well. * Because {@linkplain PermissionConfiguration.Builder#rationaleMessage} will be ignored in that case. - * + *

* If you don't specify any dialogProvider implementation {@linkplain SimpleMessageDialogProvider} will be used with * given {@linkplain PermissionConfiguration.Builder#rationaleMessage} */ @@ -70,7 +70,7 @@ public Builder rationaleDialogProvider(DialogProvider dialogProvider) { * {@linkplain PermissionProvider} and manager will use that implementation to ask required permissions. * Important, if you set your own implementation, please make sure to handle dialogProvider as well. * Because {@linkplain PermissionConfiguration.Builder#rationaleDialogProvider} will be ignored in that case. - * + *

* If you don't specify any permissionProvider implementation {@linkplain DefaultPermissionProvider} will be used * with given {@linkplain PermissionConfiguration.Builder#rationaleDialogProvider} */ diff --git a/library/src/main/java/com/yayandroid/locationmanager/providers/dialogprovider/DialogProvider.java b/library/src/main/java/com/yayandroid/locationmanager/providers/dialogprovider/DialogProvider.java index e99f1c9..7ca8498 100644 --- a/library/src/main/java/com/yayandroid/locationmanager/providers/dialogprovider/DialogProvider.java +++ b/library/src/main/java/com/yayandroid/locationmanager/providers/dialogprovider/DialogProvider.java @@ -25,7 +25,7 @@ public abstract class DialogProvider { /** * Sets a {@linkplain DialogListener} to provide pre-defined actions to the component which uses this dialog - * + *

* This method will be called by {@linkplain DefaultPermissionProvider} internally, if it is in use. * * @param dialogListener will be used to notify on specific actions diff --git a/library/src/main/java/com/yayandroid/locationmanager/providers/dialogprovider/SimpleMessageDialogProvider.java b/library/src/main/java/com/yayandroid/locationmanager/providers/dialogprovider/SimpleMessageDialogProvider.java index ba6f7f3..747a351 100644 --- a/library/src/main/java/com/yayandroid/locationmanager/providers/dialogprovider/SimpleMessageDialogProvider.java +++ b/library/src/main/java/com/yayandroid/locationmanager/providers/dialogprovider/SimpleMessageDialogProvider.java @@ -9,7 +9,7 @@ public class SimpleMessageDialogProvider extends DialogProvider implements DialogInterface.OnClickListener { - private String message; + private final String message; public SimpleMessageDialogProvider(String message) { this.message = message; diff --git a/library/src/main/java/com/yayandroid/locationmanager/providers/locationprovider/DefaultLocationProvider.java b/library/src/main/java/com/yayandroid/locationmanager/providers/locationprovider/DefaultLocationProvider.java index 6c03a0b..29dce4c 100644 --- a/library/src/main/java/com/yayandroid/locationmanager/providers/locationprovider/DefaultLocationProvider.java +++ b/library/src/main/java/com/yayandroid/locationmanager/providers/locationprovider/DefaultLocationProvider.java @@ -1,6 +1,8 @@ package com.yayandroid.locationmanager.providers.locationprovider; +import android.app.Activity; import android.app.Dialog; +import android.content.Context; import android.content.Intent; import android.location.Location; import android.location.LocationListener; @@ -10,6 +12,8 @@ import androidx.annotation.NonNull; +import com.yayandroid.locationmanager.configuration.DefaultProviderConfiguration; +import com.yayandroid.locationmanager.configuration.Defaults; import com.yayandroid.locationmanager.constants.FailType; import com.yayandroid.locationmanager.constants.ProcessType; import com.yayandroid.locationmanager.constants.RequestCode; @@ -98,7 +102,9 @@ public void get() { askForLocation(LocationManager.GPS_PROVIDER); } else { // GPS is not enabled, - if (getConfiguration().defaultProviderConfiguration().askForEnableGPS() && getActivity() != null) { + DefaultProviderConfiguration configuration = getConfiguration().defaultProviderConfiguration(); + + if (configuration != null && configuration.askForEnableGPS() && getActivity() != null) { LogUtils.logI("GPS is not enabled, asking user to enable it..."); askForEnableGPS(); } else { @@ -109,11 +115,18 @@ public void get() { } void askForEnableGPS() { - DialogProvider gpsDialogProvider = getConfiguration().defaultProviderConfiguration().gpsDialogProvider(); - gpsDialogProvider.setDialogListener(this); + DefaultProviderConfiguration configuration = getConfiguration().defaultProviderConfiguration(); + + if (configuration != null) { + DialogProvider gpsDialogProvider = configuration.gpsDialogProvider(); + Activity activity = getActivity(); + if (gpsDialogProvider != null && activity != null) { + gpsDialogProvider.setDialogListener(this); - gpsDialog = gpsDialogProvider.getDialog(getActivity()); - gpsDialog.show(); + gpsDialog = gpsDialogProvider.getDialog(activity); + gpsDialog.show(); + } + } } void onGPSActivated() { @@ -154,9 +167,11 @@ void askForLocation(String provider) { boolean checkForLastKnowLocation() { Location lastKnownLocation = getSourceProvider().getLastKnownLocation(provider); - if (getSourceProvider().isLocationSufficient(lastKnownLocation, - getConfiguration().defaultProviderConfiguration().acceptableTimePeriod(), - getConfiguration().defaultProviderConfiguration().acceptableAccuracy())) { + DefaultProviderConfiguration configuration = getConfiguration().defaultProviderConfiguration(); + + if (configuration != null && getSourceProvider().isLocationSufficient(lastKnownLocation, + configuration.acceptableTimePeriod(), + configuration.acceptableAccuracy())) { LogUtils.logI("LastKnowLocation is usable."); onLocationReceived(lastKnownLocation); return true; @@ -180,15 +195,26 @@ void notifyProcessChange() { } void requestUpdateLocation() { - long timeInterval = getConfiguration().defaultProviderConfiguration().requiredTimeInterval(); - long distanceInterval = getConfiguration().defaultProviderConfiguration().requiredDistanceInterval(); + DefaultProviderConfiguration configuration = getConfiguration().defaultProviderConfiguration(); + long timeInterval = Defaults.TIME_PERIOD; + long distanceInterval = Defaults.LOCATION_DISTANCE_INTERVAL; + if (configuration != null) { + configuration.requiredTimeInterval(); + configuration.requiredDistanceInterval(); + } getSourceProvider().getUpdateRequest().run(provider, timeInterval, distanceInterval); } long getWaitPeriod() { - return LocationManager.GPS_PROVIDER.equals(provider) - ? getConfiguration().defaultProviderConfiguration().gpsWaitPeriod() - : getConfiguration().defaultProviderConfiguration().networkWaitPeriod(); + DefaultProviderConfiguration configuration = getConfiguration().defaultProviderConfiguration(); + + if (configuration != null) { + return LocationManager.GPS_PROVIDER.equals(provider) + ? configuration.gpsWaitPeriod() + : configuration.networkWaitPeriod(); + } else { + return Defaults.WAIT_PERIOD; + } } private boolean isNetworkProviderEnabled() { @@ -214,7 +240,7 @@ void onLocationFailed(@FailType int type) { } @Override - public void onLocationChanged(Location location) { + public void onLocationChanged(@NonNull Location location) { if (getSourceProvider().updateRequestIsRemoved()) { return; } @@ -247,14 +273,14 @@ public void onStatusChanged(String provider, int status, Bundle extras) { } @Override - public void onProviderEnabled(String provider) { + public void onProviderEnabled(@NonNull String provider) { if (getListener() != null) { getListener().onProviderEnabled(provider); } } @Override - public void onProviderDisabled(String provider) { + public void onProviderDisabled(@NonNull String provider) { if (getListener() != null) { getListener().onProviderDisabled(provider); } @@ -277,8 +303,8 @@ public void runScheduledTask(@NonNull String taskId) { @Override public void onPositiveButtonClick() { - boolean activityStarted = startActivityForResult(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS), - RequestCode.GPS_ENABLE); + boolean activityStarted = startActivityForResult(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS) + ); if (!activityStarted) { onLocationFailed(FailType.VIEW_NOT_REQUIRED_TYPE); } @@ -296,8 +322,9 @@ void setDefaultLocationSource(DefaultLocationSource defaultLocationSource) { } private DefaultLocationSource getSourceProvider() { - if (defaultLocationSource == null) { - defaultLocationSource = new DefaultLocationSource(getContext(), this, this); + Context context = getContext(); + if (defaultLocationSource == null && context != null) { + defaultLocationSource = new DefaultLocationSource(context, this, this); } return defaultLocationSource; } diff --git a/library/src/main/java/com/yayandroid/locationmanager/providers/locationprovider/DefaultLocationSource.java b/library/src/main/java/com/yayandroid/locationmanager/providers/locationprovider/DefaultLocationSource.java index 0883b61..4af1546 100644 --- a/library/src/main/java/com/yayandroid/locationmanager/providers/locationprovider/DefaultLocationSource.java +++ b/library/src/main/java/com/yayandroid/locationmanager/providers/locationprovider/DefaultLocationSource.java @@ -15,7 +15,7 @@ class DefaultLocationSource { static final String PROVIDER_SWITCH_TASK = "providerSwitchTask"; - private LocationManager locationManager; + private final LocationManager locationManager; private UpdateRequest updateRequest; private ContinuousTask cancelTask; diff --git a/library/src/main/java/com/yayandroid/locationmanager/providers/locationprovider/DispatcherLocationProvider.java b/library/src/main/java/com/yayandroid/locationmanager/providers/locationprovider/DispatcherLocationProvider.java index cb3c8cc..127f957 100644 --- a/library/src/main/java/com/yayandroid/locationmanager/providers/locationprovider/DispatcherLocationProvider.java +++ b/library/src/main/java/com/yayandroid/locationmanager/providers/locationprovider/DispatcherLocationProvider.java @@ -7,6 +7,7 @@ import androidx.annotation.NonNull; import com.google.android.gms.common.ConnectionResult; +import com.yayandroid.locationmanager.configuration.GooglePlayServicesConfiguration; import com.yayandroid.locationmanager.constants.FailType; import com.yayandroid.locationmanager.constants.RequestCode; import com.yayandroid.locationmanager.helper.LogUtils; @@ -141,7 +142,9 @@ void checkGooglePlayServicesAvailability(boolean askForGooglePlayServices) { } void askForGooglePlayServices(int gpServicesAvailability) { - if (getConfiguration().googlePlayServicesConfiguration().askForGooglePlayServices() && + GooglePlayServicesConfiguration configuration = getConfiguration().googlePlayServicesConfiguration(); + + if (configuration != null && configuration.askForGooglePlayServices() && getSourceProvider().isGoogleApiErrorUserResolvable(gpServicesAvailability)) { resolveGooglePlayServices(gpServicesAvailability); @@ -159,7 +162,7 @@ void askForGooglePlayServices(int gpServicesAvailability) { * The {@link com.google.android.gms.common.GoogleApiAvailability#isGooglePlayServicesAvailable(android.content.Context)} returns one of following in {@link ConnectionResult}: * SUCCESS, SERVICE_MISSING, SERVICE_UPDATING, SERVICE_VERSION_UPDATE_REQUIRED, SERVICE_DISABLED, SERVICE_INVALID. *

- * See https://developers.google.com/android/reference/com/google/android/gms/common/GoogleApiAvailability#public-int-isgoogleplayservicesavailable-context-context + * See ... */ void resolveGooglePlayServices(int gpServicesAvailability) { LogUtils.logI("Asking user to handle GooglePlayServices error..."); @@ -207,8 +210,12 @@ public void onDismiss(DialogInterface dialog) { void getLocationFromGooglePlayServices() { LogUtils.logI("Attempting to get location from Google Play Services providers..."); setLocationProvider(getSourceProvider().createGooglePlayServicesLocationProvider(this)); - getSourceProvider().gpServicesSwitchTask().delayed(getConfiguration() - .googlePlayServicesConfiguration().googlePlayServicesWaitPeriod()); + + GooglePlayServicesConfiguration configuration = getConfiguration().googlePlayServicesConfiguration(); + + if (configuration != null) { + getSourceProvider().gpServicesSwitchTask().delayed(configuration.googlePlayServicesWaitPeriod()); + } activeProvider.get(); } diff --git a/library/src/main/java/com/yayandroid/locationmanager/providers/locationprovider/DispatcherLocationSource.java b/library/src/main/java/com/yayandroid/locationmanager/providers/locationprovider/DispatcherLocationSource.java index c8be583..5fc3bc5 100644 --- a/library/src/main/java/com/yayandroid/locationmanager/providers/locationprovider/DispatcherLocationSource.java +++ b/library/src/main/java/com/yayandroid/locationmanager/providers/locationprovider/DispatcherLocationSource.java @@ -16,7 +16,7 @@ class DispatcherLocationSource { static final String GOOGLE_PLAY_SERVICE_SWITCH_TASK = "googlePlayServiceSwitchTask"; - private ContinuousTask gpServicesSwitchTask; + private final ContinuousTask gpServicesSwitchTask; DispatcherLocationSource(ContinuousTaskRunner continuousTaskRunner) { this.gpServicesSwitchTask = new ContinuousTask(GOOGLE_PLAY_SERVICE_SWITCH_TASK, continuousTaskRunner); diff --git a/library/src/main/java/com/yayandroid/locationmanager/providers/locationprovider/GooglePlayServicesLocationProvider.java b/library/src/main/java/com/yayandroid/locationmanager/providers/locationprovider/GooglePlayServicesLocationProvider.java index 65510ca..e55d060 100644 --- a/library/src/main/java/com/yayandroid/locationmanager/providers/locationprovider/GooglePlayServicesLocationProvider.java +++ b/library/src/main/java/com/yayandroid/locationmanager/providers/locationprovider/GooglePlayServicesLocationProvider.java @@ -15,6 +15,7 @@ import com.google.android.gms.location.LocationSettingsResponse; import com.google.android.gms.location.LocationSettingsStatusCodes; import com.google.android.gms.tasks.Task; +import com.yayandroid.locationmanager.configuration.GooglePlayServicesConfiguration; import com.yayandroid.locationmanager.constants.FailType; import com.yayandroid.locationmanager.constants.ProcessType; import com.yayandroid.locationmanager.constants.RequestCode; @@ -71,7 +72,9 @@ public void get() { if (getContext() != null) { LogUtils.logI("Start request location updates."); - if (getConfiguration().googlePlayServicesConfiguration().ignoreLastKnowLocation()) { + GooglePlayServicesConfiguration configuration = getConfiguration().googlePlayServicesConfiguration(); + + if (configuration != null && configuration.ignoreLastKnowLocation()) { LogUtils.logI("Configuration requires to ignore last know location from GooglePlayServices Api."); // Request fresh location @@ -198,7 +201,7 @@ void resolveSettingsApi(@NonNull ResolvableApiException resolvable) { /** * Task result can be null in certain conditions - * See: https://developers.google.com/android/reference/com/google/android/gms/location/FusedLocationProviderClient#getLastLocation() + * See: ... */ @Override public void onLastKnowLocationTaskReceived(@NonNull Task task) { @@ -220,7 +223,10 @@ public void onLastKnowLocationTaskReceived(@NonNull Task task) { void locationRequired() { LogUtils.logI("Ask for location update..."); - if (getConfiguration().googlePlayServicesConfiguration().askForSettingsApi()) { + + GooglePlayServicesConfiguration configuration = getConfiguration().googlePlayServicesConfiguration(); + + if (configuration != null && configuration.askForSettingsApi()) { LogUtils.logI("Asking for SettingsApi..."); getSourceProvider().checkLocationSettings(); } else { @@ -239,7 +245,10 @@ void requestLocationUpdate() { } void settingsApiFail(@FailType int failType) { - if (getConfiguration().googlePlayServicesConfiguration().failOnSettingsApiSuspended()) { + + GooglePlayServicesConfiguration configuration = getConfiguration().googlePlayServicesConfiguration(); + + if (configuration != null && configuration.failOnSettingsApiSuspended()) { failed(failType); } else { LogUtils.logE("Even though settingsApi failed, configuration requires moving on. " @@ -250,7 +259,9 @@ void settingsApiFail(@FailType int failType) { } void failed(@FailType int type) { - if (getConfiguration().googlePlayServicesConfiguration().fallbackToDefault() && fallbackListener.get() != null) { + GooglePlayServicesConfiguration configuration = getConfiguration().googlePlayServicesConfiguration(); + + if (configuration != null && configuration.fallbackToDefault() && fallbackListener.get() != null) { fallbackListener.get().onFallback(); } else { if (getListener() != null) { @@ -266,9 +277,11 @@ void setDispatcherLocationSource(GooglePlayServicesLocationSource googlePlayServ } private GooglePlayServicesLocationSource getSourceProvider() { - if (googlePlayServicesLocationSource == null) { + GooglePlayServicesConfiguration configuration = getConfiguration().googlePlayServicesConfiguration(); + + if (configuration != null && googlePlayServicesLocationSource == null) { googlePlayServicesLocationSource = new GooglePlayServicesLocationSource(getContext(), - getConfiguration().googlePlayServicesConfiguration().locationRequest(), this); + configuration.locationRequest(), this); } return googlePlayServicesLocationSource; } diff --git a/library/src/main/java/com/yayandroid/locationmanager/providers/locationprovider/GooglePlayServicesLocationSource.java b/library/src/main/java/com/yayandroid/locationmanager/providers/locationprovider/GooglePlayServicesLocationSource.java index ff4c819..37b67f4 100644 --- a/library/src/main/java/com/yayandroid/locationmanager/providers/locationprovider/GooglePlayServicesLocationSource.java +++ b/library/src/main/java/com/yayandroid/locationmanager/providers/locationprovider/GooglePlayServicesLocationSource.java @@ -25,6 +25,7 @@ class GooglePlayServicesLocationSource extends LocationCallback { + private final Context context; private final FusedLocationProviderClient fusedLocationProviderClient; private final LocationRequest locationRequest; private final SourceListener sourceListener; @@ -40,13 +41,14 @@ interface SourceListener extends OnSuccessListener, On } GooglePlayServicesLocationSource(Context context, LocationRequest locationRequest, SourceListener sourceListener) { + this.context = context; this.sourceListener = sourceListener; this.locationRequest = locationRequest; this.fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(context); } void checkLocationSettings() { - LocationServices.getSettingsClient(fusedLocationProviderClient.getApplicationContext()) + LocationServices.getSettingsClient(context.getApplicationContext()) .checkLocationSettings( new LocationSettingsRequest.Builder() .addLocationRequest(locationRequest) diff --git a/library/src/main/java/com/yayandroid/locationmanager/providers/locationprovider/LocationProvider.java b/library/src/main/java/com/yayandroid/locationmanager/providers/locationprovider/LocationProvider.java index 20747ca..f110b98 100644 --- a/library/src/main/java/com/yayandroid/locationmanager/providers/locationprovider/LocationProvider.java +++ b/library/src/main/java/com/yayandroid/locationmanager/providers/locationprovider/LocationProvider.java @@ -128,11 +128,11 @@ protected Fragment getFragment() { return contextProcessor.getFragment(); } - protected boolean startActivityForResult(Intent intent, int requestCode) { + protected boolean startActivityForResult(Intent intent) { if (getFragment() != null) { - getFragment().startActivityForResult(intent, requestCode); + getFragment().startActivityForResult(intent, com.yayandroid.locationmanager.constants.RequestCode.GPS_ENABLE); } else if (getActivity() != null) { - getActivity().startActivityForResult(intent, requestCode); + getActivity().startActivityForResult(intent, com.yayandroid.locationmanager.constants.RequestCode.GPS_ENABLE); } else { LogUtils.logE("Cannot startActivityForResult because host is neither Activity nor Fragment."); return false; diff --git a/library/src/main/java/com/yayandroid/locationmanager/providers/permissionprovider/DefaultPermissionProvider.java b/library/src/main/java/com/yayandroid/locationmanager/providers/permissionprovider/DefaultPermissionProvider.java index 0e15171..d22b4ec 100644 --- a/library/src/main/java/com/yayandroid/locationmanager/providers/permissionprovider/DefaultPermissionProvider.java +++ b/library/src/main/java/com/yayandroid/locationmanager/providers/permissionprovider/DefaultPermissionProvider.java @@ -26,7 +26,7 @@ public boolean requestPermissions() { return false; } - if (shouldShowRequestPermissionRationale()) { + if (shouldShowRequestPermissionRationale() && getDialogProvider() != null) { getDialogProvider().setDialogListener(this); getDialogProvider().getDialog(getActivity()).show(); } else { @@ -45,6 +45,7 @@ public void onRequestPermissionsResult(int requestCode, String[] permissions, @N for (int i = 0, size = permissions.length; i < size; i++) { if (grantResults[i] != PackageManager.PERMISSION_GRANTED) { isDenied = true; + break; } } diff --git a/library/src/main/java/com/yayandroid/locationmanager/providers/permissionprovider/PermissionProvider.java b/library/src/main/java/com/yayandroid/locationmanager/providers/permissionprovider/PermissionProvider.java index 35e51b5..7b9ad42 100644 --- a/library/src/main/java/com/yayandroid/locationmanager/providers/permissionprovider/PermissionProvider.java +++ b/library/src/main/java/com/yayandroid/locationmanager/providers/permissionprovider/PermissionProvider.java @@ -17,13 +17,14 @@ import com.yayandroid.locationmanager.view.ContextProcessor; import java.lang.ref.WeakReference; +import java.util.Objects; public abstract class PermissionProvider { private WeakReference weakContextProcessor; private WeakReference weakPermissionListener; private final String[] requiredPermissions; - private DialogProvider rationalDialogProvider; + private final DialogProvider rationalDialogProvider; /** * This class is responsible to get required permissions, and notify {@linkplain LocationManager}. @@ -111,7 +112,7 @@ public boolean hasPermission() { // For test purposes protected int checkSelfPermission(String permission) { - return ContextCompat.checkSelfPermission(getContext(), permission); + return ContextCompat.checkSelfPermission(Objects.requireNonNull(getContext()), permission); } } diff --git a/library/src/main/java/com/yayandroid/locationmanager/view/ContextProcessor.java b/library/src/main/java/com/yayandroid/locationmanager/view/ContextProcessor.java index e9a5e19..5ae9337 100644 --- a/library/src/main/java/com/yayandroid/locationmanager/view/ContextProcessor.java +++ b/library/src/main/java/com/yayandroid/locationmanager/view/ContextProcessor.java @@ -11,7 +11,7 @@ public class ContextProcessor { - private Context applicationContext; + private final Context applicationContext; private WeakReference weakActivity; private WeakReference weakFragment;