Integrating Huawei Scan-Kit in Flutter - Huawei Developers

Introduction
HUAWEI Scan Kit scans and parses all major 1D and 2D barcodes as well as generates barcodes to help you quickly build barcode scanning functions into your apps. Scan Kit automatically detects, magnifies, and recognizes barcodes from a distance, and also can scan a very small barcode in the same way. It works even in suboptimal situations, such as under dim lighting or when the barcode is reflective, dirty, blurry, or printed on a cylindrical surface. Huawei Scan kit has a higher scanning success rate.
There are three type of scan type.
1. Default View
2. Customized View
3. Multiprocessor Camera
1. Default View: In Default View mode, Scan Kit scans the barcodes using the camera or from images in the album. You do not need to worry about designing a UI as Scan Kit provides one.
2. Customized View: In Customized View mode, you do not need to worry about developing the scanning process or camera control. Scan Kit will do all these tasks for you. However, you will need to customize the scanning UI according to the customization options that Flutter Scan Plugin provides. This can also be easily completed based on the sample code below.
3. Multiprocessor Camera: Multiprocessor Camera Mode is used to recognize multiple barcodes simultaneously from the scanning UI or from the gallery. Scanning results will be returned as a list and during the scanning, the scanned barcodes will be caught by rectangles and their values will be shown on the scanning UI. In Multiprocessor Camera mode, you do not need to worry about developing the scanning process or camera control. Scan Kit will do all these tasks for you. However, you will need to customize the scanning UI according to the customization options that Flutter Scan Plugin provides.
In this article, we will learn Default view and Customized view.
Follow the steps
Step 1: Register as a Huawei Developer.
Step 2: Download Scan Flutter package and decompress it.
Step 3: Add dependencies pubspec.yaml. Change path according to your downloaded path.
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
Step 4: After adding the dependencies, click on Pub get.
Step 5: Navigate to any of the *.dart file and click on Get dependencies.
Step 6: Build Flutter sample Application.
Code:
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:huawei_scan/HmsScanLibrary.dart';
import 'item_list.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Scan Kit Demo',
theme: ThemeData(
primarySwatch: Colors.red,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Scan Kit'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/backgrond.jpg"),
fit: BoxFit.cover,
)),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
InkWell(
onTap: () async {
DefaultViewRequest request = new DefaultViewRequest(
scanType: HmsScanTypes.AllScanType);
ScanResponse response =
await HmsScanUtils.startDefaultView(request);
setState(() {
var resultScan = response.originalValue;
var codeFormatScan = response.scanType;
var resultTypeScan = response.scanTypeForm;
print("Result" +
resultTypeScan.toString() +
" " +
codeFormatScan.toString() +
" " +
resultScan);
Fluttertoast.showToast(
msg: "Result: "+ resultScan,
toastLength: Toast.LENGTH_LONG,
gravity: ToastGravity.BOTTOM,
timeInSecForIosWeb: 1,
backgroundColor: Colors.black,
textColor: Colors.white,
fontSize: 16.0
);
Scaffold.of(context).showSnackBar(SnackBar(
content: Text("Result" +resultScan),
));
});
},
child: Container(
width: MediaQuery.of(context).size.width * 0.8,
margin: EdgeInsets.all(10.0),
alignment: Alignment(0, 1),
padding: EdgeInsets.all(15.0),
decoration: new BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(25)),
child: Text(
'Default View',
style: new TextStyle(color: Colors.white),
),
),
),
InkWell(
onTap: () async {
CustomizedViewRequest request = new CustomizedViewRequest(scanType: HmsScanTypes.AllScanType);
await HmsCustomizedView.startCustomizedView(request);
},
child: Container(
width: MediaQuery.of(context).size.width * 0.8,
margin: EdgeInsets.all(10.0),
alignment: Alignment(0, 1),
padding: EdgeInsets.all(15.0),
decoration: new BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(25)),
child: Text(
'Customized View',
style: new TextStyle(color: Colors.white),
),
),
),
InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => ProductList()),
);
},
child: Container(
width: MediaQuery.of(context).size.width * 0.8,
margin: EdgeInsets.all(10.0),
alignment: Alignment(0, 1),
padding: EdgeInsets.all(15.0),
decoration: new BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(25)),
child: Text(
'Generate QR code',
style: new TextStyle(color: Colors.white),
),
),
)
],
),
),
),
);
}
customizedView() async {
var responseList = [];
ScanResponse response =
await HmsCustomizedView.startCustomizedView(
CustomizedViewRequest(
scanType: HmsScanTypes.AllScanType,
continuouslyScan: false,
isFlashAvailable: true,
flashOnLightChange: false,
customizedCameraListener: (ScanResponse response) {
//pause();
setState(() {
responseList.add(response);
});
//resume();
},
customizedLifeCycleListener:
(CustomizedViewEvent lifecycleStatus) {
debugPrint("Customized View LifeCycle Listener: " +
lifecycleStatus.toString());
if (lifecycleStatus == CustomizedViewEvent.onStart) {
Future.delayed(const Duration(seconds: 5), () async {
// switchLightOnLightStatus();
});
}
},
));
setState(() {
var resultScan = response.originalValue;
var codeFormatScan = response.scanType;
var resultTypeScan = response.scanTypeForm;
print("Result" +
resultTypeScan.toString() +
" " +
codeFormatScan.toString() +
" " +
resultScan);
Fluttertoast.showToast(
msg: "Result: "+ resultScan,
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
timeInSecForIosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 16.0
);
});
}
}
More details, you can check https://forums.developer.huawei.com/forumPortal/en/topic/0203436830890850132

Related

HMS Account Kit with Provider Pattern in Flutter

HMS Account Kit with Provider Pattern in Flutter
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
Hello everyone,
In this article, we will develop a login screen with Huawei’s account kit. We will be using the provider pattern which is one of the most preferred patterns in Flutter. In the end, our demo application will look like below.
Demo Application
HMS Account Kit
Apps with HUAWEI Account Kit allow users to sign in using their HUAWEI IDs with just a tap. By integrating, you can attract new users, by leveraging the enormous HUAWEI ID user base. Account Kit complies with international standards and protocols such as OAuth2.0 and OpenID Connect. It supports two-factor authentication(password authentication and mobile number authentication) to ensure high security. For a detailed explanation please refer to the documentation.
Provider Pattern
Provider pattern is a simple app state management. The idea behind it is that you have a central store or data container in the app which is called provider. Once you added your provider, so this data container to a widget, all child widgets of that widget can listen to that provider. It contains some data and notifies observers when a change occurs.
Provider pattern gives us an easy, low boiler-plate way to separate business logic from our widgets in apps. In the demo application, we are going to have a provider that is called LoginProvider and we will have all the required methods over there. From the other widgets in the app, we will be able to reach the methods and data of it.
Integration Preparations
First of all, you need to register as a HUAWEI developer and verify your identity. Please refer to the link for details. After that, you need to integrate the HUAWEI HMS Core into your application.
Software Requirements
Android Studio 3.X or later
JDK 1.8 or later
SDK Platform 19 or later
Gradle 4.6 or later
The integration flow will be like this :
For a detailed HMS core integration process, you can refer to Preparations for Integrating HUAWEI HMS Core.
Please make sure that you have enabled the Account Kit in Manage APIs section on AppGallery Connect.
Click to expand...
Click to collapse
Implementation
On your Flutter project directory, open pubspec.yaml file and add the dependencies for Account kit and Provider package. In order to show toast messages on user login and logout actions, I have also added fluttertoast package as well.
Code:
dependencies:
flutter:
sdk: flutter
huawei_account: ^5.0.0+300
provider: ^4.3.2+2
fluttertoast: ^7.1.1
Login Provider
In Login provider, we have all the required methods to manage Account actions like sign in, sign out, silent sign in, and revoke authorization. It gives us the flexibility to use any of these methods wherever we desire in the application.
Code:
class LoginProvider with ChangeNotifier {
User _user = new User();
User get getUser {
return _user;
}
void signIn() async {
AuthParamHelper authParamHelper = new AuthParamHelper();
authParamHelper
..setIdToken()
..setAuthorizationCode()
..setAccessToken()
..setProfile()
..setEmail()
..setId()
..addToScopeList([Scope.openId])
..setRequestCode(8888);
try {
final AuthHuaweiId accountInfo = await HmsAccount.signIn(authParamHelper);
_user.id = accountInfo.unionId;
_user.displayName = accountInfo.displayName;
_user.email = accountInfo.email;
_user.profilePhotoUrl = accountInfo.avatarUriString;
notifyListeners();
showToast('Welcome ${_user.displayName}');
} on Exception catch (exception) {
print(exception.toString());
}
}
Future signOut() async {
final signOutResult = await HmsAccount.signOut();
if (signOutResult) {
_user.id = null;
notifyListeners();
showToast('Signed out');
} else {
print('Login_provider:signOut failed');
}
}
void silentSignIn() async {
AuthParamHelper authParamHelper = new AuthParamHelper();
try {
final AuthHuaweiId accountInfo =
await HmsAccount.silentSignIn(authParamHelper);
if (accountInfo.unionId != null) {
_user.id = accountInfo.unionId;
_user.displayName = accountInfo.displayName;
_user.profilePhotoUrl = accountInfo.avatarUriString;
_user.email = accountInfo.email;
notifyListeners();
showToast('Welcome ${_user.displayName}');
}
} on Exception catch (exception) {
print(exception.toString());
print('Login_provider:Can not SignIn silently');
}
}
Future revokeAuthorization() async {
final bool revokeResult = await HmsAccount.revokeAuthorization();
if (revokeResult) {
print('Login_provider:Revoked Auth Successfully');
} else {
print('Login_provider:Failed to Revoked Auth');
}
}
void showToast(String message) {
Fluttertoast.showToast(
msg: message,
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
timeInSecForIosWeb: 1,
backgroundColor: Colors.grey,
textColor: Colors.black,
fontSize: 16.0);
}
}
Login Screen
On the login screen page, we are going to try if we can sign in silently first. If the revoke authorization method was not called, then the app will sign in silently and will not ask for user permissions. So that the application’s login screen will be skipped and the profile page will appear on the screen. If the user clicked the button that is called signout, then we call both sign-out and revoke authorization methods of the Account kit in our use case here. As a result, the user will be redirected to the login screen.
Code:
class LoginScreen extends StatelessWidget {
static const routeName = '/login-screen';
@override
Widget build(BuildContext context) {
final loginProvider = Provider.of<LoginProvider>(context, listen: false);
loginProvider.silentSignIn();
return Consumer<LoginProvider>(
builder: (context, data, _) {
return data.getUser.id != null
? ProfileScreen()
: LoginWidget(loginProvider: loginProvider);
},
);
}
}
class LoginWidget extends StatelessWidget {
const LoginWidget({
Key key,
@required this.loginProvider,
}) : super(key: key);
final LoginProvider loginProvider;
@override
Widget build(BuildContext context) {
var screenSize = MediaQuery.of(context).size;
return Scaffold(
body: Stack(
children: [
Image.asset(
'assets/images/welcome.png',
fit: BoxFit.cover,
height: double.infinity,
width: double.infinity,
alignment: Alignment.center,
),
Container(
alignment: Alignment.bottomCenter,
padding: EdgeInsets.only(bottom: screenSize.height / 6),
child: HuaweiIdAuthButton(
onPressed: () {
loginProvider.signIn();
},
buttonColor: AuthButtonBackground.BLACK,
borderRadius: AuthButtonRadius.MEDIUM,
),
)
],
),
);
}
}
Profile Screen
On the profile screen page, we are taking advantage of the provider pattern. We reach out to the data related to the user and the methods that are required to sign out through the login provider.
Code:
class ProfileScreen extends StatelessWidget {
static const routeName = '/profile-screen';
@override
Widget build(BuildContext context) {
final loginProvider = Provider.of<LoginProvider>(context, listen: false);
final _user = Provider.of<LoginProvider>(context).getUser;
return Scaffold(
appBar: AppBar(
title: Text('Profile'),
backgroundColor: Colors.black45,
),
body: Column(
children: [
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SafeArea(
child: Row(
children: [
_buildCircleAvatar(_user.profilePhotoUrl),
_userInformationText(_user.displayName, _user.email),
],
),
),
Divider(
color: Colors.black26,
height: 50,
),
],
),
OutlineButton.icon(
textColor: Colors.black54,
onPressed: () {
loginProvider.signOut().then((value) {
loginProvider.revokeAuthorization().then((value) =>
Navigator.of(context)
.pushReplacementNamed(LoginScreen.routeName));
});
},
icon: Icon(Icons.exit_to_app_sharp, color: Colors.black54),
label: Text("Log out"),
)
],
),
);
}
}
Widget _buildCircleAvatar(String photoUrl) {
return Padding(
padding: const EdgeInsets.only(
left: 10,
top: 30,
),
child: Container(
width: 100,
height: 100,
decoration: BoxDecoration(
border: Border.all(color: Colors.white, width: 3),
shape: BoxShape.circle,
color: Colors.white,
image: DecorationImage(
fit: BoxFit.cover,
image: photoUrl == null
? AssetImage('assets/images/profile_circle_avatar.png')
: NetworkImage(photoUrl),
),
),
),
);
}
Widget _userInformationText(String name, String email) {
return Padding(
padding: const EdgeInsets.only(left: 15.0, top: 15),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
name,
style: TextStyle(
fontSize: 15.0,
letterSpacing: 1,
fontWeight: FontWeight.w600,
),
),
SizedBox(
height: 3,
),
email == null
? Text('')
: Text(
email,
style: TextStyle(
color: Colors.grey,
fontSize: 12.0,
letterSpacing: 1,
fontWeight: FontWeight.w600,
),
),
],
),
);
}
You can find the source code of the demo app here.
In this article, we have developed a sample application of the HUAWEI Account Kit with Provider pattern in Flutter. I hope this article makes it easier for you to integrate Account Kit into your Flutter projects.
RESOURCES
Account Kit Service
Hi, Well explained User profile image URL is not there in plugin what is the do you have anyidea
sujith.e said:
Hi, Well explained User profile image URL is not there in plugin what is the do you have anyidea
Click to expand...
Click to collapse
Hi, there are two options for profile photo. The first one is that, if the user signed in, then the Account kit gives us the avatarUriString and we can use it to show the profile photo. For the second situation that we don't have the user info, we can use a default photo which is in this case under the assets folder. We need to modify pubspec.yaml for that purpose. You can examine the source code for a better understanding of it.
Regards.
Hi, Does the silent sign in asks for security code for first time login ?

Integrating Huawei Account, Banner and Splash Ads in Flutter StoryApp

{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
Introduction
In this article, we will be integrating Huawei Account, Banner and Splash Ads kit in Flutter StoryApp. Flutter plugin provides simple and convenient way to experience authorization of users. Flutter Account Plugin allows users to connect to the Huawei ecosystem using their Huawei IDs from the different devices such as mobiles phones and tablets, added users can login quickly and conveniently sign in to apps with their Huawei IDs after granting initial access permission.
Huawei Ads kit provides access to range of development capabilities. You can promote your apps quickly and more efficiently to Huawei’s vast users. Ads kit helps your app to monetize quickly and start generating revenue.
Huawei supports following Ads
Banner
Interstitial
Native
Reward
Splash
Instream(Roll)
Development Overview
You need to install Flutter and Dart plugin in IDE and I assume that you have prior knowledge about the Flutter and Dart.
Hardware Requirements
A computer (desktop or laptop) running Windows 10.
A Huawei phone (with the USB cable), which is used for debugging.
Software Requirements
Java JDK 1.7 or later.
Android studio software or Visual Studio or Code installed.
HMS Core (APK) 4.X or later.
Integration process
Step 1: Create Flutter project.
Step 2: Add the App level gradle dependencies.
Choose inside project Android > app > build.gradle.
[/B]
[CODE]apply plugin: 'com.android.application'
apply plugin: 'com.huawei.agconnect'[/CODE]
[B]Root level gradle [/B]dependencies
[CODE]maven {url 'https://developer.huawei.com/repo/'}
classpath 'com.huawei.agconnect:agcp:1.4.1.300'[/CODE]
[B]
Step 3: Add the below permissions in Android Manifest file.
Code:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="com.huawei.appmarket.service.commondata.permission.GET_COMMON_DATA"/>
Step 4: Download flutter plugins
Step 5: Add downloaded file into parent directory of the project. Declare plugin path in pubspec.yaml file under dependencies.
Add path location for asset image.
Let's start coding
loginScreen.dart
Code:
class LoginScreen extends StatelessWidget {
const LoginScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: LoginDemo(),
);
}
}
class LoginDemo extends StatefulWidget {
@override
_LoginDemoState createState() => _LoginDemoState();
}
class _LoginDemoState extends State<LoginDemo> {
final HMSAnalytics _hmsAnalytics = new HMSAnalytics();
@override
void initState() {
HwAds.init();
showSplashAd();
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
title: Text("Login Page"),
backgroundColor: Colors.grey[850],
),
body: RefreshIndicator(
onRefresh: showToast,
child: SingleChildScrollView(
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 60.0),
child: Center(
child: Container(
width: 200,
height: 150,
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(60.0)),
child: Image.asset('images/logo_huawei.png')),
),
),
Padding(
padding: EdgeInsets.symmetric(horizontal: 15),
child: TextField(
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Email',
hintText: 'Enter valid email id '),
),
),
Padding(
padding: const EdgeInsets.only(
left: 15.0, right: 15.0, top: 15, bottom: 0),
child: TextField(
obscureText: true,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Password',
hintText: 'Enter password'),
),
),
FlatButton(
onPressed: () {
//TODO FORGOT PASSWORD SCREEN GOES HERE
},
child: Text(
'Forgot Password',
style: TextStyle(color: Colors.blue, fontSize: 15),
),
),
Container(
height: 50,
width: 270,
decoration: BoxDecoration(
color: Colors.red, borderRadius: BorderRadius.circular(20)),
child: FlatButton(
onPressed: () async {
try {
try {
final bool result = await AccountAuthService.signOut();
if (result) {
final bool response =
await AccountAuthService.cancelAuthorization();
}
} on Exception catch (e) {
print(e.toString());
}
} on Exception catch (e) {
print(e.toString());
}
},
child: GestureDetector(
onTap: () async {
try {
final bool response =
await AccountAuthService.cancelAuthorization();
} on Exception catch (e) {
print(e.toString());
}
},
child: Text(
'Login',
style: TextStyle(color: Colors.white, fontSize: 25),
),
),
),
),
SizedBox(
height: 5,
),
Container(
height: 50,
width: 270,
decoration: BoxDecoration(
color: Colors.red, borderRadius: BorderRadius.circular(20)),
child: HuaweiIdAuthButton(
theme: AuthButtonTheme.FULL_TITLE,
buttonColor: AuthButtonBackground.RED,
borderRadius: AuthButtonRadius.MEDIUM,
onPressed: () {
signInWithHuaweiAccount();
}),
),
SizedBox(
height: 30,
),
GestureDetector(
onTap: () {
//showBannerAd();
},
child: Text('New User? Create Account'),
),
],
),
),
),
);
}
void signInWithHuaweiAccount() async {
AccountAuthParamsHelper helper = new AccountAuthParamsHelper();
helper.setAuthorizationCode();
try {
// The sign-in is successful, and the user's ID information and authorization code are obtained.
Future<AuthAccount> account = AccountAuthService.signIn(helper);
account.then((value) => Fluttertoast.showToast(
msg: "Welcome " + value.displayName.toString(),
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
timeInSecForIosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 16.0));
Navigator.push(
context, MaterialPageRoute(builder: (_) => StoryListScreen()));
} on Exception catch (e) {
print(e.toString());
}
}
Future<void> showToast() async {
Fluttertoast.showToast(
msg: "Refreshing.. ",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
timeInSecForIosWeb: 1,
backgroundColor: Colors.lightBlue,
textColor: Colors.white,
fontSize: 16.0);
}
//Show Splash Ad
void showSplashAd() {
SplashAd _splashAd = createSplashAd();
_splashAd
..loadAd(
adSlotId: "testq6zq98hecj",
orientation: SplashAdOrientation.portrait,
adParam: AdParam(),
topMargin: 20);
Future.delayed(Duration(seconds: 10), () {
_splashAd.destroy();
});
}
SplashAd createSplashAd() {
SplashAd _splashAd = new SplashAd(
adType: SplashAdType.above,
ownerText: ' Huawei SplashAd',
footerText: 'Test SplashAd',
); // Splash Ad
return _splashAd;
}
}
storyListScreen.dart
Code:
class StoryListScreen extends StatefulWidget {
@override
_StoryListScreenState createState() => _StoryListScreenState();
}
class _StoryListScreenState extends State<StoryListScreen> {
final _itemExtent = 56.0;
final generatedList = List.generate(22, (index) => 'Item $index');
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Stories'),
),
backgroundColor: Colors.white,
body: CustomScrollView(
controller: ScrollController(initialScrollOffset: _itemExtent * 401),
slivers: [
SliverFixedExtentList(
itemExtent: _itemExtent,
delegate: SliverChildBuilderDelegate(
(context, index) => Card(
margin: EdgeInsets.only(left: 12, right: 12, top: 5, bottom: 5),
child: Center(
child: GestureDetector(
onTap: () {
showStory(index);
},
child: ListTile(
title: Text(
storyTitles[index],
style: TextStyle(
fontSize: 22.0, fontWeight: FontWeight.bold),
),
),
),
),
),
childCount: storyTitles.length,
),
),
],
),
);
}
void showStory(int index) {
print(storyTitles[index] + " Index :" + index.toString());
Navigator.push(
context, MaterialPageRoute(builder: (_) => StoryDetails(index)));
}
}
storyDetails.dart
Code:
class StoryDetails extends StatefulWidget {
int index;
StoryDetails(this.index);
@override
_StoryDetailsState createState() => new _StoryDetailsState(index);
}
class _StoryDetailsState extends State<StoryDetails> {
int index;
BannerAd? _bannerAd = null;
_StoryDetailsState(this.index);
@override
void initState() {
// TODO: implement initState
super.initState();
showBannerAd();
}
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: _onBackPressed,
child: Scaffold(
appBar: AppBar(
title: Text(storyTitles[index]),
),
backgroundColor: Colors.white,
body: SafeArea(
child: SingleChildScrollView(
child: Padding(
padding: EdgeInsets.only(left: 5, right: 5, top: 3, bottom: 50),
child: Column(children: <Widget>[
Card(
child: Image.asset(
"images/image_0" + index.toString() + ".png"),
),
Card(
child: Text(
storyDetails[index],
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.normal,
fontSize: 20),
)),
Center(
child: Image.asset(
"images/greeting.gif",
height: 320.0,
width: 620.0,
),
),
]),
),
),
)),
);
}
void showBannerAd() {
_bannerAd = createBannerAd();
_bannerAd!
..loadAd()
..show(gravity: Gravity.bottom, offset: 1);
}
//Create BannerAd
static BannerAd createBannerAd() {
BannerAd banner = BannerAd(
adSlotId: "testw6vs28auh3",
size: BannerAdSize.sSmart,
adParam: AdParam());
banner.setAdListener = (AdEvent event, {int? errorCode}) {
print("Banner Ad event : $event " + banner.id.toString());
};
return banner;
}
Future<bool> _onBackPressed() async {
if (_bannerAd != null) {
_bannerAd?.destroy();
}
return true;
}
}
Result
Tricks and Tips
Make sure that downloaded plugin is unzipped in parent directory of project.
Makes sure that agconnect-services.json file added.
Make sure dependencies are added yaml file.
Run flutter pug get after adding dependencies.
Make sure that service is enabled in agc.
Makes sure images are defined in yaml file.
Conclusion
we have learnt how to integrate Huawei Account kit and Huawei Banner and Splash Ads in Flutter StoryApp. Once Account kit integrated, users can login quickly and conveniently sign in to apps with their Huawei IDs after granting initial access permission. Banner and Splash Ads helps you to monetize your StoryApp.
Thank you so much for reading, and also I would like to 'thanks author for write-ups'. I hope this article helps you to understand the integration of Huawei Account kit, Huawei Banner and Splash Ads in flutter StoryApp.
Reference
Ads Kit
StoryAuthors: https://momlovesbest.com/short-moral-stories-kids
Ads Kit – Training Video
Account Kit – Training Video
Checkout in forum

Integration of Huawei ML Kit Text To Speech [TTS] - Listen to your story in Flutter StoryApp

{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
Introduction
In this article, we will be integrating Huawei ML kit in Flutter StoryApp to listen stories using ML kit Text To Speech (TTS). ML Kit provides diversified leading machine learning capabilities that are easy to use, helping you to develop various AI apps. ML Kit allows your apps to easily leverage Huawei's long-term proven expertise in machine learning to support diverse artificial intelligence (AI) applications throughout a wide range of industries.
In this flutter sample application, we are using Language/Voice-related services, services are as follows.
Real-time translation: Translates text from the source language into the target language through the server on the cloud.
On-device translation: Translates text from the source language into the target language with the support of an on-device model, even when no Internet service is available.
Real-time language detection: Detects the language of text online. Both single-language text and multi-language text are supported.
On-device language detection: Detects the language of text without Internet connection. Both single-language text and multi-language text are supported.
Automatic speech recognition: Converts speech (no longer than 60 seconds) into text in real time.
Automatic speech recognition: Converts speech (no longer than 60 seconds) into text in real time.
Text to speech: Converts text information into audio output online in real time. Rich timbres, and volume and speed options are supported to produce more natural sounds.
On-device text to speech: Converts text information into speech with the support of an on-device model, even when there is no Internet connection.
Audio file transcription: Converts an audio file (no longer than 5 hours) into text. The generated text contains punctuation and timestamps. Currently, the service supports Chinese and English.
Real-time transcription: Converts speech (no longer than 5 hours) into text in real time. The generated text contains punctuation and timestamps.
Sound detection: Detects sound events in online (real-time recording) mode. The detected sound events can help you perform subsequent actions.
Supported Devices
Development Overview
You need to install Flutter and Dart plugin in IDE and I assume that you have prior knowledge about the Flutter and Dart.
Hardware Requirements
A computer (desktop or laptop) running Windows 10.
Android phone (with the USB cable), which is used for debugging.
Software Requirements
Java JDK 1.7 or later.
Android studio software or Visual Studio or Code installed.
HMS Core (APK) 4.X or later.
Integration process
Step 1: Create Flutter project.
Step 2: Add the App level gradle dependencies.
Choose inside project Android > app > build.gradle.
[/B]
apply plugin: 'com.android.application'
apply plugin: 'com.huawei.agconnect'
[B]
Root level gradle dependencies
[/B]
maven {url 'https://developer.huawei.com/repo/'}
classpath 'com.huawei.agconnect:agcp:1.4.1.300'
[B]
Step 3: Add the below permissions in Android Manifest file.
[/B]
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
[B]
Step 4: Download flutter plugins
Step 5: Add downloaded file into parent directory of the project. Declare plugin path in pubspec.yaml file under dependencies. Add path location for asset image.
Let's start coding
loginScreen.dart
[/B][/B]
class LoginScreen extends StatelessWidget {
const LoginScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: LoginDemo(),
);
}
}
class LoginDemo extends StatefulWidget {
@override
_LoginDemoState createState() => _LoginDemoState();
}
class _LoginDemoState extends State<LoginDemo> {
final HMSAnalytics _hmsAnalytics = new HMSAnalytics();
@override
void initState() {
HwAds.init();
showSplashAd();
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
title: Text("Login Page"),
backgroundColor: Colors.grey[850],
),
body: RefreshIndicator(
onRefresh: showToast,
child: SingleChildScrollView(
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 60.0),
child: Center(
child: Container(
width: 200,
height: 150,
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(60.0)),
child: Image.asset('images/logo_huawei.png')),
),
),
Padding(
padding: EdgeInsets.symmetric(horizontal: 15),
child: TextField(
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Email',
hintText: 'Enter valid email id '),
),
),
Padding(
padding: const EdgeInsets.only(
left: 15.0, right: 15.0, top: 15, bottom: 0),
child: TextField(
obscureText: true,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Password',
hintText: 'Enter password'),
),
),
FlatButton(
onPressed: () {
//TODO FORGOT PASSWORD SCREEN GOES HERE
},
child: Text(
'Forgot Password',
style: TextStyle(color: Colors.blue, fontSize: 15),
),
),
Container(
height: 50,
width: 270,
decoration: BoxDecoration(
color: Colors.red, borderRadius: BorderRadius.circular(20)),
child: FlatButton(
onPressed: () async {
try {
try {
final bool result = await AccountAuthService.signOut();
if (result) {
final bool response =
await AccountAuthService.cancelAuthorization();
}
} on Exception catch (e) {
print(e.toString());
}
} on Exception catch (e) {
print(e.toString());
}
},
child: GestureDetector(
onTap: () async {
try {
final bool response =
await AccountAuthService.cancelAuthorization();
} on Exception catch (e) {
print(e.toString());
}
},
child: Text(
'Login',
style: TextStyle(color: Colors.white, fontSize: 25),
),
),
),
),
SizedBox(
height: 5,
),
Container(
height: 50,
width: 270,
decoration: BoxDecoration(
color: Colors.red, borderRadius: BorderRadius.circular(20)),
child: HuaweiIdAuthButton(
theme: AuthButtonTheme.FULL_TITLE,
buttonColor: AuthButtonBackground.RED,
borderRadius: AuthButtonRadius.MEDIUM,
onPressed: () {
signInWithHuaweiAccount();
}),
),
SizedBox(
height: 30,
),
GestureDetector(
onTap: () {
//showBannerAd();
},
child: Text('New User? Create Account'),
),
],
),
),
),
);
}
void signInWithHuaweiAccount() async {
AccountAuthParamsHelper helper = new AccountAuthParamsHelper();
helper.setAuthorizationCode();
try {
// The sign-in is successful, and the user's ID information and authorization code are obtained.
Future<AuthAccount> account = AccountAuthService.signIn(helper);
account.then((value) => Fluttertoast.showToast(
msg: "Welcome " + value.displayName.toString(),
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
timeInSecForIosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 16.0));
Navigator.push(
context, MaterialPageRoute(builder: (_) => StoryListScreen()));
} on Exception catch (e) {
print(e.toString());
}
}
Future<void> showToast() async {
Fluttertoast.showToast(
msg: "Refreshing.. ",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
timeInSecForIosWeb: 1,
backgroundColor: Colors.lightBlue,
textColor: Colors.white,
fontSize: 16.0);
}
//Show Splash Ad
void showSplashAd() {
SplashAd _splashAd = createSplashAd();
_splashAd
..loadAd(
adSlotId: "testq6zq98hecj",
orientation: SplashAdOrientation.portrait,
adParam: AdParam(),
topMargin: 20);
Future.delayed(Duration(seconds: 10), () {
_splashAd.destroy();
});
}
SplashAd createSplashAd() {
SplashAd _splashAd = new SplashAd(
adType: SplashAdType.above,
ownerText: ' Huawei SplashAd',
footerText: 'Test SplashAd',
); // Splash Ad
return _splashAd;
}
}
[B][B]
storyListScreen.dart
[/B][/B][/B]
class StoryListScreen extends StatefulWidget {
@override
_StoryListScreenState createState() => _StoryListScreenState();
}
class _StoryListScreenState extends State<StoryListScreen> {
final _itemExtent = 56.0;
final generatedList = List.generate(22, (index) => 'Item $index');
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Stories'),
),
backgroundColor: Colors.white,
body: CustomScrollView(
controller: ScrollController(initialScrollOffset: _itemExtent * 401),
slivers: [
SliverFixedExtentList(
itemExtent: _itemExtent,
delegate: SliverChildBuilderDelegate(
(context, index) => Card(
margin: EdgeInsets.only(left: 12, right: 12, top: 5, bottom: 5),
child: Center(
child: GestureDetector(
onTap: () {
showStory(index);
},
child: ListTile(
title: Text(
storyTitles[index],
style: TextStyle(
fontSize: 22.0, fontWeight: FontWeight.bold),
),
),
),
),
),
childCount: storyTitles.length,
),
),
],
),
);
}
void showStory(int index) {
print(storyTitles[index] + " Index :" + index.toString());
Navigator.push(
context, MaterialPageRoute(builder: (_) => StoryDetails(index)));
}
}
[B][B][B]
storyDetails.dart
[/B][/B][/B][/B]
class StoryDetails extends StatefulWidget {
int index;
StoryDetails(this.index);
@override
_StoryDetailsState createState() => new _StoryDetailsState(index);
}
class _StoryDetailsState extends State<StoryDetails> {
int index = 0;
MLTtsEngine? engine = null;
bool toggle = false;
BannerAd? _bannerAd = null;
bool isPaused = false;
_StoryDetailsState(this.index);
@override
void initState() {
// TODO: implement initState
initML();
showBannerAd();
super.initState();
}
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: _onBackPressed,
child: Scaffold(
appBar: AppBar(
title: Text(storyTitles[index]),
actions: <Widget>[
IconButton(
icon: toggle
? Icon(Icons.pause_circle_filled_outlined)
: Icon(
Icons.play_circle_fill_outlined,
),
onPressed: () {
setState(() {
// Here we changing the icon.
toggle = !toggle;
if (toggle) {
if (!isPaused) {
// do something
print("......Play.....");
final stream = storyDetails[index].splitStream(
chunkSize: 499,
splitters: [','],
delimiters: [r'\'],
);
play(stream);
} else {
MLTtsEngine().resume();
isPaused = false;
}
} else {
isPaused = true;
MLTtsEngine().pause();
}
});
}),
],
),
backgroundColor: Colors.white,
body: SafeArea(
child: SingleChildScrollView(
child: Padding(
padding: EdgeInsets.only(left: 5, right: 5, top: 3, bottom: 50),
child: Column(children: <Widget>[
Card(
child: Image.asset(
"images/image_0" + index.toString() + ".png"),
),
Card(
child: Text(
storyDetails[index],
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.normal,
fontSize: 20),
)),
Center(
child: Image.asset(
"images/greeting.gif",
height: 320.0,
width: 620.0,
),
),
]),
),
),
)),
);
}
void showBannerAd() {
_bannerAd = createBannerAd();
_bannerAd!
..loadAd()
..show(gravity: Gravity.bottom, offset: 1);
}
//Create BannerAd
static BannerAd createBannerAd() {
BannerAd banner = BannerAd(
adSlotId: "testw6vs28auh3",
size: BannerAdSize.sSmart,
adParam: AdParam());
banner.setAdListener = (AdEvent event, {int? errorCode}) {
print("Banner Ad event : $event " + banner.id.toString());
};
return banner;
}
Future<bool> _onBackPressed() async {
if (_bannerAd != null) {
_bannerAd?.destroy();
}
if (engine != null) {
engine!.stop();
}
return true;
}
Future<void> playStory(String parts) async {
// Create MLTtsConfig to configure the speech.
final config = MLTtsConfig(
language: MLTtsConstants.TTS_EN_US,
synthesizeMode: MLTtsConstants.TTS_ONLINE_MODE,
text: parts,
);
// Create an MLTtsEngine object.
engine = new MLTtsEngine();
// Set a listener to track tts events.
engine?.setTtsCallback(MLTtsCallback(
onError: _onError,
onEvent: _onEvent,
onAudioAvailable: _onAudioAvailable,
onRangeStart: _onRangeStart,
onWarn: _onWarn,
));
// Start the speech.
await engine?.speak(config);
}
void _onError(String taskId, MLTtsError err) {
print(err.errorMsg);
}
void _onEvent(String taskId, int eventId) {
}
void _onAudioAvailable(
String taskId, MLTtsAudioFragment audioFragment, int offset) {
}
void _onRangeStart(String taskId, int start, int end) {
}
void _onWarn(String taskId, MLTtsWarn warn) {
}
Future<void> initML() async {
MLLanguageApp().setApiKey(
"DAED8900[p0-tu7au4ZHZuWDrR7oKps/WybCAJ0IOi7UdLfIlsIu9C4pEw0OSNA==");
}
Future<void> play(Stream<List<String>> stream) async {
int i = 0;
await for (List<String> parts in stream) {
// print(parts);
if (i == 0) {
playStory(parts.toString());
}
i++;
}
}
}
[B][B][B][B]
Result
Tricks and Tips
Make sure that downloaded plugin is unzipped in parent directory of project.
Makes sure that agconnect-services.json file added.
Make sure dependencies are added yaml file.
Run flutter pug get after adding dependencies.
Make sure that service is enabled in agc.
Makes sure images are defined in yaml file.
Make sure that permissions are added in Manifest file.
Conclusion
In this article, we have learnt how to integrate Huawei ML kit Text to Speech in Flutter StoryApp. It supports maximum of 500 character for one request to convert Text to Speech. Once Account kit integrated, users can login quickly and conveniently sign in to apps with their Huawei IDs after granting initial access permission. Banner and Splash Ads helps you to monetize your StoryApp.
Thank you so much for reading, and also I would like to ‘thanks author for write-ups’. I hope this article helps you to understand the integration of Huawei ML Kit, Banner and Splash Ads in flutter StoryApp.
Reference
ML Kit Text To Speech
StoryAuthors : https://momlovesbest.com/short-moral-stories-kids
Account Kit – Training Video
ML Kit – Training Video
Checkout in forum

Integration of Huawei Account kit and Analytics kit in Flutter DietApp – Part 1

{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
Introduction
In this article, we will be integrating Huawei Account and Analytics kit in Flutter DietApp. Flutter plugin provides simple and convenient way to experience authorization of users. Flutter Account Plugin allows users to connect to the Huawei ecosystem using their Huawei IDs from the different devices such as mobiles phones and tablets, added users can login quickly and conveniently sign in to apps with their Huawei IDs after granting initial access permission.
Huawei Analytics is a one-stop solution to get user behavior analysis in different platforms for all yours products such as mobile apps, web apps and quick apps. It helps developers to get detailed analysis report and also provides crash reports by default. It offers scenario-specific data collection, management, analysis, and usage, helping enterprises to achieve effective user acquisition, product optimization, precise operations, and business growth.
Development Overview
You need to install Flutter and Dart plugin in IDE and I assume that you have prior knowledge about the Flutter and Dart.
Hardware Requirements
A computer (desktop or laptop) running Windows 10.
Android phone (with the USB cable), which is used for debugging.
Software Requirements
Java JDK 1.7 or later.
Android studio software or Visual Studio or Code installed.
HMS Core (APK) 4.X or later.
Integration process
Step 1: Create Flutter project.
Step 2: Add the App level gradle dependencies. Choose inside project Android > app > build.gradle.
[/B][/B]
apply plugin: 'com.android.application'
apply plugin: 'com.huawei.agconnect'
[B][B]
Root level gradle dependencies
[/B][/B]
maven {url 'https://developer.huawei.com/repo/'}
classpath 'com.huawei.agconnect:agcp:1.5.2.300'
[B][B]
Step 3: Add the below permissions in Android Manifest file.
<uses-permission android:name="android.permission.INTERNET" />
Step 4: Download flutter plugins
Step 5: Add downloaded file into parent directory of the project. Declare plugin path in pubspec.yaml file under dependencies.
Add path location for asset image.
Let's start coding
loginScreen.dart
[/B]
class LoginScreen extends StatelessWidget {
const LoginScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: LoginDemo(),
);
}
}
class LoginDemo extends StatefulWidget {
@override
_LoginDemoState createState() => _LoginDemoState();
}
class _LoginDemoState extends State<LoginDemo> {
final HMSAnalytics _hmsAnalytics = new HMSAnalytics();
@override
void initState() {
_enableLog();
super.initState();
}
Future<void> _enableLog() async {
_hmsAnalytics.setUserId("TestUserDietApp");
await _hmsAnalytics.enableLog();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
title: Text("Login"),
backgroundColor: Colors.grey[850],
),
body: RefreshIndicator(
onRefresh: showToast,
child: SingleChildScrollView(
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 90.0),
child: Center(
child: Container(
width: 220,
height: 165,
decoration: BoxDecoration(
color: Colors.black,
borderRadius: BorderRadius.circular(60.0)),
child: Image.asset('images/logo_huawei.png')),
),
),
Padding(
padding: EdgeInsets.only(
left: 40.0, right: 40.0, top: 15, bottom: 0),
child: TextField(
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Email',
hintText: 'Enter valid email id '),
),
),
Padding(
padding: const EdgeInsets.only(
left: 40.0, right: 40.0, top: 10, bottom: 0),
child: TextField(
obscureText: true,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Password',
hintText: 'Enter password'),
),
),
FlatButton(
onPressed: () {
},
child: Text(
'Forgot Password',
style: TextStyle(color: Colors.blue, fontSize: 15),
),
),
Container(
height: 50,
width: 270,
decoration: BoxDecoration(
color: Colors.black,
borderRadius: BorderRadius.circular(20)),
child: FlatButton(
onPressed: () async {
try {
try {
final bool result = await AccountAuthService.signOut();
if (result) {
final bool response =
await AccountAuthService.cancelAuthorization();
}
} on Exception catch (e) {
print(e.toString());
}
} on Exception catch (e) {
print(e.toString());
}
},
child: GestureDetector(
onTap: () async {
try {
final bool response =
await AccountAuthService.cancelAuthorization();
} on Exception catch (e) {
print(e.toString());
}
},
child: Text(
'Login',
style: TextStyle(color: Colors.white, fontSize: 22),
),
),
),
),
SizedBox(
height: 20,
),
Container(
height: 50,
width: 270,
decoration: BoxDecoration(
color: Colors.black,
borderRadius: BorderRadius.circular(5)),
child: HuaweiIdAuthButton(
theme: AuthButtonTheme.FULL_TITLE,
buttonColor: AuthButtonBackground.RED,
borderRadius: AuthButtonRadius.MEDIUM,
onPressed: () {
signInWithHuaweiID();
}),
),
SizedBox(
height: 30,
),
],
),
),
),
);
}
void signInWithHuaweiID() async {
AccountAuthParamsHelper helper = new AccountAuthParamsHelper();
String name = '';
helper.setAuthorizationCode();
try {
Future<AuthAccount> account = AccountAuthService.signIn();
account.then((value) => Navigator.push(
context,
MaterialPageRoute(
builder: (_) => MyHomePage(
title: '' + value.displayName.toString(),
))));
} on Exception catch (e) {
print(e.toString());
}
}
Future<void> showToast() async {
Fluttertoast.showToast(
msg: "Refreshing.. ",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
timeInSecForIosWeb: 1,
backgroundColor: Colors.lightBlue,
textColor: Colors.white,
fontSize: 16.0);
}
}
[B]
main.dart
[/B][/B][/B][/B][/B][/B]
[B][B][B][B]void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Exercise&DietApp',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: SplashScreen(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Wel come ',
),
Text(
widget.title.toString(),
style: Theme.of(context).textTheme.headline4,
),
],
),
),
}
}
[B][B]
Result
Tricks and Tips
Make sure that downloaded plugin is unzipped in parent directory of project.
Makes sure that agconnect-services.json file added.
Make sure dependencies are added yaml file.
Run flutter pug get after adding dependencies.
Make sure that service is enabled in agc.
Makes sure images are defined in yaml file.
Conclusion
In this article, we have learnt how to integrate Huawei Account kit in Flutter DietApp. Once Account kit integrated, users can login quickly and conveniently sign in to apps with their Huawei IDs after granting initial access permission.
Thank you so much for reading. I hope this article helps you to understand the integration of Huawei Account kit, in flutter DietApp.
Reference
Account Kit – Training Video
Checkout in forum

Integration of Huawei Account kit, Remote Configuration, Crash kit and IAP Service in Flutter DietApp – Part 6

{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
Introduction
In this article, we will be integrating Huawei Remote Configuration service, Account Kit, Crash Kit and Huawei IAP Service in Flutter DietApp. Flutter plugin provides simple and convenient way to experience authorization of users. Flutter Account Plugin allows users to connect to the Huawei ecosystem using their Huawei IDs from the different devices such as mobiles phones and tablets, added users can login quickly and conveniently sign in to apps with their Huawei IDs after granting initial access permission.
We will also learn to integrate Huawei Crash Service in this application. It is a responsibility of the developer to build crash free i.e. unexpected exit of application, it is very difficult to find the cause of the crash in huge application code base. This unexpected crash makes app users annoying and may lead to business loss and reduce market value of the product and the company. To avoid such crashes Huawei provides Crash service which makes developer to find the crash and cause of unexpected exit of the application in AG-console.
Crash SDK provides very simple and developer need not code much to implementation crash service. You can also download the detailed crash report whenever required.
Remote Configuration is a service provided by Huawei. It provides cloud-based services. Once you integrate the client SDK, your app can periodically fetch parameter values from the cloud. The service checks whether the parameter that your app tries fetching has an on-cloud value update and returns the new value if so. Based on the parameter values fetched, you can implement service processing logic to change behaviour or appearance of your app. In this sample i.e. DietApp, we are fetching the Personal Exercise data using Remote Configuration service by AppGallery.
Flutter In-App Purchases (IAP) plugin provides communication between the HMS Core IAP SDK and Flutter platform. Huawei IAP allows you to offer in-app purchases and facilitates in-app payment. Users can purchase a variety of virtual products, including one-time virtual products and subscriptions, directly within your app.
Flutter IAP plugin provides the following APIs, which are also core capabilities you need to quickly build apps with which your users can buy, consume, and subscribe to services you provide:
isEnvReady: Returns a response which indicates user's sign-in and location status for HUAWEI IAP.
isSandboxActivated: Returns a response which indicates user's account capabilities for sandbox testing.
obtainProductInfo: Returns a list of products.
startIapActivity: Starts an activity to manage and edit subscriptions.
createPurchaseIntent: Starts an activity to purchase a desired product or subscribe to a product.
consumeOwnedPurchase: Consumes a desired product.
obtainOwnedPurchases: Returns the list of products purchased by a user.
obtainOwnedPurchaseRecord: Returns the list of products purchased and consumed by a user.
Previous article
Please check my previous articles, if you have not gone through, click on part-5.
Development Overview
You need to install Flutter and Dart plugin in IDE and I assume that you have prior knowledge about the Flutter and Dart.
Hardware Requirements
A computer (desktop or laptop) running Windows 10.
Android phone (with the USB cable), which is used for debugging.
Software Requirements
Java JDK 1.7 or later.
Android studio software or Visual Studio or Code installed.
HMS Core (APK) 4.X or later.
Integration process
Step 1: Create Flutter project.
Step 2: Add the App level gradle dependencies. Choose inside project Android > app > build.gradle.
apply plugin: 'com.android.application'
apply plugin: 'com.huawei.agconnect'
Root level gradle dependencies
maven {url 'https://developer.huawei.com/repo/'}
classpath 'com.huawei.agconnect:agcp:1.5.2.300'
Step 3: Add the below permissions in Android Manifest file.
<uses-permission android:name="android.permission.INTERNET" />
Step 4: Download flutter IAP kit plugins
Step 5: Add downloaded file into parent directory of the project. Declare plugin path in pubspec.yaml file under dependencies.
Add path location for asset image.
Let's start coding
SplashScreen.dart
[/B]
class SplashScreen extends StatefulWidget {
@override
_SplashScreenState createState() => _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen> {
@override
void initState() {
super.initState();
Timer(
Duration(seconds: 3),
() => Navigator.pushReplacement(context,
MaterialPageRoute(builder: (context) => const LoginScreen())));
}
@override
Widget build(BuildContext context) {
return Container(
color: Colors.white, child: Image.asset('images/logo_huawei.png'));
}
}
[B]
loginScreen.dart
[/B][/B]
class LoginScreen extends StatelessWidget {
const LoginScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: LoginDemo(),
);
}
}
class LoginDemo extends StatefulWidget {
@override
_LoginDemoState createState() => _LoginDemoState();
}
class _LoginDemoState extends State<LoginDemo> {
final HMSAnalytics _hmsAnalytics = new HMSAnalytics();
@override
void initState() {
_enableLog();
super.initState();
}
Future<void> _enableLog() async {
_hmsAnalytics.setUserId("TestUserDietApp");
await _hmsAnalytics.enableLog();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
title: Text("Login"),
backgroundColor: Colors.blue,
),
body: RefreshIndicator(
onRefresh: showToast,
child: SingleChildScrollView(
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 90.0),
child: Center(
child: Container(
width: 320,
height: 220,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(50.0)),
child: Image.asset('images/logo_huawei.png')),
),
),
Padding(
padding: EdgeInsets.only(
left: 40.0, right: 40.0, top: 15, bottom: 0),
child: TextField(
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Email',
hintText: 'Enter valid email id '),
),
),
Padding(
padding: const EdgeInsets.only(
left: 40.0, right: 40.0, top: 10, bottom: 0),
child: TextField(
obscureText: true,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Password',
hintText: 'Enter password'),
),
),
FlatButton(
onPressed: () {
//TODO FORGOT PASSWORD SCREEN GOES HERE
},
child: Text(
'Forgot Password',
style: TextStyle(color: Colors.blue, fontSize: 15),
),
),
Container(
height: 50,
width: 270,
decoration: BoxDecoration(
color: Colors.red, borderRadius: BorderRadius.circular(20)),
child: FlatButton(
onPressed: () async {
try {
try {
final bool result = await AccountAuthService.signOut();
if (result) {
final bool response =
await AccountAuthService.cancelAuthorization();
}
} on Exception catch (e) {
print(e.toString());
}
} on Exception catch (e) {
print(e.toString());
}
},
child: GestureDetector(
onTap: () async {
try {
final bool response =
await AccountAuthService.cancelAuthorization();
} on Exception catch (e) {
print(e.toString());
}
},
child: Text(
'Login',
style: TextStyle(color: Colors.white, fontSize: 22),
),
),
),
),
SizedBox(
height: 20,
),
Container(
height: 50,
width: 270,
decoration:
BoxDecoration(borderRadius: BorderRadius.circular(5)),
child: HuaweiIdAuthButton(
theme: AuthButtonTheme.FULL_TITLE,
buttonColor: AuthButtonBackground.RED,
borderRadius: AuthButtonRadius.MEDIUM,
onPressed: () {
signInWithHuaweiID();
}),
),
SizedBox(
height: 30,
),
GestureDetector(
onTap: () {
//showBannerAd();
},
child: Text('New User? Create Account'),
),
],
),
),
),
);
}
void signInWithHuaweiID() async {
AccountAuthParamsHelper helper = new AccountAuthParamsHelper();
String name = '';
helper.setAuthorizationCode();
try {
// The sign-in is successful, and the user's ID information and authorization code are obtained.
Future<AuthAccount> account = AccountAuthService.signIn();
account.then(
(value) => Navigator.push(
context,
MaterialPageRoute(
builder: (_) => MyHomePage(
title: value.displayName.toString(),
),
),
),
);
} on Exception catch (e) {
print(e.toString());
}
}
Future<void> showToast() async {
Fluttertoast.showToast(
msg: "Refreshing.. ",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
timeInSecForIosWeb: 1,
backgroundColor: Colors.lightBlue,
textColor: Colors.white,
fontSize: 16.0);
}
}
[B][B]
main.dart
[/B][/B][/B]
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Exercise&DietApp',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: SplashScreen(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
late double? age, height, weight, tagetWeight, days;
TextEditingController ageController = TextEditingController();
TextEditingController genderController = TextEditingController();
TextEditingController heightController = TextEditingController();
TextEditingController weightController = TextEditingController();
TextEditingController targetWeightController = TextEditingController();
TextEditingController inDaysWeightController = TextEditingController();
TextEditingController dietPlanController = TextEditingController();
TextEditingController activeLevelPlanController = TextEditingController();
late SharedPreferences prefs;
String _genderLabel = "Male";
String _dietLabel = "Veg";
String _activeLable = "Low-Active";
final _genderList = ["Male", "Women"];
final _dietPlanList = ["Veg", "Non Veg", "Egg"];
final _activeLevelList = ["Low-Active", "Mid-Active", "Very Active"];
String _token = '';
void initState() {
initPreferences();
initTokenStream();
super.initState();
}
Future<void> initTokenStream() async {
if (!mounted) return;
Push.getTokenStream.listen(_onTokenEvent, onError: _onTokenError);
getToken();
}
void getToken() async {
// Call this method to request for a token
Push.getToken("");
}
void _onTokenEvent(String event) {
// Requested tokens can be obtained here
setState(() {
_token = event;
print("TokenEvent: " + _token);
});
}
void _onTokenError(Object error) {
print("TokenErrorEvent: " + error.toString());
PlatformException? e = error as PlatformException?;
}
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
resizeToAvoidBottomInset: true,
appBar: AppBar(
title: Text(widget.title.toString()),
automaticallyImplyLeading: false,
),
body: Center(
child: SingleChildScrollView(
reverse: true,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 0.0),
child: Center(
child: Container(
width: 120,
height: 120,
decoration: BoxDecoration(
color: Colors.black,
borderRadius: BorderRadius.circular(60.0)),
child: Image.asset('images/nu_icon.png')),
),
),
Padding(
padding: const EdgeInsets.only(
left: 22.0, right: 22.0, top: 15, bottom: 0),
child: TextField(
controller: ageController,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Age',
hintText: 'Enter valid age '),
),
),
Padding(
padding: const EdgeInsets.only(
left: 22.0, right: 22.0, top: 15, bottom: 0),
child: TextField(
controller: heightController,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Height',
hintText: 'Enter height '),
),
),
Padding(
padding: const EdgeInsets.only(
left: 22.0, right: 22.0, top: 15, bottom: 0),
child: TextField(
controller: weightController,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Weight',
hintText: 'Enter Weight '),
),
),
Padding(
padding: const EdgeInsets.only(
left: 22.0, right: 22.0, top: 15, bottom: 0),
child: TextField(
controller: targetWeightController,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Target Weight',
hintText: 'Enter target Weight '),
),
),
Padding(
padding: const EdgeInsets.only(
left: 22.0, right: 22.0, top: 15, bottom: 0),
child: TextField(
controller: inDaysWeightController,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'In days',
hintText: 'How quickly you want loose/gain weight '),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
const Text('Gender :'),
DropdownButton(
items: _genderList
.map((String item) => DropdownMenuItem<String>(
child: SizedBox(
height: 22,
width: 100,
child: Text(item,
style: TextStyle(fontSize: 20))),
value: item))
.toList(),
onChanged: (value) {
setState(() {
_genderLabel = value.toString();
});
},
value: _genderLabel,
)
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text('Diet Plan :'),
DropdownButton(
items: _dietPlanList
.map((String item) => DropdownMenuItem<String>(
child: SizedBox(
height: 22,
width: 100,
child: Text(item,
style: TextStyle(fontSize: 20))),
value: item))
.toList(),
onChanged: (value) {
setState(() {
_dietLabel = value.toString();
print('Diet plan changed to $value');
});
},
value: _dietLabel,
)
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text('Active Level :'),
DropdownButton(
items: _activeLevelList
.map((String item) => DropdownMenuItem<String>(
child: SizedBox(
height: 22,
width: 100,
child: Text(item,
style: TextStyle(fontSize: 20))),
value: item))
.toList(),
onChanged: (value) {
setState(() {
_activeLable = value.toString();
print('Active level changed to $value');
});
},
value: _activeLable,
)
],
)
,
Padding(
padding: const EdgeInsets.only(
left: 22.0, right: 22.0, top: 20, bottom: 0),
child: MaterialButton(
child: const Text(
'Next',
style: TextStyle(
fontSize: 22,
color: Colors.white,
fontWeight: FontWeight.w300),
),
height: 45,
minWidth: 140,
color: Colors.lightBlue,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
onPressed: () {
print('Button clicked.....');
age = double.parse(ageController.text);
height = double.parse(heightController.text);
weight = double.parse(weightController.text);
tagetWeight = double.parse(targetWeightController.text);
days = double.parse(inDaysWeightController.text);
storeDataLocally();
},
),
),
],
),
),
),
),
);
}
Future<void> storeDataLocally() async {
prefs.setString("name", widget.title.toString());
prefs.setDouble("age", age!);
prefs.setDouble("height", height!);
prefs.setString("gender", _genderLabel);
prefs.setDouble("weight", weight!);
prefs.setString("dietPlan", _dietLabel);
prefs.setDouble("targetWeight", tagetWeight!);
prefs.setString("activeLevel", _activeLable);
prefs.setDouble("inDays", days!);
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const DietPlanScreen()),
);
}
Future<void> initPreferences() async {
prefs = await SharedPreferences.getInstance();
showData();
}
void showData() {
print("Gender ===>" + prefs.getString('gender').toString());
print("Diet Plan ===>" + prefs.getString('dietPlan').toString());
print("Active Level ===>" + prefs.getString('activeLevel').toString());
if (prefs.getDouble('age')! > 10) {
ageController.text = prefs.getDouble('age').toString();
heightController.text = prefs.getDouble('height').toString();
targetWeightController.text = prefs.getDouble('targetWeight').toString();
genderController.text = prefs.getString('gender').toString();
dietPlanController.text = prefs.getString('dietPlan').toString();
weightController.text = prefs.getDouble('weight').toString();
inDaysWeightController.text = prefs.getDouble('inDays').toString();
activeLevelPlanController.text =
prefs.getString('activeLevel').toString();
if (prefs.getString('gender').toString() != null &&
prefs.getString('gender').toString() != '') {
_genderLabel = prefs.getString('gender').toString();
}
if (prefs.getString('dietPlan').toString() != null) {
_dietLabel = prefs.getString('dietPlan').toString();
}
if (prefs.getString('activeLevel').toString() != null) {
_activeLable = prefs.getString('activeLevel').toString();
}
}
}
}
[B][B][B]
tabScreen.dart
[/B][/B][/B][/B]
class TabScreen extends StatefulWidget {
@override
TabScreenPage createState() => TabScreenPage();
}
class TabScreenPage extends State<TabScreen> {
final rnd = math.Random();
List<String> gridItems = [];
@override
void initState() {
// TODO: implement initState
fetchRemoteConfiguration();
super.initState();
}
@override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
title: const Text(
'Diet Plan',
),
centerTitle: true,
backgroundColor: Colors.blue,
elevation: 0,
),
body: Column(
children: <Widget>[
// the tab bar with two items
SizedBox(
height: 50,
child: AppBar(
bottom: const TabBar(
tabs: [
Tab(
text: 'Paid Diet Plans',
),
Tab(
text: 'Personal Exercise',
),
],
),
),
),
// create widgets for each tab bar here
Expanded(
child: TabBarView(
children: [
// first tab bar view widget
Container(
color: Colors.white,
child: ListView(
padding: EdgeInsets.all(8),
children: <Widget>[
Card(
child: ListTile(
title: Text("30 days plan"),
iconColor: Colors.blue,
subtitle: Text('Meal Plan: Burn 1,200 Calories'),
leading: Icon(Icons.sports_gymnastics),
onTap: () {
routeScreen('30 days plan');
},
),
),
Card(
child: ListTile(
title: Text("28 days plan"),
iconColor: Colors.blue,
subtitle: Text('Meal Plan: Burn 950 Calories'),
leading: Icon(Icons.sports_gymnastics),
onTap: () {
routeScreen('28 days plan');
},
),
),
Card(
child: ListTile(
title: Text("22 days plan"),
iconColor: Colors.blue,
subtitle: Text('Meal Plan: Burn 850 Calories'),
leading: Icon(Icons.sports_gymnastics),
onTap: () {
routeScreen('22 days plan');
},
),
),
Card(
child: ListTile(
iconColor: Colors.blue,
title: Text("18 days plan"),
subtitle: Text('Meal Plan: Burn 650 Calories'),
leading: Icon(Icons.sports_gymnastics),
onTap: () {
routeScreen('18 days plan');
},
),
),
],
),
),
// second tab bar viiew widget
Container(
color: Colors.white,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: GridView.builder(
gridDelegate:
const SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 200,
childAspectRatio: 3 / 3,
crossAxisSpacing: 20,
mainAxisSpacing: 20),
itemCount: gridItems.length,
itemBuilder: (BuildContext ctx, index) {
return Center(
child: GestureDetector(
onTap: () {
print(' ' + gridItems[index]);
checkDeviceEnvirnoment();
//makePayment();
//checkSDK();
},
child: Container(
alignment: Alignment.center,
child: Image.asset('images/image$index.png'),
decoration: BoxDecoration(
color: Colors.primaries[Random()
.nextInt(Colors.primaries.length)],
borderRadius: BorderRadius.circular(15)),
),
),
);
}),
),
),
],
),
),
],
),
),
);
}
void routeScreen(String title) {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => PaidPlanScreen(title)),
);
}
Future<void> fetchRemoteConfiguration() async {
await AGCRemoteConfig.instance
.fetch()
.catchError((error) => print(error.toString()));
await AGCRemoteConfig.instance.applyLastFetched();
Map value = await AGCRemoteConfig.instance.getMergedAll();
final data = jsonDecode(value["categories"].toString());
List<String> gridItem = List<String>.from(data['categories']);
setState(() {
gridItems.addAll(gridItem);
});
}
void checkDeviceEnvirnoment() async {
try {
//Call the isEnvReady API.
IsEnvReadyResult result = await IapClient.isEnvReady();
print('*****');
print(result.returnCode.toString());
//Call isSandboxActivated API.
IsSandboxActivatedResult result1 = await IapClient.isSandboxActivated();
print('####');
//Print the isSandboxUser property.
print(result1.isSandboxUser.toString());
bool? isUser = result1.isSandboxUser;
if (isUser!) {
makePayment();
}
} on Exception catch (_, e) {
print(e.toString());
}
}
void makePayment() async {
try {
//Constructing the request.
PurchaseIntentReq request = PurchaseIntentReq(
productId: '11223344', priceType: IapClient.IN_APP_CONSUMABLE);
request.priceType =
0; //You may also use IN_APP_CONSUMABLE from IapClient's constant values.
request.productId = "11223344";
request.developerPayload = "Test";
//Call the createPurchaseIntent API.
PurchaseResultInfo result = await IapClient.createPurchaseIntent(request);
print(result.inAppPurchaseData.toString());
} on Exception catch (e) {
print(e.toString());
}
}
}
[B][B][B][B]
Result
Using Remote Configuration fetching cloud data and displayed in UI
Before you use any service in AppGallery Console, enable the service first like shown below :
IAP allows three types products to add in AppGallery Console once you click navigate below shown path click add products and choose the desired product type and add details and save, after adding Activate the product then only it will be accessible.
Tricks and Tips
Make sure that downloaded plugin is unzipped in parent directory of project.
Makes sure that agconnect-services.json file added.
Make sure dependencies are added yaml file.
Run flutter pug get after adding dependencies.
Make sure that service is enabled in agc.
Makes sure images are defined in yaml file.
Add products in AppGallery My apps/Operate/Product Management
Conclusion
In this article, we have learnt how to integrate Huawei Remote Configuration service, Account kit, Crash kit flutter DietApp. Once Account kit integrated, users can login quickly and conveniently sign in to apps with their Huawei IDs after granting initial access permission. Push kit enables you to send push notification to user device in real time, you can see the push notification in the result part. Huawei Crash service which provides developers to quickly detect, locate and fix the crash or unexpected exit of application. Hence improves stability and reliability of application. With the help of Remote Configuration service we are fetching the Personal Exercise data from the cloud. Using Huawei IAP we are making payment for access personal exercise.
Thank you so much for reading. I hope this article helps you to understand the integration of Huawei Remote Configuration, Account kit, Huawei IAP and Crash kit in flutter DietApp.
Reference
Crash Kit
Account Kit – Training Video
Crash Kit – Training Video
IAP
Checkout in forum

Categories

Resources