Skip to content

Commit e8297e1

Browse files
committed
Changed native code structure, added makeGooglePlayServicesAvailable.
1 parent c186fe7 commit e8297e1

File tree

6 files changed

+212
-77
lines changed

6 files changed

+212
-77
lines changed
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+
private 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: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package com.baseflow.googleapiavailability;
2+
3+
import android.app.Activity;
4+
import android.content.Context;
5+
import android.util.Log;
6+
7+
import com.google.android.gms.common.GoogleApiAvailability;
8+
9+
public class GoogleApiAvailabilityManager {
10+
11+
GoogleApiAvailability googleApiAvailability = GoogleApiAvailability.getInstance();
12+
13+
@FunctionalInterface
14+
interface SuccessCallback {
15+
void onSuccess(@GoogleApiAvailabilityConstants.GooglePlayServicesAvailability int connectionResult);
16+
}
17+
18+
@FunctionalInterface
19+
interface MakeGooglePlayServicesAvailable {
20+
void onSuccess(boolean makeGooglePlayServicesAvailable);
21+
}
22+
23+
@FunctionalInterface
24+
interface ErrorCallback {
25+
void onError(String errorCode, String errorDescription);
26+
}
27+
28+
void checkPlayServicesAvailability(Boolean showDialog, Context applicationContext, SuccessCallback successCallback, ErrorCallback errorCallback) {
29+
if (applicationContext == null) {
30+
Log.d(GoogleApiAvailabilityConstants.LOG_TAG, "Context cannot be null.");
31+
errorCallback.onError("GoogleApiAvailability.GoogleApiAvailabilityManager", "Android context cannot be null.");
32+
return;
33+
}
34+
35+
final int connectionResult = googleApiAvailability
36+
.isGooglePlayServicesAvailable(applicationContext);
37+
38+
if (showDialog != null && showDialog) {
39+
googleApiAvailability
40+
.showErrorDialogFragment((Activity) applicationContext, connectionResult, GoogleApiAvailabilityConstants.REQUEST_GOOGLE_PLAY_SERVICES);
41+
}
42+
43+
successCallback.onSuccess(connectionResult);
44+
}
45+
46+
void makeGooglePlayServicesAvailable(Activity activity, MakeGooglePlayServicesAvailable successCallback, ErrorCallback errorCallback){
47+
if (activity == null){
48+
Log.d(GoogleApiAvailabilityConstants.LOG_TAG, "Activity cannot be null.");
49+
errorCallback.onError("GoogleApiAvailability.makeGooglePlayServicesAvailable", "Android Activity cannot be null.");
50+
return;
51+
}
52+
53+
final boolean status = googleApiAvailability.makeGooglePlayServicesAvailable(activity).isSuccessful();
54+
successCallback.onSuccess(status);
55+
}
56+
}

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
}

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

Lines changed: 38 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -2,98 +2,64 @@
22

33
import android.app.Activity;
44
import android.content.Context;
5+
56
import androidx.annotation.IntDef;
67
import androidx.annotation.NonNull;
78
import androidx.annotation.Nullable;
9+
810
import com.google.android.gms.common.ConnectionResult;
911
import com.google.android.gms.common.GoogleApiAvailability;
12+
1013
import io.flutter.plugin.common.MethodCall;
1114
import io.flutter.plugin.common.MethodChannel;
1215
import io.flutter.plugin.common.MethodChannel.Result;
16+
1317
import java.lang.annotation.Retention;
1418
import java.lang.annotation.RetentionPolicy;
1519

1620
public class MethodCallHandlerImpl implements MethodChannel.MethodCallHandler {
1721

18-
MethodCallHandlerImpl(Context applicationContext) {
19-
this.applicationContext = applicationContext;
20-
}
21-
22-
private final Context applicationContext;
23-
24-
@Nullable
25-
private Activity activity;
22+
private final GoogleApiAvailabilityManager googleApiAvailabilityManager;
2623

27-
void setActivity(@Nullable Activity activity) {
28-
this.activity = activity;
29-
}
24+
MethodCallHandlerImpl(Context applicationContext, GoogleApiAvailabilityManager googleApiAvailabilityManager) {
25+
this.applicationContext = applicationContext;
3026

31-
private static final int REQUEST_GOOGLE_PLAY_SERVICES = 1000;
27+
this.googleApiAvailabilityManager = googleApiAvailabilityManager;
28+
}
3229

33-
//GOOGLE_PLAY_SERVICES_AVAILABILITY
34-
private static final int GOOGLE_PLAY_SERVICES_AVAILABILITY_SUCCESS = 0;
35-
private static final int GOOGLE_PLAY_SERVICES_AVAILABILITY_SERVICE_MISSING = 1;
36-
private static final int GOOGLE_PLAY_SERVICES_AVAILABILITY_SERVICE_UPDATING = 2;
37-
private static final int GOOGLE_PLAY_SERVICES_AVAILABILITY_SERVICE_VERSION_UPDATE_REQUIRED = 3;
38-
private static final int GOOGLE_PLAY_SERVICES_AVAILABILITY_SERVICE_DISABLED = 4;
39-
private static final int GOOGLE_PLAY_SERVICES_AVAILABILITY_SERVICE_INVALID = 5;
40-
private static final int GOOGLE_PLAY_SERVICES_AVAILABILITY_NOT_AVAILABLE_ON_PLATFORM = 6;
41-
private static final int GOOGLE_PLAY_SERVICES_AVAILABILITY_UNKNOWN = 7;
30+
private final Context applicationContext;
4231

43-
@Retention(RetentionPolicy.SOURCE)
44-
@IntDef({
45-
GOOGLE_PLAY_SERVICES_AVAILABILITY_SUCCESS,
46-
GOOGLE_PLAY_SERVICES_AVAILABILITY_SERVICE_MISSING,
47-
GOOGLE_PLAY_SERVICES_AVAILABILITY_SERVICE_UPDATING,
48-
GOOGLE_PLAY_SERVICES_AVAILABILITY_SERVICE_VERSION_UPDATE_REQUIRED,
49-
GOOGLE_PLAY_SERVICES_AVAILABILITY_SERVICE_DISABLED,
50-
GOOGLE_PLAY_SERVICES_AVAILABILITY_SERVICE_INVALID,
51-
GOOGLE_PLAY_SERVICES_AVAILABILITY_NOT_AVAILABLE_ON_PLATFORM,
52-
GOOGLE_PLAY_SERVICES_AVAILABILITY_UNKNOWN,
53-
})
54-
private @interface GooglePlayServicesAvailability {
32+
@Nullable
33+
private Activity activity;
5534

56-
}
35+
void setActivity(@Nullable Activity activity) {
36+
this.activity = activity;
37+
}
5738

58-
@Override
59-
public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
60-
if (call.method.equals("checkPlayServicesAvailability")) {
61-
final Boolean showDialog = call.argument("showDialog");
62-
GoogleApiAvailability googleApiAvailability = GoogleApiAvailability.getInstance();
63-
final int connectionResult = googleApiAvailability
64-
.isGooglePlayServicesAvailable(applicationContext);
6539

66-
if (activity != null) {
67-
if (showDialog != null && showDialog) {
68-
googleApiAvailability
69-
.showErrorDialogFragment(activity, connectionResult, REQUEST_GOOGLE_PLAY_SERVICES);
40+
@Override
41+
public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
42+
switch (call.method) {
43+
case "checkPlayServicesAvailability": {
44+
final Boolean showDialog = call.argument("showDialog");
45+
googleApiAvailabilityManager.checkPlayServicesAvailability(showDialog, applicationContext, result::success,
46+
(String errorCode, String errorDescription) -> result.error(
47+
errorCode,
48+
errorDescription,
49+
null));
50+
break;
51+
}
52+
case "makeGooglePlayServicesAvailable": {
53+
googleApiAvailabilityManager.makeGooglePlayServicesAvailable(activity,result::success,
54+
(String errorCode, String errorDescription) -> result.error(
55+
errorCode,
56+
errorDescription,
57+
null));
58+
break;
59+
}
60+
default:
61+
result.notImplemented();
62+
break;
7063
}
71-
}
72-
73-
final int availability = toPlayServiceAvailability(connectionResult);
74-
result.success(availability);
75-
} else {
76-
result.notImplemented();
77-
}
78-
}
79-
80-
@GooglePlayServicesAvailability
81-
private int toPlayServiceAvailability(int connectionResult) {
82-
switch (connectionResult) {
83-
case ConnectionResult.SUCCESS:
84-
return GOOGLE_PLAY_SERVICES_AVAILABILITY_SUCCESS;
85-
case ConnectionResult.SERVICE_MISSING:
86-
return GOOGLE_PLAY_SERVICES_AVAILABILITY_SERVICE_MISSING;
87-
case ConnectionResult.SERVICE_UPDATING:
88-
return GOOGLE_PLAY_SERVICES_AVAILABILITY_SERVICE_UPDATING;
89-
case ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED:
90-
return GOOGLE_PLAY_SERVICES_AVAILABILITY_SERVICE_VERSION_UPDATE_REQUIRED;
91-
case ConnectionResult.SERVICE_DISABLED:
92-
return GOOGLE_PLAY_SERVICES_AVAILABILITY_SERVICE_DISABLED;
93-
case ConnectionResult.SERVICE_INVALID:
94-
return GOOGLE_PLAY_SERVICES_AVAILABILITY_SERVICE_INVALID;
95-
default:
96-
return GOOGLE_PLAY_SERVICES_AVAILABILITY_UNKNOWN;
9764
}
98-
}
9965
}

example/lib/main.dart

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ class MyApp extends StatefulWidget {
1818
class _MyAppState extends State<MyApp> {
1919
GooglePlayServicesAvailability _playStoreAvailability =
2020
GooglePlayServicesAvailability.unknown;
21+
bool _madeGooglePlayServiceAvailable = false;
2122

2223
// Platform messages are asynchronous, so we initialize in an async method.
2324
Future<void> checkPlayServices([bool showDialog = false]) async {
@@ -42,6 +43,28 @@ class _MyAppState extends State<MyApp> {
4243
});
4344
}
4445

46+
Future<void> makeGooglePlayServicesAvailable() async {
47+
bool madeGooglePlayServiceAvailable;
48+
49+
try {
50+
madeGooglePlayServiceAvailable = await GoogleApiAvailability.instance
51+
.makeGooglePlayServicesAvailable();
52+
} on PlatformException {
53+
madeGooglePlayServiceAvailable = false;
54+
}
55+
56+
// If the widget was removed from the tree while the asynchronous platform
57+
// message was in flight, we want to discard the reply rather than calling
58+
// setState to update our non-existent appearance.
59+
if (!mounted) {
60+
return;
61+
}
62+
63+
setState(() {
64+
_madeGooglePlayServiceAvailable = madeGooglePlayServiceAvailable;
65+
});
66+
}
67+
4568
@override
4669
Widget build(BuildContext context) {
4770
return MaterialApp(
@@ -56,15 +79,24 @@ class _MyAppState extends State<MyApp> {
5679
child: const Text('Get PlayServices availability'),
5780
color: Colors.red,
5881
),
82+
Center(
83+
child: Text(
84+
'Google Play Store status: ${_playStoreAvailability.toString().split('.').last}\n')
85+
),
86+
MaterialButton(
87+
onPressed: () => makeGooglePlayServicesAvailable(),
88+
child: const Text('Set Google Play Service to availabe'),
89+
color: Colors.red,
90+
),
91+
Center(
92+
child: Text(
93+
'Make available: $_madeGooglePlayServiceAvailable\n')),
5994
MaterialButton(
6095
onPressed: () => checkPlayServices(true),
6196
child:
6297
const Text('Get PlayServices availability with fix dialog'),
6398
color: Colors.redAccent,
6499
),
65-
Center(
66-
child: Text(
67-
'Google Play Store status: ${_playStoreAvailability.toString().split('.').last}\n')),
68100
],
69101
)),
70102
);

lib/src/google_api_availability.dart

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,20 @@ class GoogleApiAvailability {
4141

4242
return GooglePlayServicesAvailability.values[availability];
4343
}
44+
45+
/// Returns true if the device was able to set Google Play Services to available.
46+
/// Returns false if the device was unable to set Google Play Services to available or staus is unknown.
47+
///
48+
/// If it is necessary to display UI in order to complete this request
49+
/// (e.g. sending the user to the Google Play store) the passed Activity will be used to display this UI.
50+
Future<bool> makeGooglePlayServicesAvailable() async {
51+
if (defaultTargetPlatform != TargetPlatform.android) {
52+
return false;
53+
}
54+
55+
final availability = await _methodChannel.invokeMethod(
56+
'makeGooglePlayServicesAvailable');
57+
58+
return availability;
59+
}
4460
}

0 commit comments

Comments
 (0)