Flutter DietAppのHuawei口座キット、プッシュキットと分析キットの統合-パート3



導入
この記事では、我々はHuaweiアカウント、Flutter DietAppでプッシュキットと解析キットを統合されます.この記事では、フォームフォームダイエットプランを参照することができますどのような種類の食品を得ることができる/画像と重量を失う、我々はダイエット画面で見ることができます.Flutterプラグインは、ユーザーの承認を体験する簡単で便利な方法を提供します.Flutterのアカウントのプラグインは、ユーザーが携帯電話やタブレットなどのさまざまなデバイスから自分のHuawei IDを使用してHuawei生態系に接続することができます、ユーザーが迅速にログインすることができます便利な初期のアクセス許可を付与した後に自分のHuawei IDでアプリにログインすることができます.
Huaweiプッシュキットメッセージングサービスを提供しています.これは、クラウドからデバイスへのメッセージングチャネルを確立します.プッシュキットを統合することにより、リアルタイムでユーザーのデバイス上のアプリケーションにメッセージを送信することができます.これは、ユーザーとの緊密な関係を維持し、ユーザーの意識とあなたのアプリとの約束を高めることができます.
Huawei Analyticsは、モバイルアプリケーション、Webアプリケーションやクイックアプリケーションなどのすべてのあなたの製品のためのさまざまなプラットフォームでのユーザーの行動分析を取得するワンストップソリューションです.これは、開発者が詳細な分析レポートを取得し、また、デフォルトでクラッシュレポートを提供することができます.それは、特定のデータ収集、管理、分析、および使用を提供しています.そして、効果的なユーザー獲得、製品最適化、正確な活動とビジネス成長を成し遂げるために、企業を助けます.


前記事
あなたが行っていない場合、私の前の記事をチェックしてください、パート2をクリックしてください.
開発概要
IDEでFlutterとDARTプラグインをインストールする必要があります.そして、フラッタとダーツについての事前の知識があると仮定します.
ハードウェア要件
Windows 10を実行しているコンピュータ(デスクトップまたはラップトップ).
デバッギングのために使われるAndroid電話(USBケーブルで).
ソフトウェア要件
Java JDK 1.7以降.
Android StudioソフトウェアまたはVisual Studioまたはコードをインストールします.
HMSコア( APK ) 4 .x以降.
統合プロセス
ステップ1:作成フラッタプロジェクト.


ステップ2:アプリケーションレベルのGradleの依存関係を追加します.プロジェクトAndroidの内部を選択します.グレード.
ルートレベルのgradle依存性
ステップ3 : Androidマニフェストファイルに以下のパーミッションを追加します.
ステップ4:ダウンロードフラッタープッシュキットplugins.
ステップ5 :ダウンロードしたファイルをプロジェクトの親ディレクトリに追加します.プラグインのパスを宣言します.依存関係の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();
      }
    }
  }
}

Dietplanscreenダート
class DietPlanScreen extends StatelessWidget {
  const DietPlanScreen({Key? key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'Exercise&DietApp',
      home: MyHomePage(
        title: 'Diet',
      ),
    );
  }
}

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 SharedPreferences prefs;

  String dietPlan = '', wt_lg = '';
  double wt = 0;

  bool isGain = false;

  void initState() {
    initPreference();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        resizeToAvoidBottomInset: true,
        appBar: AppBar(
          title: Text(widget.title.toString()),
          backgroundColor: Colors.blue,
          automaticallyImplyLeading: false,
        ),
        body: SingleChildScrollView(
          child: Card(
            color: Colors.white,
            child: Center(
              child: Padding(
                padding: EdgeInsets.all(15),
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.start,
                  children: <Widget>[
                    Card(
                      elevation: 3,
                      shape: Border(
                          right: BorderSide(color: Colors.red, width: 5)),
                      child: Padding(
                        padding: EdgeInsets.all(20),
                        child: Text(
                          dietPlan,
                          style: const TextStyle(
                              fontSize: 19, color: Colors.deepOrange),
                        ),
                      ),
                    ),
                    Visibility(
                      visible: isGain,
                      child: Card(
                        elevation: 3,
                        shape: Border(
                            right: BorderSide(
                                color: Colors.greenAccent, width: 5)),
                        child: Padding(
                          padding: EdgeInsets.all(5),
                          child: ExpansionTile(
                            title: Text('Diet Plan',
                                style: TextStyle(
                                    fontSize: 22, color: Colors.teal)),
                            subtitle: Text('To $wt_lg $wt kg weight'),
                            children: <Widget>[
                              Text(
                                'Foods to gain weight quickly',
                                style: TextStyle(
                                    color: Colors.green, fontSize: 20),
                              ),
                              ListTile(
                                title: Column(
                                  children: <Widget>[
                                    ListTile(
                                      title: getTile('Milk'),
                                    ),
                                    Image.asset('images/milk.jpg'),
                                    ListTile(
                                      title: getTile('Protein shakes'),
                                    ),
                                    Image.asset('images/proteinshake.jpg'),
                                    ListTile(
                                      title: getTile('Rice'),
                                    ),
                                    Image.asset('images/rice.jpg'),
                                    ListTile(
                                      title: getTile('Nuts and nut butter'),
                                    ),
                                    Image.asset('images/nutsbutter.jpg'),
                                    ListTile(
                                      title: getTile('Whole-grain breads'),
                                    ),
                                    Image.asset('images/wholegrain.jpg'),
                                    ListTile(
                                      title: getTile('Eggs, Fats and oils'),
                                    ),
                                    Image.asset('images/eggfat.jpeg'),
                                    ListTile(
                                      title: getTile('Dried fruits'),
                                    ),
                                    Image.asset('images/dryfruit.jpg'),
                                  ],
                                ),
                              ),
                            ],
                          ),
                        ),
                      ),
                    ),
                    Visibility(
                      visible: !isGain,
                      child: Card(
                        elevation: 3,
                        shape: Border(
                            right: BorderSide(color: Colors.black26, width: 5)),
                        child: Padding(
                          padding: EdgeInsets.all(5),
                          child: ExpansionTile(
                            title: Text('Diet Plan',
                                style: TextStyle(
                                    fontSize: 22, color: Colors.teal)),
                            subtitle: Text('To $wt_lg $wt kg weight'),
                            children: <Widget>[
                              Text(
                                'Foods to loose weight quickly',
                                style: TextStyle(
                                    color: Colors.green, fontSize: 20),
                              ),
                              ListTile(
                                title: Column(
                                  children: <Widget>[
                                    ListTile(
                                      title: getTile('Beans'),
                                    ),
                                    Image.asset('images/beans.jpg'),
                                    ListTile(
                                      title: getTile('Soup'),
                                    ),
                                    Image.asset('images/soup.jpg'),
                                    ListTile(
                                      title: getTile('Dark Chocolate'),
                                    ),
                                    Image.asset('images/dark_chocolate.jpg'),
                                    ListTile(
                                      title: getTile('Pureed Vegetables'),
                                    ),
                                    Image.asset('images/pureed.jpg'),
                                    ListTile(
                                      title: getTile('Yogurt with berries'),
                                    ),
                                    Image.asset('images/yogurt.jpg'),
                                    ListTile(
                                      title: getTile('Nuts, Apples and Yogurt'),
                                    ),
                                    Image.asset('images/nutsapple.jpg'),
                                    ListTile(
                                      title: getTile('Grapefruit'),
                                    ),
                                    Image.asset('images/grapefruit.jpg'),
                                  ],
                                ),
                              ),
                            ],
                          ),
                        ),
                      ),
                    ),
                  ],
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }

  void getPlan() {
    double? days = prefs.getDouble('inDays');
    double? tagetWeight = prefs.getDouble('targetWeight');
    double? weight = prefs.getDouble('weight');
    print('Target $tagetWeight');
    print('weight $weight');

    setState(() {
      if (tagetWeight! > weight!) {
        setState(() {
          isGain = true;
        });
        wt_lg = 'gain';
        wt = tagetWeight - weight;
        dietPlan = 'Aim is to $wt_lg $wt kg weight in $days days.';
      } else {
        setState(() {
          isGain = false;
        });

        wt_lg = 'loose';
        wt = weight - tagetWeight;
        dietPlan = 'Aim is to $wt_lg $wt kg weight in $days days.';
      }
    });
  }

  Future<void> initPreference() async {
    prefs = await SharedPreferences.getInstance();
    getPlan();
  }

  RichText getTile(String item) {
    return RichText(
      text: TextSpan(
        text: '• ',
        style: TextStyle(
          color: Colors.lightBlue,
        ),
        children: <TextSpan>[
          TextSpan(text: '$item', style: TextStyle(fontSize: 18)),
        ],
      ),
    );
  }
}

結果


トリックとヒント
ダウンロードしたプラグインがプロジェクトの親ディレクトリに展開されていることを確認します.
AGconnectサービスを確実にします.JSONファイル追加.
依存関係をYAMLファイルに追加してください.
run flugパグは依存関係を追加した後に取得します.
AGCでサービスが有効になっていることを確認してください.
イメージをYAMLファイルで定義します.
結論
この記事では、どのようにHuaweiアカウントキット、プッシュキットと分析キットをFlutter DietAppで統合する方法を学びました.アカウントキットを統合すると、ユーザーが迅速かつ便利にログインすることができます便利なアプリケーションに自分のhuawei IDを最初のアクセス許可を付与した後に署名します.プッシュキットでは、リアルタイムでユーザーのデバイスにプッシュ通知を送信することができます、結果の部分でプッシュ通知を見ることができます.
読書ありがとうございます.私はこの記事をHuaweiアカウントキットの統合を理解するのに役立ちますプッシュキットと分析キットFlutter DietAppで.
リファレンス
Push Kit
アカウントキット
プッシュキット