フラッターDietAppでHuaweiアカウントキット、リモート構成サービスとクラッシュキットの統合-第5部
30540 ワード
導入
この記事では、我々はHuaweiリモート設定サービス、アカウントキットをフラッターDietAppで統合されます.Flutterプラグインは、ユーザーの承認を体験する簡単で便利な方法を提供します.Flutterのアカウントのプラグインは、ユーザーが携帯電話やタブレットなどのさまざまなデバイスから自分のHuawei IDを使用してHuawei生態系に接続することができます、ユーザーが迅速にログインすることができます便利な初期のアクセス許可を付与した後に自分のHuawei IDでアプリにログインすることができます.
また、このアプリケーションでHuaweiクラッシュサービスを統合することを学びます.これは、開発者のクラッシュは無料、すなわち予期しないアプリケーションの出口を構築するための責任であり、それは非常に巨大なアプリケーションのコードベースでクラッシュの原因を見つけることは困難です.この予期しないクラッシュは、アプリのユーザーが迷惑になり、ビジネス損失につながる可能性があります製品や企業の市場価値を減らす.そのようなクラッシュを避けるために、Huaweiは、開発者がクラッシュして、AGコンソールのアプリケーションの予期せぬ出口を見つけることができるクラッシュサービスを提供します.
クラッシュSDKは非常にシンプルで開発者が実装クラッシュサービスに多くのコードを必要としません.また、必要なときに詳細なクラッシュレポートをダウンロードすることができます.
リモート設定はHuaweiによって提供されるサービスです.これは、クラウドベースのサービスを提供します.クライアントSDKを統合すると、アプリケーションは定期的にクラウドからパラメーター値を取得できます.サービスは、アプリケーションがフェッチしようとするパラメータがon - cloud値更新を持つかどうかをチェックし、もしそうならば新しい値を返します.フェッチされたパラメーター値に基づいて、あなたのアプリケーションの動作や外観を変更するサービス処理ロジックを実装できます.このサンプルでは、すなわちDietAppでは、AppGalleryによるリモート設定サービスを使用して、個人のエクササイズデータを取得しています.
前記事
私の前の記事をチェックしてください.
開発概要
IDEでFlutterとDARTプラグインをインストールする必要があります.そして、フラッタとダーツについての事前の知識があると仮定します.
ハードウェア要件
Windows 10を実行しているコンピュータ(デスクトップまたはラップトップ).
デバッギングのために使われるAndroid電話(USBケーブルで).
ソフトウェア要件
Java JDK 1.7以降.
Android StudioソフトウェアまたはVisual Studioまたはコードをインストールします.
HMSコア( APK ) 4 .x以降.
統合プロセス
ステップ1:作成フラッタプロジェクト.
ステップ2:アプリケーションレベルのGradleの依存関係を追加します.プロジェクトAndroidの内部を選択します.グレード.
apply plugin: 'com.android.application'
apply plugin: 'com.huawei.agconnect'
ルートレベルのgradle依存性maven {url 'https://developer.huawei.com/repo/'}
classpath 'com.huawei.agconnect:agcp:1.5.2.300'
ステップ3 : Androidマニフェストファイルに以下のパーミッションを追加します.<uses-permission android:name="android.permission.INTERNET" />
ステップ4 :ダウンロードしたファイルをプロジェクトの親ディレクトリに追加します.プラグインのパスを宣言します.依存関係のYAMLファイル.アセットイメージのパスの場所を追加します.
コーディングを始めましょう
スプラッシュスクリーン.ダート
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'));
}
}
Loginscreen.ダート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);
}
}
メイン.ダート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();
}
}
}
}
タブスクリーン.ダート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>[
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: [
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');
},
),
),
],
),
),
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]);
},
child: Container(
alignment: Alignment.center,
child: Text(gridItems[index],
style: const TextStyle(
color: Colors.white,
fontSize: 24,
fontWeight: FontWeight.bold)),
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);
});
}
}
結果トリックとヒント
ダウンロードしたプラグインがプロジェクトの親ディレクトリに展開されていることを確認します.
AGconnectサービスを確実にします.JSONファイル追加.
依存関係をYAMLファイルに追加してください.
run flugパグは依存関係を追加した後に取得します.
AGCでサービスが有効になっていることを確認してください.
イメージをYAMLファイルで定義します.
AGCで追加されたパラメータはJSON形式です.
結論
この記事では、Huaweiリモート設定サービス、アカウントキット、クラッシュキットフラッターDietAppを統合する方法を学びました.アカウントキットを統合すると、ユーザーが迅速かつ便利にログインすることができます便利なアプリケーションに自分のhuawei IDを最初のアクセス許可を付与した後に署名します.プッシュキットでは、リアルタイムでユーザーのデバイスにプッシュ通知を送信することができます、結果の部分でプッシュ通知を見ることができます.開発者を迅速に検出し、見つけて、アプリケーションのクラッシュや予期しない終了を修正するHuaweiクラッシュサービスを提供します.したがって、アプリケーションの安定性と信頼性を向上させる.リモート設定サービスの助けを借りて、私たちはクラウドから個人の運動データを取得しています.
読書ありがとうございます.私はこの記事をHuaweiリモート設定、アカウントキットとFlutter DietAppでクラッシュキットの統合を理解するのに役立ちます願っています.
リファレンス
Crash Kit
アカウントキット
クラッシュキット
Training Video
Reference
この問題について(フラッターDietAppでHuaweiアカウントキット、リモート構成サービスとクラッシュキットの統合-第5部), 我々は、より多くの情報をここで見つけました https://dev.to/hmscommunity/integration-of-huawei-account-kit-remote-configuration-service-and-crash-kit-in-flutter-dietapp-part-5-3392テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol