Skip to content

Commit 2193b32

Browse files
authored
Merge pull request #29 from Baseflow/feature/make_google_play_services_available
Changed native code structure, added more functionality
2 parents 46df933 + 9be7479 commit 2193b32

22 files changed

+758
-141
lines changed

.github/no-response.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Configuration for probot-no-response - https://github.com/probot/no-response
2+
3+
# Number of days of inactivity before an Issue is closed for lack of response
4+
daysUntilClose: 14
5+
6+
# Label requiring a response
7+
responseRequiredLabel: "status: needs more info"
8+
9+
# Comment to post when closing an Issue for lack of response. Set to `false` to disable
10+
closeComment: >
11+
This issue has been automatically closed because there has been no response
12+
to our request for more information from the original author. With only the
13+
information that is currently in the issue, we don't have enough information
14+
to take action. Please reach out if you have or find the answers we need so
15+
that we can investigate further.

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ flutter_*.png
5454
linked_*.ds
5555
unlinked.ds
5656
unlinked_spec.ds
57+
pubspec.lock
5758

5859
# Android related
5960
**/android/**/gradle-wrapper.jar
@@ -96,3 +97,6 @@ unlinked_spec.ds
9697
!**/ios/**/default.pbxuser
9798
!**/ios/**/default.perspectivev3
9899
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
100+
101+
# Ignore coverage folder.
102+
coverage/

CHANGELOG.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,21 @@
1+
## 4.0.0
2+
3+
* Changed the structure of the native code;
4+
* Updated the example app;
5+
* Added `makeGooglePlayServicesAvailable` ;
6+
* Added `getErrorString`;
7+
* Added `isUserResolvable`;
8+
* Added `showErrorNotification`;
9+
* Added extra tests for the newly added methods.
10+
11+
## 3.0.2
12+
13+
* Updated `pubspec.yaml` to newer versions of `SDK` and `flutter` and adding `flutter_lints` as a dependency;
14+
* Updated `analysis_options.yaml` for using `flutter_lints`;
15+
* Updated code according to the set lint rule(s);
16+
* Updated `compileSdkVersion` and `targetSdkVersion` in the `build.gradle`
17+
* Fixed bug were starting the example app would close on running for the first time by adding internet permission in the `AndroidManifest`
18+
119
## 3.0.1
220

321
* Added unit-tests to guard API against breaking changes.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ To use this plugin, add `google_api_availability` as a [dependency in your pubsp
1414

1515
```yaml
1616
dependencies:
17-
google_api_availability: ^3.0.1
17+
google_api_availability: ^3.0.2
1818
```
1919
2020
> **NOTE:** There's a known issue with integrating plugins that use Swift into a Flutter project created with the Objective-C template. See issue [Flutter#16049](https://github.com/flutter/flutter/issues/16049) for help on integration.

analysis_options.yaml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
1-
include: package:pedantic/analysis_options.yaml
1+
include: package:flutter_lints/flutter.yaml
22

33
analyzer:
44
exclude:
55
# Ignore generated files
66
- '**/*.g.dart'
77
- 'lib/src/generated/*.dart'
8-
# workaround for https://github.com/dart-lang/sdk/issues/42910
9-
- 'example/**'
108
linter:
119
rules:
1210
- public_member_api_docs

android/build.gradle

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,30 @@ version '1.0-SNAPSHOT'
44
buildscript {
55
repositories {
66
google()
7-
jcenter()
7+
mavenCentral()
88
}
99

1010
dependencies {
11-
classpath 'com.android.tools.build:gradle:3.6.1'
11+
classpath 'com.android.tools.build:gradle:4.1.0'
1212
}
1313
}
1414

1515
rootProject.allprojects {
1616
repositories {
1717
google()
18-
jcenter()
18+
mavenCentral()
1919
}
2020
}
2121

2222
apply plugin: 'com.android.library'
2323

2424
android {
25-
compileSdkVersion 28
25+
compileSdkVersion 31
26+
27+
compileOptions {
28+
sourceCompatibility JavaVersion.VERSION_1_8
29+
targetCompatibility JavaVersion.VERSION_1_8
30+
}
2631

2732
defaultConfig {
2833
minSdkVersion 16
@@ -34,6 +39,6 @@ android {
3439
}
3540

3641
dependencies {
37-
implementation 'com.google.android.gms:play-services-base:17.2.1'
42+
implementation 'com.google.android.gms:play-services-base:18.1.0'
3843
implementation 'androidx.annotation:annotation:1.1.0'
3944
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package com.baseflow.googleapiavailability;
2+
3+
import androidx.annotation.IntDef;
4+
5+
import com.google.android.gms.common.ConnectionResult;
6+
7+
import java.lang.annotation.Retention;
8+
import java.lang.annotation.RetentionPolicy;
9+
10+
final class GoogleApiAvailabilityConstants {
11+
static final String LOG_TAG = "google_api_availability";
12+
13+
static final int REQUEST_GOOGLE_PLAY_SERVICES = 1000;
14+
15+
//GOOGLE_PLAY_SERVICES_AVAILABILITY
16+
static final int GOOGLE_PLAY_SERVICES_AVAILABILITY_SUCCESS = 0;
17+
static final int GOOGLE_PLAY_SERVICES_AVAILABILITY_SERVICE_MISSING = 1;
18+
static final int GOOGLE_PLAY_SERVICES_AVAILABILITY_SERVICE_UPDATING = 2;
19+
static final int GOOGLE_PLAY_SERVICES_AVAILABILITY_SERVICE_VERSION_UPDATE_REQUIRED = 3;
20+
static final int GOOGLE_PLAY_SERVICES_AVAILABILITY_SERVICE_DISABLED = 4;
21+
static final int GOOGLE_PLAY_SERVICES_AVAILABILITY_SERVICE_INVALID = 5;
22+
static final int GOOGLE_PLAY_SERVICES_AVAILABILITY_NOT_AVAILABLE_ON_PLATFORM = 6;
23+
static final int GOOGLE_PLAY_SERVICES_AVAILABILITY_UNKNOWN = 7;
24+
25+
26+
@Retention(RetentionPolicy.SOURCE)
27+
@IntDef({
28+
GOOGLE_PLAY_SERVICES_AVAILABILITY_SUCCESS,
29+
GOOGLE_PLAY_SERVICES_AVAILABILITY_SERVICE_MISSING,
30+
GOOGLE_PLAY_SERVICES_AVAILABILITY_SERVICE_UPDATING,
31+
GOOGLE_PLAY_SERVICES_AVAILABILITY_SERVICE_VERSION_UPDATE_REQUIRED,
32+
GOOGLE_PLAY_SERVICES_AVAILABILITY_SERVICE_DISABLED,
33+
GOOGLE_PLAY_SERVICES_AVAILABILITY_SERVICE_INVALID,
34+
GOOGLE_PLAY_SERVICES_AVAILABILITY_NOT_AVAILABLE_ON_PLATFORM,
35+
GOOGLE_PLAY_SERVICES_AVAILABILITY_UNKNOWN,
36+
})
37+
@interface GooglePlayServicesAvailability {
38+
}
39+
40+
@GooglePlayServicesAvailability
41+
static int toPlayServiceAvailability(int connectionResult) {
42+
switch (connectionResult) {
43+
case ConnectionResult.SUCCESS:
44+
return GOOGLE_PLAY_SERVICES_AVAILABILITY_SUCCESS;
45+
case ConnectionResult.SERVICE_MISSING:
46+
return GOOGLE_PLAY_SERVICES_AVAILABILITY_SERVICE_MISSING;
47+
case ConnectionResult.SERVICE_UPDATING:
48+
return GOOGLE_PLAY_SERVICES_AVAILABILITY_SERVICE_UPDATING;
49+
case ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED:
50+
return GOOGLE_PLAY_SERVICES_AVAILABILITY_SERVICE_VERSION_UPDATE_REQUIRED;
51+
case ConnectionResult.SERVICE_DISABLED:
52+
return GOOGLE_PLAY_SERVICES_AVAILABILITY_SERVICE_DISABLED;
53+
case ConnectionResult.SERVICE_INVALID:
54+
return GOOGLE_PLAY_SERVICES_AVAILABILITY_SERVICE_INVALID;
55+
default:
56+
return GOOGLE_PLAY_SERVICES_AVAILABILITY_UNKNOWN;
57+
}
58+
}
59+
}
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
package com.baseflow.googleapiavailability;
2+
3+
import android.app.Activity;
4+
import android.app.Dialog;
5+
import android.app.PendingIntent;
6+
import android.content.Context;
7+
import android.util.Log;
8+
9+
import com.google.android.gms.common.ConnectionResult;
10+
import com.google.android.gms.common.GoogleApiAvailability;
11+
import com.google.android.gms.tasks.Task;
12+
13+
import java.util.List;
14+
15+
public class GoogleApiAvailabilityManager {
16+
17+
GoogleApiAvailability googleApiAvailability = GoogleApiAvailability.getInstance();
18+
19+
@FunctionalInterface
20+
interface SuccessCallback {
21+
void onSuccess(int connectionResult);
22+
}
23+
24+
@FunctionalInterface
25+
interface MakeGooglePlayServicesAvailableCallback {
26+
void onSuccess(Void v);
27+
}
28+
29+
@FunctionalInterface
30+
interface getErrorStringCallback {
31+
void onSuccess(String errorString);
32+
}
33+
34+
@FunctionalInterface
35+
interface isUserResolvableCallback {
36+
void onSuccess(boolean isUserResolvable);
37+
}
38+
39+
@FunctionalInterface
40+
interface showErrorNotificationCallback {
41+
void onSuccess(Void v);
42+
}
43+
44+
@FunctionalInterface
45+
interface showErrorDialogFragmentCallback {
46+
void onSuccess(boolean showErrorDialogFragmentCallback);
47+
}
48+
49+
@FunctionalInterface
50+
interface ErrorCallback {
51+
void onError(String errorCode, String errorDescription);
52+
}
53+
54+
void checkPlayServicesAvailability(Boolean showDialog, Activity activity, Context applicationContext, SuccessCallback successCallback, ErrorCallback errorCallback) {
55+
if (applicationContext == null) {
56+
Log.e(GoogleApiAvailabilityConstants.LOG_TAG, "The `ApplicationContext` cannot be null.");
57+
errorCallback.onError("GoogleApiAvailability.GoogleApiAvailabilityManager", "Android `ApplicationContext` cannot be null.");
58+
return;
59+
}
60+
61+
final int connectionResult = googleApiAvailability
62+
.isGooglePlayServicesAvailable(applicationContext);
63+
64+
if (activity == null) {
65+
if (showDialog != null && showDialog) {
66+
// Only log warning when `showDialog` property was `true`.
67+
Log.w(GoogleApiAvailabilityConstants.LOG_TAG, "Unable to show dialog as `Activity` is not available.");
68+
}
69+
showDialog = false;
70+
}
71+
72+
if (showDialog != null && showDialog) {
73+
googleApiAvailability
74+
.showErrorDialogFragment(activity, connectionResult, GoogleApiAvailabilityConstants.REQUEST_GOOGLE_PLAY_SERVICES);
75+
}
76+
77+
successCallback.onSuccess(GoogleApiAvailabilityConstants.toPlayServiceAvailability(connectionResult));
78+
}
79+
80+
void makeGooglePlayServicesAvailable(Activity activity, MakeGooglePlayServicesAvailableCallback successCallback, ErrorCallback errorCallback) {
81+
if (activity == null) {
82+
Log.e(GoogleApiAvailabilityConstants.LOG_TAG, "Activity cannot be null.");
83+
errorCallback.onError("GoogleApiAvailability.makeGooglePlayServicesAvailable", "Android Activity cannot be null.");
84+
return;
85+
}
86+
87+
googleApiAvailability.makeGooglePlayServicesAvailable(activity)
88+
.addOnFailureListener((Exception e) -> errorCallback.onError("GoogleApiAvailability.makeGooglePlayServicesAvailable", e.getMessage()))
89+
.addOnSuccessListener((Void t) -> successCallback.onSuccess(null));
90+
}
91+
92+
void getErrorString(Context applicationContext, getErrorStringCallback successCallback, ErrorCallback errorCallback) {
93+
if (applicationContext == null) {
94+
Log.e(GoogleApiAvailabilityConstants.LOG_TAG, "Context cannot be null.");
95+
errorCallback.onError("GoogleApiAvailability.getErrorString", "Android context cannot be null.");
96+
return;
97+
}
98+
99+
final String errorString = googleApiAvailability.getErrorString(googleApiAvailability.isGooglePlayServicesAvailable(applicationContext));
100+
101+
successCallback.onSuccess(errorString);
102+
}
103+
104+
void isUserResolvable(Context applicationContext, isUserResolvableCallback successCallback, ErrorCallback errorCallback) {
105+
if (applicationContext == null) {
106+
Log.e(GoogleApiAvailabilityConstants.LOG_TAG, "Context cannot be null.");
107+
errorCallback.onError("GoogleApiAvailability.isUserResolvable", "Android context cannot be null.");
108+
return;
109+
}
110+
111+
final int connectionResult = googleApiAvailability
112+
.isGooglePlayServicesAvailable(applicationContext);
113+
114+
successCallback.onSuccess(googleApiAvailability.isUserResolvableError(connectionResult));
115+
}
116+
117+
void showErrorNotification(Context applicationContext, showErrorNotificationCallback successCallback, ErrorCallback errorCallback) {
118+
if (applicationContext == null) {
119+
Log.e(GoogleApiAvailabilityConstants.LOG_TAG, "Context cannot be null.");
120+
errorCallback.onError("GoogleApiAvailability.showErrorNotification", "Android context cannot be null.");
121+
return;
122+
}
123+
124+
final int connectionResult = googleApiAvailability
125+
.isGooglePlayServicesAvailable(applicationContext);
126+
127+
googleApiAvailability.showErrorNotification(applicationContext, connectionResult);
128+
129+
successCallback.onSuccess(null);
130+
}
131+
132+
void showErrorDialogFragment(Context applicationContext, Activity activity, showErrorDialogFragmentCallback successCallback, ErrorCallback errorCallback) {
133+
if (applicationContext == null) {
134+
Log.e(GoogleApiAvailabilityConstants.LOG_TAG, "Context cannot be null.");
135+
errorCallback.onError("GoogleApiAvailability.showErrorDialogFragment", "Android context cannot be null.");
136+
return;
137+
}
138+
139+
final int errorCode = googleApiAvailability
140+
.isGooglePlayServicesAvailable(applicationContext);
141+
142+
if (errorCode != GoogleApiAvailabilityConstants.GOOGLE_PLAY_SERVICES_AVAILABILITY_SUCCESS) {
143+
googleApiAvailability.showErrorDialogFragment(activity, errorCode, GoogleApiAvailabilityConstants.REQUEST_GOOGLE_PLAY_SERVICES);
144+
successCallback.onSuccess(true);
145+
}
146+
147+
successCallback.onSuccess(false);
148+
}
149+
}

android/src/main/java/com/baseflow/googleapiavailability/GoogleApiAvailabilityPlugin.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import android.content.Context;
44
import androidx.annotation.NonNull;
5+
56
import io.flutter.embedding.engine.plugins.FlutterPlugin;
67
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
78
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
@@ -16,10 +17,15 @@
1617
*/
1718
public class GoogleApiAvailabilityPlugin implements FlutterPlugin, ActivityAware {
1819

20+
private final GoogleApiAvailabilityManager googleApiAvailabilityManager;
1921
private MethodChannel channel;
2022
private MethodCallHandlerImpl methodCallHandler;
2123

22-
@Override
24+
public GoogleApiAvailabilityPlugin() {
25+
this.googleApiAvailabilityManager = new GoogleApiAvailabilityManager();
26+
}
27+
28+
@Override
2329
public void onAttachedToActivity(ActivityPluginBinding binding) {
2430
methodCallHandler.setActivity(binding.getActivity());
2531
}
@@ -64,7 +70,7 @@ public boolean onViewDestroy(FlutterNativeView view) {
6470
}
6571

6672
private void registerPlugin(Context context, BinaryMessenger messenger) {
67-
methodCallHandler = new MethodCallHandlerImpl(context);
73+
methodCallHandler = new MethodCallHandlerImpl(context, googleApiAvailabilityManager);
6874
channel = new MethodChannel(messenger, "flutter.baseflow.com/google_api_availability/methods");
6975
channel.setMethodCallHandler(methodCallHandler);
7076
}

0 commit comments

Comments
 (0)