ℹ️

今のアプリのバージョンを画面に表示したい

に公開

Overview

たまに、インストールしたアプリを見てアプリのバージョン1.0.0って書いてあることありませんか?
Flutterには、現在のアプリのバージョンを表示する便利なパッケージでpackage_info_plusというものがあります。昔は、package_infoというものだったようですが、こちらに変更になったようです。

https://pub.dev/packages/package_info_plus/versions/4.2.0

iOS、Android両方に対応しており、特別な設定もしないでそのまま使えます。

summary

早速使ってみました。pub getして、Exampleのソースコードをそのまま使用しただけです。

main.dart
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// ignore_for_file: public_member_api_docs

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:package_info_plus/package_info_plus.dart';

void main() {
  runApp(const MyApp());
}

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

  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'PackageInfoPlus Demo',
      theme: ThemeData(
        useMaterial3: true,
        colorSchemeSeed: const Color(0x9f4376f8),
      ),
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key}) : super(key: key);

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

class _MyHomePageState extends State<MyHomePage> {
  PackageInfo _packageInfo = PackageInfo(
    appName: 'Unknown',
    packageName: 'Unknown',
    version: 'Unknown',
    buildNumber: 'Unknown',
    buildSignature: 'Unknown',
    installerStore: 'Unknown',
  );

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

  Future<void> _initPackageInfo() async {
    final info = await PackageInfo.fromPlatform();
    setState(() {
      _packageInfo = info;
    });
  }

  Widget _infoTile(String title, String subtitle) {
    return ListTile(
      title: Text(title),
      subtitle: Text(subtitle.isEmpty ? 'Not set' : subtitle),
    );
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('PackageInfoPlus example'),
        elevation: 4,
      ),
      body: ListView(
        children: <Widget>[
          _infoTile('App name', _packageInfo.appName),
          _infoTile('Package name', _packageInfo.packageName),
          _infoTile('App version', _packageInfo.version),
          _infoTile('Build number', _packageInfo.buildNumber),
          _infoTile('Build signature', _packageInfo.buildSignature),
          _infoTile(
            'Installer store',
            _packageInfo.installerStore ?? 'not available',
          ),
        ],
      ),
    );
  }
}

📱ビルドするとこのように表示されます

iOS

Android

thoughts

PackageInfoというクラスですが、こちらはどうやら、非同期のメソッドを呼び出して、使っているようで、FutureBuilderを使えば、initStateを使用しなくてもアプリのバージョンの情報を取得できるようです。

StatelessWidgetでもできる
main.dart
import 'dart:async';

import 'package:flutter/material.dart';
import 'package:package_info_plus/package_info_plus.dart';

void main() {
  runApp(const MyApp());
}

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

  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'PackageInfoPlus Demo',
      theme: ThemeData(
        useMaterial3: true,
        colorSchemeSeed: const Color(0x9f4376f8),
      ),
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key});

  
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: FutureBuilder<String>(
          future: _getAppVersion(),
          builder: (context, snapshot) {
            if (snapshot.hasData) {
              return Text('アプリのバージョン: ${snapshot.data}');
            } else if (snapshot.hasError) {
              return Text('Error: ${snapshot.error}');
            } else {
              return const CircularProgressIndicator();
            }
          },
        ),
      ),
    );
  }

  Future<String> _getAppVersion() async {
    final packageInfo = await PackageInfo.fromPlatform();
    return packageInfo.version;
  }
}

flutter_hooksを使ったパターンも考えてみました

useFutureを使うとFutureBuilderより短く簡潔に書けます。とはいっても使用例があまりないので、短いコードでも書くのが大変でした💦

タイトル
main.dart
import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:package_info_plus/package_info_plus.dart';

void main() {
  runApp(const MyApp());
}

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

  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'PackageInfoPlus Demo',
      theme: ThemeData(
        useMaterial3: true,
        colorSchemeSeed: const Color(0x9f4376f8),
      ),
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends HookWidget {
  const MyHomePage({super.key});

  
  Widget build(BuildContext context) {
    // useMemoizedでキャッシュすると、再描画時にキャッシュした値を返す
    final memo = useMemoized(() => _getAppVersion(), []);
    // useFutureで非同期処理を実行する
    final snapshot = useFuture(memo);
    return Scaffold(
      appBar: AppBar(
        title: const Text('PackageInfoPlus Demo Hooks'),
      ),
      // FutureBuilderと同じようにsnapshotを使う
      body: snapshot.connectionState == ConnectionState.done
          ? Center(
              child: Text(
                'アプリのバージョン: ${snapshot.data.toString()}',
                style: const TextStyle(fontSize: 24),
              ),
            )
          : const Center(
              child: CircularProgressIndicator(),
            ),
    );
  }

  Future<String> _getAppVersion() async {
    final packageInfo = await PackageInfo.fromPlatform();
    return packageInfo.version;
  }
}

こんな感じになります

最近副業で、アプリのバージョンをUIに表示する要件があったので、こちらのパッケージを今回使ってみました。

Discussion