[Huawei Developers] Freemind R:
This article is originally from HUAWEI Developer Forum

Forum link: https://forums.developer.huawei.com/forumPortal/en/home​

As Flutter grows, we would get lot of plugins . If your project needs a specific dependency that does not exist on flutter you can define it in native code (IOS and android) and create a communication link between your flutter code and native code.

Contents

· Download Flutter SDK

· Set up flutter in Android studio

· Understanding the structure

· Running the demo project

· Understanding UI Components

· Threading concepts in flutter

· Integrating HMS to a flutter app

· Using hot reload

· Flutter inspector

Download Flutter SDK

Visit the following url to download the latest flutter SDK for your operating system.

https://flutter.dev/docs/get-started/install

Open Android studio and go to Plugin market place and search flutter and download the flutter plugin and restart your ID to show changes to your IDE, which enables us to create and manage a Flutter project.

[IMG="https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/753/335/2640091000001753335.20200605195354.48125382110162297778126358768588:50510615061246:2800:08D85F5785C2765E4D742A258D5C9ED0E87D6FD261F2384286E3167C3F8F4D80.png"]https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/753/335/2640091000001753335.20200605195354.48125382110162297778126358768588:50510615061246:2800:08D85F5785C2765E4D742A258D5C9ED0E87D6FD261F2384286E3167C3F8F4D80.png[/IMG]

Set up flutter in Android studio

To create a new Flutter application select File->New Flutter project and follow the steps mentioned below.

[IMG="https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/753/335/2640091000001753335.20200605195354.05691217397723311567252858168213:50510615061246:2800:12B744673414861595F42B2E6BCF28F2A4758AF6548E275CFB4FB04A7DC015E6.png"]https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/753/335/2640091000001753335.20200605195354.05691217397723311567252858168213:50510615061246:2800:12B744673414861595F42B2E6BCF28F2A4758AF6548E275CFB4FB04A7DC015E6.png[/IMG]

[IMG="https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/753/335/2640091000001753335.20200605195352.56275628200256319039404109272465:50510615061246:2800:2A4FA98E1047D01273F248AC621F9CB9EAE2B3A990590FBD5306D4A3877C7CBE.png"]https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/753/335/2640091000001753335.20200605195352.56275628200256319039404109272465:50510615061246:2800:2A4FA98E1047D01273F248AC621F9CB9EAE2B3A990590FBD5306D4A3877C7CBE.png[/IMG]

Specify the path of your Flutter SDK that you downloaded in your Flutter SDK path as shown below and click next.

[IMG="https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/753/335/2640091000001753335.20200605195353.06382773208372346205086298436754:50510615061246:2800:F090C03AF9B7A016EC4C23EE5AC08035B0B1410CE4CA05C50A1AA452C50E0D8A.png"]https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/753/335/2640091000001753335.20200605195353.06382773208372346205086298436754:50510615061246:2800:F090C03AF9B7A016EC4C23EE5AC08035B0B1410CE4CA05C50A1AA452C50E0D8A.png[/IMG]

Understanding the structure

[IMG="https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/753/335/2640091000001753335.20200605195353.16247920623681984304764845329399:50510615061246:2800:71AFB05EBAF04C293C52A7A669631FE434C820036FB698290049921F0767319A.png"]https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/753/335/2640091000001753335.20200605195353.16247920623681984304764845329399:50510615061246:2800:71AFB05EBAF04C293C52A7A669631FE434C820036FB698290049921F0767319A.png[/IMG]

Pubspec.yaml : Here you will find the app’s dependencies. This includes configuration files, images and other assets. Enter the package name and the version under the dependencies: section of the pubspec.yaml. Run the command flutter packages get to install these packages, enter the package name and version under the dependencies section.

[IMG="https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/753/335/2640091000001753335.20200605195353.93657663451001528966393498311527:50510615061246:2800:B6885F85BAD3AE4ECFA753E1C1593E3498C847998E244D9DA107B4D7F619A620.png"]https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/753/335/2640091000001753335.20200605195353.93657663451001528966393498311527:50510615061246:2800:B6885F85BAD3AE4ECFA753E1C1593E3498C847998E244D9DA107B4D7F619A620.png[/IMG]

Main.dart : main.dart is the entry point of any flutter application, this is found under lib folder as shown above, this contains all the dart classes. During creation the main.dart file comes with a simple pre written code. Connect your device to the system or start the emulator and run the project to see the result of the sample project.

Adding images in flutter:

Create an assets folder in the directory that contains the pubspec.yaml file and move all your Images to this folder.

[IMG="https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/753/335/2640091000001753335.20200605195353.49243859520704073314257741545514:50510615061246:2800:2FA25F74AFA5253379CD6D210206EAC7D8C35B3033368B076B71BC6C2520B6FF.png"]https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/753/335/2640091000001753335.20200605195353.49243859520704073314257741545514:50510615061246:2800:2FA25F74AFA5253379CD6D210206EAC7D8C35B3033368B076B71BC6C2520B6FF.png[/IMG]

Use pub.get to sync all the files and use the images.

[IMG="https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/753/335/2640091000001753335.20200605195352.23010310643351447162275808570117:50510615061246:2800:F0160117656C19BA7ABD77F3F6A415EE23245AA22033CEFF207EF77622A6D221.png"]https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/753/335/2640091000001753335.20200605195352.23010310643351447162275808570117:50510615061246:2800:F0160117656C19BA7ABD77F3F6A415EE23245AA22033CEFF207EF77622A6D221.png[/IMG]

All native flutter dependencies are also added to pubspec.yaml file as shown below

Running Demo project

When we create a new flutter project, we get a simple app with floating action button and a counter, if you change text from the sample project above the counter text and click save it is immediately shown on the screen, this feature is called Hot reload and will be used extensively during flutter development.

[IMG="https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/753/335/2640091000001753335.20200605201111.49630315475231225667771280030767:50510615061246:2800:78A2EDE4D4FC2392B7EA182E475F90D444B4635867F1E371ABCC055305C818BE.png"]https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/753/335/2640091000001753335.20200605201111.49630315475231225667771280030767:50510615061246:2800:78A2EDE4D4FC2392B7EA182E475F90D444B4635867F1E371ABCC055305C818BE.png[/IMG]

We will be creating a simple UI with a click event which helps us to send messages to our native code.

UI Components in Flutter

Scaffold

Container

Material app

Stateful and stateless widget

Scaffold: The foundation for most projects on Android are an App bar, a body which holds our app design and a floating action button as highlighted below.

Create a structure for the design remains simple with a scaffold as most of the commonly used components are defined and supported by Scaffold.

[IMG="https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/753/335/2640091000001753335.20200605195354.06257339536459957020958911144102:50510615061246:2800:32A367972C9568EA15E50071CF9F1BF6A416C5D612CBD5B0ED0DB5E84DFD525B.png"]https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/753/335/2640091000001753335.20200605195354.06257339536459957020958911144102:50510615061246:2800:32A367972C9568EA15E50071CF9F1BF6A416C5D612CBD5B0ED0DB5E84DFD525B.png[/IMG]

As shown in the program below we have the following properties

· Appbar with a title

· Body with a text at the center of the screen

· Floating action button with onPressed click event

Widget build(BuildContext context){
Return Scaffold(
appBar:AppBar(
title: const Text(‘Sample Code’),
),
Body: Center(child: Text(‘You have pressed the button $_count times.’)),
floatingActionButton: FloatingActionButton(
onPressed: () => setState(() => _count++),
tooltip: ‘Increment Counter’,
child: const Icon(Icons.add),
),
);
}}

Container: allows us to add background padding and design to different elements available on flutter. The diagram shows an example on using Container where we have a child text and color.

[IMG="https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/753/335/2640091000001753335.20200605195353.04675635701036479454769392813769:50510615061246:2800:72FFAFBA4FF2F64119B923C405A39FE0558FC5693D588994B81B5E8EFD5F482B.png"]https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/753/335/2640091000001753335.20200605195353.04675635701036479454769392813769:50510615061246:2800:72FFAFBA4FF2F64119B923C405A39FE0558FC5693D588994B81B5E8EFD5F482B.png[/IMG]

MaterialApp: MaterialApp is required when we use Material components and follow material design in your app

Stateful widget: Stateful widgets are mutable and are used when the UI can change dynamically, flutter creates a state object during build process of a stateful widget, this is the place where mutable state for that widget is saved.

Stateless widget: A stateless widget has no internal state to manage. Icon, IconButton, and Text are examples of stateless widgets, which are a subclass of StatelessWidget and are expected to remain static.

Threading concepts in Flutter

Async: function is asynchronous and you might need to wait a bit to get its result.

Await: wait until this function is finished and you will get its return value.

Future: is a type that ‘comes from the future’ and returns value from your asynchronous function. It can complete with success (.then) or with an error(.catchError).

Then ((value){…}): is a callback that’s called when future completes successfully(with a value).

Difference between Const and final in Flutter

Const: it is initialized during the compilation. Whenever you compile the program the value of PI will be initialized and memory will be allocated. It does not matter if you are using this variable or not.

Final: If you use the final variable in your program only then the value is initialized and memory location is allocated. And if you never use the final variable the value will never be initialized in your program.

Let us use the design and threading concepts to create project which updates location on a click event.

Integrating HMS to a Flutter app

Add a channel name in MyHomePage stateful widget, which will be added to our native code for message passing.

static const Locationplatform = const MethodChannel("samples.flutter.dev/Location");

We will be adding an Icon button and adding a click event to create a class which extends stateful widget as shown

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

final String title;

@override
_MyHomePageState createState() {
return _MyHomePageState();
}
}

class _MyHomePageState extends State<MyHomePage> {
static const Locationplatform = const MethodChannel("samples.flutter.dev/Location");

@override
Widget build(BuildContext context) {

}
}

We have a stateful widget which will hold our click event to pass the message to native code using method channel. The program for the design of the button and click event is defined in the overridden method build in MyHomePageState class.

We have a text element which will be placed below the icon and all of this would be at the center of the screen. We define a Scaffold with app bar and body which would eb the important material design components of our app.

We define tooltip and icon button and center align them and create a text at the top of the screen.

Here is the complete main.dart file

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

final String title;

@override
_MyHomePageState createState() {
return _MyHomePageState();
}
}

class _MyHomePageState extends State<MyHomePage> {
static const Locationplatform = const MethodChannel("samples.flutter.dev/Location");

@override
Widget build(BuildContext context) {

}
}

Using hot reload

One of the best feature of flutter is hot reload, make changes to your UI and click save while your device is connected to pc and click Ctrl + S on windows and see changes instantly on your screen.

Hot reload helps you see code and user interface changes instantly on your virtual device or mobile device. This is an extremely useful feature for the developer as it saves development time.

[IMG="https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/753/335/2640091000001753335.20200605195352.28419389967562322109960528961555:50510615061246:2800:A7E87B1F670083A1300F04DB1D0A4F2BF6DFA7461F84EF662FEDE02C80F74F8F.png"]https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/753/335/2640091000001753335.20200605195352.28419389967562322109960528961555:50510615061246:2800:A7E87B1F670083A1300F04DB1D0A4F2BF6DFA7461F84EF662FEDE02C80F74F8F.png[/IMG]

To see the changes instantly on your device change the title of your material app as shown above and click ctrl+S on windows and cmd+S on Mac.

It is important to know that any editing that will be performed in gradle or your JAVA/Kotlin files have to be opened for editing in a new window as editing it in the same files could show errors, which cannot be corrected.

[IMG="https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/753/335/2640091000001753335.20200605203708.76566681321632265155221940398564:50510615061246:2800:26A899DF274BC12F7C617BAE70F4BC7C78C07D9231420036D3FEC60C577E3105.png"]https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/753/335/2640091000001753335.20200605203708.76566681321632265155221940398564:50510615061246:2800:26A899DF274BC12F7C617BAE70F4BC7C78C07D9231420036D3FEC60C577E3105.png[/IMG]

After selecting open for editing in android studio as show below, we can follow the mentioned steps to add HMS location kit dependency, the process remains the same as adding any other kit to your project.

Please follow these steps

Creating an AGC Application.

Creating an Android Studio Project.

Generating a signature certificate.

Generating a signature certificate fingerprint.

Configuring the signature certificate fingerprint.

Adding the application package name and save the configuration file.

Configure the Maven address and AGC gradle plug-in.

Configure the signature file in Android Studio.

For more information please check the following link:

https://developer.huawei.com/consumer/en/codelab/HMSLocationKit/index.html#0

Define the Method channel in MainActivity file as shown below and this name should match the channel name in your main.dart file

private static final String ShowLocationchannel = "samples.flutter.dev/Location";

Extend your MainActivity class with FlutterActivity and override configureFlutterEngine to handle click event.

@Override
public void configureFlutterEngine(FlutterEngine flutterEngine) {
super.configureFlutterEngine(flutterEngine);
new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), ShowLocationchannel)
.setMethodCallHandler(
(call, result) -> {

if(call.method.equals("ShowLocation"))
{
ShowLocation();
result.success(0);
}

}
);
}

Create a method ShowLocation() and create an Intent to move to LocationActivity class

private int ShowLocation() {

startActivity(new Intent(MainActivity.this, LocationActivity.class));
return 0;
} Create LocationActivity class that uses FusedLocationProviderClient object to requestLocationUpdates and settingsClient object to call checkLocationSettings method to check device settings.
public class LocationActivity extends AppCompatActivity implements View.OnClickListener {
public static final String TAG = "LocationUpdatesCallback";

// the callback of the request
LocationCallback mLocationCallback;

LocationRequest mLocationRequest;

private FusedLocationProviderClient fusedLocationProviderClient;

private SettingsClient settingsClient;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_location);
findViewById(R.id.location_requestLocationUpdatesWithCallback).setOnClickListener(this);
findViewById(R.id.location_removeLocationUpdatesWithCallback).setOnClickListener(this);

// create fusedLocationProviderClient
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);
// create settingsClient
settingsClient = LocationServices.getSettingsClient(this);
mLocationRequest = new LocationRequest();
// Set the interval for location updates, in milliseconds.
mLocationRequest.setInterval(10000);
// set the priority of the request
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

if (null == mLocationCallback) {
mLocationCallback = new LocationCallback() {
@Override
public void onLocationResult(LocationResult locationResult) {
if (locationResult != null) {
List<Location> locations = locationResult.getLocations();
if (!locations.isEmpty()) {
for (Location location : locations) {
Toast.makeText(LocationActivity.this,
"onLocationResult location[Longitude,Latitude,Accuracy]:" + location.getLongitude()
+ "," + location.getLatitude() + "," + location.getAccuracy(),Toast.LENGTH_LONG);
}
}
}
}

@Override
public void onLocationAvailability(LocationAvailability locationAvailability) {
if (locationAvailability != null) {
boolean flag = locationAvailability.isLocationAvailable();
Log.i(TAG, "onLocationAvailability isLocationAvailable:" + flag);
}
}
};
}

// check location permisiion
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) {
Log.i(TAG, "sdk < 28 Q");
if (ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
String[] strings =
{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION};
ActivityCompat.requestPermissions(this, strings, 1);
}
} else {
if (ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(this,
"android.permission.ACCESS_BACKGROUND_LOCATION") != PackageManager.PERMISSION_GRANTED) {
String[] strings = {android.Manifest.permission.ACCESS_FINE_LOCATION,
android.Manifest.permission.ACCESS_COARSE_LOCATION,
"android.permission.ACCESS_BACKGROUND_LOCATION"};
ActivityCompat.requestPermissions(this, strings, 2);
}
}
}

private void requestLocationUpdatesWithCallback() {
try {
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
builder.addLocationRequest(mLocationRequest);
LocationSettingsRequest locationSettingsRequest = builder.build();
// check devices settings before request location updates.
settingsClient.checkLocationSettings(locationSettingsRequest)
.addOnSuccessListener(new OnSuccessListener<LocationSettingsResponse>() {
@Override
public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
Log.i(TAG, "check location settings success");
// request location updates
fusedLocationProviderClient
.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.getMainLooper())
.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
Log.i(TAG, "requestLocationUpdatesWithCallback onSuccess");
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
Log.e(TAG,
"requestLocationUpdatesWithCallback onFailure:" + e.getMessage());
}
});
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
Log.e(TAG, "checkLocationSetting onFailure:" + e.getMessage());
int statusCode = ((ApiException) e).getStatusCode();
switch (statusCode) {
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
try {
ResolvableApiException rae = (ResolvableApiException) e;
rae.startResolutionForResult(LocationActivity.this, 0);
} catch (IntentSender.SendIntentException sie) {
Log.e(TAG, "PendingIntent unable to execute request.");
}
break;
}
}
});
} catch (Exception e) {
Log.e(TAG, "requestLocationUpdatesWithCallback exception:" + e.getMessage());
}
}

@Override
protected void onDestroy() {
// don't need to receive callback
removeLocationUpdatesWithCallback();
super.onDestroy();
}

/**
* remove the request with callback
*/
private void removeLocationUpdatesWithCallback() {
try {
fusedLocationProviderClient.removeLocationUpdates(mLocationCallback)
.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
Log.i(TAG, "removeLocationUpdatesWithCallback onSuccess");
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
Log.e(TAG, "removeLocationUpdatesWithCallback onFailure:" + e.getMessage());
}
});
} catch (Exception e) {
Log.e(TAG, "removeLocationUpdatesWithCallback exception:" + e.getMessage());
}
}

@Override
public void onClick(View v) {
try {
switch (v.getId()) {
case R.id.location_requestLocationUpdatesWithCallback:
requestLocationUpdatesWithCallback();
break;
case R.id.location_removeLocationUpdatesWithCallback:
removeLocationUpdatesWithCallback();
break;
default:
break;
}
} catch (Exception e) {
Log.e(TAG, "RequestLocationUpdatesWithCallbackActivity Exception:" + e);
}
}

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == 1) {
if (grantResults.length > 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED
&& grantResults[1] == PackageManager.PERMISSION_GRANTED) {
Log.i(TAG, "onRequestPermissionsResult: apply LOCATION PERMISSION successful");
} else {
Log.i(TAG, "onRequestPermissionsResult: apply LOCATION PERMISSSION failed");
}
}

if (requestCode == 2) {
if (grantResults.length > 2 && grantResults[2] == PackageManager.PERMISSION_GRANTED
&& grantResults[0] == PackageManager.PERMISSION_GRANTED
&& grantResults[1] == PackageManager.PERMISSION_GRANTED) {
Log.i(TAG, "onRequestPermissionsResult: apply ACCESS_BACKGROUND_LOCATION successful");
} else {
Log.i(TAG, "onRequestPermissionsResult: apply ACCESS_BACKGROUND_LOCATION failed");
}
}
}
}

<span style="font-family: arial , helvetica , sans-serif;font-size: 18.0px;"><strong>Please add the following permissions to your manifest file to request Location updates</strong></span><strong>

</strong>

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>

Flutter inspector

We can use the Flutter inspector to find the nesting of all your widgets making it very easy to edit or find the widget you are looking for, improving design or changes to your UI is extremely simple in flutter using Enable select widget module.

Click select widget module to use he feature as shown below, after you click the select widget module, click on any widget on your screen and you will see changes to your flutter inspector widget tab. The widget selected on your device is highlighted and changes can be made this makes it simpler to find the widget if you a lot of widgets in your widget tree.

Click on the find Icon as shown in the figure to repeat the process again to find a widget.

[IMG="https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/753/335/2640091000001753335.20200605194649.62490715763344471832697773038335:50510615061246:2800:728BC334CD86373215F408B5907EBC02C9C2EA16DAF61EA6E77A462B970ADDD7.png"]https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/753/335/2640091000001753335.20200605194649.62490715763344471832697773038335:50510615061246:2800:728BC334CD86373215F408B5907EBC02C9C2EA16DAF61EA6E77A462B970ADDD7.png[/IMG]

[IMG="https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/753/335/2640091000001753335.20200606053921.19326820747025599405413060020320:50510615061246:2800:722CE97A604BB0F4A2E32D9DE42534F01D02F85AB3982596EA437A4488FAD2C7.gif"]https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/753/335/2640091000001753335.20200606053921.19326820747025599405413060020320:50510615061246:2800:722CE97A604BB0F4A2E32D9DE42534F01D02F85AB3982596EA437A4488FAD2C7.gif[/IMG]

Conclusion

An existing HMS project can be linked to a flutter screen using a method channel.

This completes the flutter tutorial, please comment like and share.

Stay tuned for more updates