[Huawei Developers] lokeshsuryan:
View attachment 5292109

Introduction

In this article, we will be integrating Huawei Remote Configuration Service in Flutter QuizApp. Here we will fetch the remote data which is questions and answers JSON data from Ag-console. Huawei provides Remote Configuration service to manage parameters online, with this service you can control or change the behaviour and appearance of you app online without requiring user’s interaction or update to app. By implementing the SDK you can fetch the online parameter values delivered on the AG-console to change the app behaviour and appearance.

Functional features

1. Parameter management: This function enables user to add new parameter, delete, update existing parameter and setting conditional values.

2. Condition management: This function enables user to adding, deleting and modifying conditions, and copy and modify existing conditions. Currently, you can set the following conditions version, country/region, audience, user attribute, user percentage, time and language. You can expect more conditions in the future.

3. Version management: This feature function supports user to manage and rollback up to 90 days of 300 historical versions for parameters and conditions.

4. Permission management: This feature function allows account holder, app administrator, R&D personnel, and administrator and operations personals to access Remote Configuration by default.

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

View attachment 5292115

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'

Add root level gradle dependencies

maven {url 'https://developer.huawei.com/repo/'}
classpath 'com.huawei.agconnect:agcp:1.4.1.300'

Add app level gradle dependencies

implementation 'com.huawei.agconnect:agconnect-remoteconfig:1.4.2.301'

Step 3: Add the below permissions in Android Manifest file.

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

Step 4: Add below path in pubspec.yaml file under dependencies.

View attachment 5292127

Step 5 : Create a project in AppGallery Connect

Preparations for Integrating HUAWEI HMS Core(Android)

pubspec.yaml

name: flutter_app
description: A new Flutter application.

# The following line prevents the package from being accidentally published to
# pub.dev using `pub publish`. This is preferred for private packages.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev

# The following defines the version and build number for your application.
# A version number is three numbers separated by dots, like 1.2.43
# followed by an optional build number separated by a +.
# Both the version and the builder number may be overridden in flutter
# build by specifying --build-name and --build-number, respectively.
# In Android, build-name is used as versionName while build-number used as versionCode.
# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 1.0.0+1

environment:
sdk: ">=2.7.0 <3.0.0"

dependencies:
flutter:
sdk: flutter
huawei_account:
path: ../huawei_account/
huawei_analytics:
path: ../huawei_analytics/
huawei_location:
path: ../huawei_location/
huawei_ads:
path: ../huawei_ads/
huawei_push:
path: ../huawei_push
huawei_map:
path: ../huawei_map
huawei_scan:
path: ../huawei_scan
agconnect_crash: ^1.0.0
http: ^0.12.2
fluttertoast: ^7.1.6
agconnect_remote_config: ^1.0.0

# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.2

dev_dependencies:
flutter_test:
sdk: flutter

main.dart

[CODE=java]import 'dart:convert';
import 'dart:developer';
import 'package:agconnect_remote_config/agconnect_remote_config.dart';
import 'package:flutter/material.dart';
import 'package:flutter_app/login.dart';
import 'package:flutter_app/menuscreen.dart';
import 'package:flutter_app/myquestion.dart';
import 'package:flutter_app/result.dart';
import 'package:huawei_account/hmsauthservice/hms_auth_service.dart';
import 'package:huawei_ads/adslite/ad_param.dart';
import 'package:huawei_ads/adslite/banner/banner_ad.dart';
import 'package:huawei_ads/adslite/banner/banner_ad_size.dart';
import 'package:huawei_ads/hms_ads.dart';
import 'package:huawei_analytics/huawei_analytics.dart';
import './quiz.dart';
import './result.dart';
void main() {
runApp(
MaterialApp(
title: 'TechQuizApp',
// Start the app with the "/" named route. In this case, the app starts
// on the FirstScreen widget.
initialRoute: '/',
routes: {
// When navigating to the "/" route, build the FirstScreen widget.
'/': (context) => MenuScreen(),
// When navigating to the "/second" route, build the SecondScreen widget.
'/second': (context) => MyApp('', null),
},
),
);
}
class MyApp extends StatefulWidget {
final String userName;
List<MyQuestion> _questions;
MyApp(this.userName, this._questions);
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return _MyAppState(_questions);
}
}
class _MyAppState extends State<MyApp> {
var _questionIndex = 0;
int _totalScore = 0;
String name;
List<MyQuestion> _questions;

final HMSAnalytics _hmsAnalytics = new HMSAnalytics();
_MyAppState(this._questions);

@override
void initState() {
_enableLog();
_predefinedEvent();
super.initState();
}

Future<void> _enableLog() async {
_hmsAnalytics.setUserId(widget.userName);
await _hmsAnalytics.enableLog();
}

void _restartQuiz() {
setState(() {
_questionIndex = 0;
_totalScore = 0;
});
}
void _logoutQuiz() async {
final signOutResult = await HmsAuthService.signOut();
if (signOutResult) {
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) => LoginDemo()));

print('You are logged out');
} else {
print('signOut failed');
}
}
//Predefined
void _predefinedEvent() async {
String name = HAEventType.SIGNIN;
dynamic value = {HAParamType.ENTRY: 06534797};
await _hmsAnalytics.onEvent(name, value);
print("Event posted");
}
void _customEvent(int index, int score) async {
String name = "Question$index";
dynamic value = {'Score': score};
await _hmsAnalytics.onEvent(name, value);
print("_customEvent posted");
}
Future<void> _answerQuestion(int score) async {
_totalScore += score;
if (_questionIndex < _questions.length) {
print('Iside if $_questionIndex');
setState(() {
_questionIndex = _questionIndex + 1;
});
print('Current questionIndex $_questionIndex');
} else {
print('Inside else $_questionIndex');
}
_customEvent(_questionIndex, score);
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Wel come ' + widget.userName),
),
body: callme2()));
}
}

myqueston.dart

class MyQuestion {
String questionText;
List<Answers> answers;
MyQuestion({this.questionText, this.answers});
MyQuestion.fromJson(Map<String, dynamic> json) {
questionText = json['questionText'];
if (json['answers'] != null) {
answers = new List<Answers>();
json['answers'].forEach((v) {
answers.add(new Answers.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['questionText'] = this.questionText;
if (this.answers != null) {
data['answers'] = this.answers.map((v) => v.toJson()).toList();
}
return data;
}
}
class Answers {
String text;
int score;
Answers({this.text, this.score});
Answers.fromJson(Map<String, dynamic> json) {
text = json['text'];
score = json['Score'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['text'] = this.text;
data['Score'] = this.score;
return data;
}
}

login.dart

import 'dart:async';

import 'dart:convert';

import 'dart:developer';

import 'package:agconnect_remote_config/agconnect_remote_config.dart';

import 'package:flutter/material.dart';

import 'package:flutter_app/main.dart';

import 'package:flutter_app/myquestion.dart';

import 'package:huawei_account/helpers/hms_auth_param_helper.dart';

import 'package:huawei_account/helpers/hms_scope.dart';

import 'package:huawei_account/hmsauthservice/hms_auth_service.dart';

import 'package:huawei_account/model/hms_auth_huawei_id.dart';

class LoginDemo extends StatefulWidget {

@override

_LoginDemoState createState() => _LoginDemoState();

}

class _LoginDemoState extends State<LoginDemo> {

TextEditingController emailController = new TextEditingController();

TextEditingController passwordController = new TextEditingController();

String email, password, user;

List<MyQuestion> _questions;

@override

void initState() {

// TODO: implement initState

fetchAndActivateImmediately();

super.initState();

}

@override

void dispose() {

// Clean up the controller when the widget is disposed.

emailController.dispose();

passwordController.dispose();

super.dispose();

}

@override

Widget build(BuildContext context) {

return MaterialApp(

home: Scaffold(

appBar: AppBar(

title: Text('Account Login'),

),

body: Center(

child: InkWell(

onTap: signInWithHuaweiAccount,

child: Ink.image(

image: AssetImage('assets/images/icon.jpg'),

// fit: BoxFit.cover,

width: 110,

height: 110,

),

),

)),

);

}

void signInWithHuaweiAccount() async {

HmsAuthParamHelper authParamHelper = new HmsAuthParamHelper();

authParamHelper

..setIdToken()

..setAuthorizationCode()

..setAccessToken()

..setProfile()

..setEmail()

..setScopeList([HmsScope.openId, HmsScope.email, HmsScope.profile])

..setRequestCode(8888);

try {

final HmsAuthHuaweiId accountInfo =

await HmsAuthService.signIn(authParamHelper: authParamHelper);

print('accountInfo ==>' + accountInfo.email);

setState(() {

String accountDetails = accountInfo.displayName;

print("account name: " + accountInfo.displayName);

print("accountDetails: " + accountDetails);

user = accountInfo.displayName;

if (_questions != null) {

Navigator.of(context).push(

MaterialPageRoute(builder: (context) => MyApp(user, _questions)));

}

});

} on Exception catch (exception) {

print(exception.toString());

print("error: " + exception.toString());

}

}

Future signOut() async {

final signOutResult = await HmsAuthService.signOut();

if (signOutResult) {

//Route route = MaterialPageRoute(builder: (context) => SignInPage());

// Navigator.pushReplacement(context, route);

print('You are logged out');

} else {

print('Login_provider:signOut failed');

}

}

fetchAndActivateImmediately() async {

await AGCRemoteConfig.instance.fetch().catchError((error) => log(error()));

await AGCRemoteConfig.instance.applyLastFetched();

Map value = await AGCRemoteConfig.instance.getMergedAll();

for (String key in value.keys) {

if (key == 'questions') {

var st = value[key].toString().replaceAll('\\', '');

var myquestionJson = jsonDecode(st) as List;

_questions =

myquestionJson.map((val) => MyQuestion.fromJson(val)).toList();

}

}

print('=================*********************======================');

print(jsonEncode(_questions));

}

}[/CODE]

quiz.dart

import 'package:flutter/material.dart';
import 'package:flutter_app/myquestion.dart';
import './answer.dart';
import './question.dart';
class Quiz extends StatelessWidget {
final List<MyQuestion> questions;
final int questionIndex;
final Function answerQuestion;
Quiz({
@required this.answerQuestion,
@required this.questions,
@required this.questionIndex,
});
@override
Widget build(BuildContext context) {
return Column(
children: [
Question(
questions[questionIndex].questionText,
),
...(questions[questionIndex].answers).map<Widget>((answer) {

return Answer(() => answerQuestion(answer.score), answer.text);
}).toList()
],
);
}
}

menuscreen.dart

import 'dart:convert';
import 'dart:developer';
import 'package:agconnect_crash/agconnect_crash.dart';
import 'package:agconnect_remote_config/agconnect_remote_config.dart';
import 'package:flutter/material.dart';
import 'package:flutter_app/AdsDemo.dart';
import 'package:flutter_app/CrashService.dart';
import 'package:flutter_app/locationdata.dart';
import 'package:flutter_app/login.dart';
import 'package:flutter_app/pushdata.dart';
import 'package:flutter_app/remotedata.dart';
class MenuScreen extends StatefulWidget {
@override
_MenuScreenState createState() => _MenuScreenState();
}
class _MenuScreenState extends State<MenuScreen> {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Menu'),
),
body: Center(
child: Column(
children: [
SizedBox(
width: 320,
child: RaisedButton(
color: Colors.red, // background
textColor: Colors.white, // foreground
child: Text('Enter Quiz'),
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(builder: (context) => LoginDemo()));
},
),
)
],
),
),
),
);
}
}

Result

View attachment 5292157

View attachment 5292161

View attachment 5292165

View attachment 5292167

View attachment 5292169

View attachment 5292173

View attachment 5292175

Tricks and Tips

Makes sure that agconnect-services.json file added.

Make sure dependencies are added build file.

Run flutter pug get after adding dependencies.

Generating SHA-256 certificate fingerprint in android studio and configure in Ag-connect.

Conclusion

In this article, we have learnt how to integrate Huawei Remote Configuration Service in Flutter QuizApp, Where json data of questions and answers are fetched from remote configurations i.e. Ag-console. Likewise you can configure other parameters like app theme, language, style and country etc. to change the app behaviour and appearance.

Thank you so much for reading, I hope this article helps you to understand the Huawei Remote Configuration Service in flutter.

Reference

Remote configuration service :

Document

developer.huawei.com

Original Source