Salman Yaqoob
Huawei Developers
Published in
4 min readJun 17, 2020

--

Flutter check HMS/GMS Availability

Flutter writing custom platform-specific code

This guide describes how to write custom platform-specific code. Some platform-specific functionality is available through existing packages

Flutter uses a flexible system that allows you to call platform-specific APIs whether available in Kotlin or Java code on Android, or in Swift or Objective-C code on iOS.

Flutter’s platform-specific API support does not rely on code generation, but rather on a flexible message passing style:

  • The Flutter portion of the app sends messages to its host, the iOS or Android portion of the app, over a platform channel.
  • The host listens on the platform channel, and receives the message. It then calls into any number of platform-specific APIs — using the native programming language — and sends a response back to the client, the Flutter portion of the app.

Architectural overview: platform channels

Messages are passed between the client (UI) and host (platform) using platform channels as illustrated in this diagram:

Flutter Architectural

Messages and responses are passed asynchronously, to ensure the user interface remains responsive.

Step 1: Create a new app project

Start by creating a new app:

  • In a terminal run: flutter create flutterhmsgmscheck

Step 2: Create the Flutter platform client

The app’s State class holds the current app state. Extend that to hold the current battery state.

First, construct the channel. Use a MethodChannel with a single platform method that returns the battery level.

The client and host sides of a channel are connected through a channel name passed in the channel constructor. All channel names used in a single app must be unique; prefix the channel name with a unique ‘domain prefix’, for example: com.salman.flutter.hmsgmscheck/isHmsGmsAvailable.

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:hmsallkitsflutter/app/ui/widgets/header.dart';

class HmsGmsCheck extends StatelessWidget {
HmsGmsCheck();

@override
Widget build(BuildContext context) {
return HmsGmsCheckStateful(
title: "HMS/GMS Check",
);
}
}

class HmsGmsCheckStateful extends StatefulWidget {
HmsGmsCheckStateful({Key key, this.title}) : super(key: key);
final String title;

@override
_HmsGmsCheckState createState() => _HmsGmsCheckState();
}

class _HmsGmsCheckState extends State<HmsGmsCheckStateful> {
static const MethodChannel methodChannel =
MethodChannel('com.salman.flutter.hmsallkitsflutter/isHmsGmsAvailable');
bool _isHmsAvailable;
bool _isGmsAvailable;

@override
void initState() {
checkHmsGms();
}

void checkHmsGms() async {
await _isHMS();
await _isGMS();
}

Future<void> _isHMS() async {
bool status;

try {
bool result = await methodChannel.invokeMethod('isHmsAvailable');
status = result;
print('status : ${status.toString()}');
} on PlatformException {
print('Failed to get _isHmsAvailable.');
}

setState(() {
_isHmsAvailable = status;
});
}

Future<void> _isGMS() async {
bool status;

try {
bool result = await methodChannel.invokeMethod('isGmsAvailable');
status = result;
print('status : ${status.toString()}');
} on PlatformException {
print('Failed to get _isGmsAvailable.');
}

setState(() {
_isGmsAvailable = status;
});
}

@override
Widget build(BuildContext context) {

return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Column(
children: <Widget>[
HeaderWidget(
title: "HMS/GMS Availability",
),
new Container(
padding: EdgeInsets.all(20),
child: new Column(
children: <Widget>[
Text(
"HMS Available: $_isHmsAvailable",
style: Theme.of(context).textTheme.headline6,
),
Text(
"GMS Available: $_isGmsAvailable",
style: Theme.of(context).textTheme.headline6,
)
],
),
)
],
));
}
}

Step 3: Update your gradle

Open your gradle in Android Studio and apply huawei repo:

Project-level build.gradle

buildscript {
ext.kotlin_version = '1.3.50'
repositories {
google()
jcenter()
maven { url 'https://developer.huawei.com/repo/' }
}

}
allprojects {
repositories {
google()
jcenter()
maven { url 'https://developer.huawei.com/repo/' }
}
}

App-level build.gradle

dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation "com.huawei.hms:hwid:4.0.0.300"
implementation "com.google.android.gms:play-services-base:17.3.0"
}

Step 4: Add an Android platform-specific implementation

Start by opening the Android host portion of your Flutter app in Android Studio:

  1. Start Android Studio
  2. Select the menu item File > Open…
  3. Navigate to the directory holding your Flutter app, and select the android folder inside it. Click OK.
  4. Open the file MainActivity.kt located in the kotlin folder in the Project view. (Note: If editing with Android Studio 2.3, note that the kotlin folder is shown as if named java.)

Inside the configureFlutterEngine() method, create a MethodChannel and call setMethodCallHandler(). Make sure to use the same channel name as was used on the Flutter client side.

class MainActivity: FlutterActivity() {
private val CHANNEL = "com.salman.flutter.hmsgmscheck/isHmsGmsAvailable"
var concurrentContext = this@MainActivity.context override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler {
call, result ->
// Note: this method is invoked on the main thread.
if (call.method.equals("isHmsAvailable")) {
result.success(isHmsAvailable());
} else if (call.method.equals("isGmsAvailable")) {
result.success(isGmsAvailable());
} else {
result.notImplemented()
}
}
}
private fun isHmsAvailable(): Boolean {
var isAvailable = false
val context: Context = concurrentContext
if (null != context) {
val result = HuaweiApiAvailability.getInstance().isHuaweiMobileServicesAvailable(context)
isAvailable = ConnectionResult.SUCCESS == result
}
Log.i("MainActivity", "isHmsAvailable: $isAvailable")
return isAvailable
}
private fun isGmsAvailable(): Boolean {
var isAvailable = false
val context: Context = concurrentContext
if (null != context) {
val result: Int = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context)
isAvailable = com.google.android.gms.common.ConnectionResult.SUCCESS === result
}
Log.i("MainActivity", "isGmsAvailable: $isAvailable")
return isAvailable
}
}

After completing above all steps compile your project you will get the following output.

Conclusion:

With the help of this article we can able to access platform specific native code under our flutter application. For further more details you can check offical flutter platform channels guide.

--

--