🙆

#1 30代から始めるAndroidアプリ開発奮闘記

2022/10/21に公開

まさかの続編。

全米が待ち望んだ新作。

ここでティンパニの音が鳴る。

主のスペック

  • 30代
  • ずっと接客業

PC

  • Windows10 Pro

スマホ

  • SCG14(Samsung Galaxy S22 Ultra)

お前なんでFlutterなんだよ

だってAndroidStudioの日本語化めんどくさいし、
VScodeの方が日本語多くて楽なんだもん。(←でも今回英語のエラーで若干沼ったバカ)

今回なにするのー

前回はとりあえずアプリ開発の基盤と、
シンプルな画面構造を作るところまでやりました。
そこで今回は

REST APIからのデータ取得

をやっていきたいと思います。
そんなすごいものどんどん作れたらこの記事書いてないです。

何のデータ取得すんのー

今回サンプルはこちら
https://dev.classmethod.jp/articles/flutter-rest-api/
とりあえず
google apiを叩いてみるところから

今回知ったこと

パッケージ追加

flutter pub add http

これでいけるんだね。pubspec直接いじるだけじゃないよねそりゃ。

Windowsでデバッグするときは開発者モードをオンにする

https://zenn.dev/nukokoi/articles/5f108b0b66e639
これです

めんどくさかったのでプロジェクトフォルダはそのまま

main.dartをmain.old.dartに。新しくmain.dart作ってそこで作業

今回、特に問題なくGoogle API叩く方はコピペだけでいけました。

MTG APIも叩いてみたい。


まあ、ここらへんを変えるんだろうなあなんて。

    var response = await http.get(Uri.https(
        'www.googleapis.com',
        '/books/v1/volumes',
        {'q': '{Flutter}', 'maxResults': '40', 'langRestrict': 'ja'}));

URLがあって、パスがあって、一番下の行はパラメータかなって。

URLは"api.magicthegathering.io"
パスは"/v1/cards"
パラメータは{"set":'DMU'}
でいいかな。

    setState(() {
      items = jsonResponse['items'];
    });  

この'items'もcardsに変えないといけませんね。

取得するパラメータも変えて実行。

エラーとの戦い

なん・・・これ・・・?
https://qiita.com/surasurag/items/0b08ba4f10b2517c293f

色々調べたら要はchrome入れろってことだった。

画像URLのhttp通信が解決できないってエラーのよう。
うまいことやってくれよって思ったけど、しょうがないね。
chrome入れたら何事もなく動いたよ

Flutterの何が良いって、
Android繋いだらちゃんとAndroidでやってくれるところだなあ。

そして同じエラーが起きるっていうね。

実機エラー起きた。

に約一日苦しめられた。

https://9to5answer.com/flutter-image-network-throws-handshakeexception

https://stackoverflow.com/questions/67945270/how-to-solve-this-error-httpclient-functionsecuritycontext-isnt-a-valid
ここに助けられた。

import 'dart:io';

class MyHttpOverrides extends HttpOverrides {
  
  HttpClient createHttpClient(SecurityContext? context) {
    return super.createHttpClient(context)
      ..badCertificateCallback =
          (X509Certificate cert, String host, int port) => true;
  }
}

void main() {
  HttpOverrides.global = MyHttpOverrides();
  runApp(const MyApp());
}

実はよくわかってない。
たぶん署名必要ないものを署名無くてもとりあえずとってこいアクセスしてこいってことだと思ってる。

でも無事動いて本当に良かった。

実機画面

画質悪!!!

さいごに

なんだかんだいろいろ問題出てきたけど、
すげえ楽しかったです。今回のコード貼っておきますね。
よかったらバッジもよろしくお願いします。
ありがたく活動資金にさせていただきます。
それでは、ここまでありがとうございました。

第0回はこちら

今回のコード

main.dart
import 'dart:io';
import 'dart:convert';

import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';

class MyHttpOverrides extends HttpOverrides {
  
  HttpClient createHttpClient(SecurityContext? context) {
    return super.createHttpClient(context)
      ..badCertificateCallback =
          (X509Certificate cert, String host, int port) => true;
  }
}

void main() {
  HttpOverrides.global = MyHttpOverrides();
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'Flutter Sample',
      home: MyHomePage(title: 'Flutter Sample'),
    );
  }
}

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

  final String title;

  
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  List items = [];

  Future<void> getData() async {
    var response = await http.get(Uri.https('api.magicthegathering.io',
        '/v1/cards', {'set': 'DMU', 'pageSize': '50'}));
    var jsonResponse = jsonDecode(response.body);

    setState(() {
      items = jsonResponse['cards'];
    });
  }

  
  void initState() {
    super.initState();

    getData();
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter Sample'),
      ),
      body: ListView.builder(
        itemCount: items.length,
        itemBuilder: (BuildContext context, int index) {
          return Card(
            child: Column(
              children: <Widget>[
                ListTile(
                  leading: Image.network(
                    items[index]['imageUrl'],
                    errorBuilder: (BuildContext context, Object exception,
                        StackTrace? stackTrace) {
                      return const Text('Your error widget');
                    },
                  ),
                  title: Text(items[index]['name']),
                  subtitle: Text(items[index]['type']),
                ),
              ],
            ),
          );
        },
      ),
    );
  }
}

Discussion