📱

FlutterでのOS判定、端末情報、バージョン情報取得や比較のあれこれ【忙しい人向け】

2022/02/07に公開

はじめに

FlutterでのOS判定、端末情報、バージョン情報取得などパッケージも含めると充実しています。よく使いそうなあれ?これどうやる?どう取得する?を簡単にまとめた記事になります。

対象

モバイルのみ(Android/iOS)

OS判定したい

これはよく使われているコードだと思うのですがdart:ioで用意されてるOS判定のクラスです

// Android
if (Platform.isAndroid) {
 // Androidで実行したい処理
} 

// iOS
if (Platform.isIOS) {
 // iOSで実行したい処理
}

ただ、Widgetの出しわけのためのOS判定は以下記事にも記載がありますが、Themeを使った判定の方が良さそうです

Theme.of(context).platform == TargetPlatform.android // Android
Theme.of(context).platform == TargetPlatform.iOS // iOS

https://qiita.com/oboenikui/items/5b42b01cedfca9ae0693

アプリ名を取得したい

package_info_plusパッケージで取得できます (package_infoの方はもうメンテされないので、package_info_plusの方を使いましょう)

https://pub.dev/packages/package_info_plus

final packageInfo = await PackageInfo.fromPlatform();
final appName = packageInfo.appName; // String

アプリバージョンを取得したい

これもpackage_info_plusパッケージで取得できます

final packageInfo = await PackageInfo.fromPlatform();
final version = packageInfo.version; // String 

アプリのビルド番号を取得したい

これもpackage_info_plusパッケージで取得できます

final packageInfo = await PackageInfo.fromPlatform();
final buildNumber = packageInfo.buildNumber; // String

OSバージョンを取得したい

これはdevice_info_plusパッケージで取得できます(これもdevice_infoの方はメンテされないので、device_info_plusを使いましょう)

https://pub.dev/packages/device_info_plus

こんな感じで取得できます

// Android
final androidInfo = await deviceInfo.androidInfo;
final androidOsVersion = androidInfo.version.release!;

// iOS
final iosInfo = await deviceInfo.iosInfo;
final iosOsVersion = iosInfo.systemVersion!;

上記のOS単位での取得できるメソッドが用意されてますが、利用者側にOSを意識せずに端末情報を取得するメソッドがあります

final deviceInfoPlugin = DeviceInfoPlugin();
final deviceInfo = await deviceInfoPlugin.deviceInfo;

以下内部コードを見るとOSごとに分岐しています
https://github.com/fluttercommunity/plus_plugins/blob/8fc1df510e130912ce4153f468ed90bda4b73edb/packages/device_info_plus/device_info_plus/lib/device_info_plus.dart#L84-L103

また、Riverpodを組み合わせたやり方で非同期で取得に時間がかかるものに対して、起動時に事前に取得してProviderScopeでoverridesさせるやる方もあるので自分はこんな感じにしてます(どっちでもいいかも)

※ Riverpodはv1.0.0以上

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

import 'app.dart';
import 'samples/device_and_packge_info/device_info_provider.dart';
import 'samples/device_and_packge_info/package_info_provider.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  // BaseDeviceInfoというabstract classが定義されていて
  // 各DeviceInfoクラス(AndroidDeviceInfo,IosDeviceInfoで)にimplementsされている
  late BaseDeviceInfo deviceInfo; 
  late PackageInfo packageInfo; // PackageInfoinfoも同様に可能

  await Future.wait([
    Future(() async {
      deviceInfo = await DeviceInfoPlugin().deviceInfo;
    }),
    Future(() async {
      packageInfo = await PackageInfo.fromPlatform();
    }),
  ]);

  runApp(
    ProviderScope(
      overrides: [
        deviceInfoProvider.overrideWithValue(deviceInfo),
        packageInfoProvider.overrideWithValue(packageInfo),
      ],
      /// 省略
    ),
  );
}

Providerの宣言は以下みたいな感じです

import 'package:device_info_plus/device_info_plus.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:package_info_plus/package_info_plus.dart';

final deviceInfoProvider = Provider<BaseDeviceInfo>(
  (_) => throw UnimplementedError(),
);

final packageInfoProvider = Provider<PackageInfo>(
  (ref) => throw UnimplementedError(),
);

利用時はこんな感じでできます

// Widgetのビルド関数内の想定 
final deviceInfo = ref.watch(deviceInfoProvider);

if (Platform.isAndroid) {
    final androidInfo = device as AndroidDeviceInfo;
    final osVersion = androidInfo.version.release!; 
} else if (Platform.isIOS) {
  final iosInfo = device as IosDeviceInfo;
  final osVersion = iosInfo.systemVersion!
} else {
  // それ以外
}

機種名を取得したい

これもdevice_info_plusで取得できます

// Android
final androidInfo = await deviceInfo.androidInfo;
final androidOsVersion = androidInfo.device!;

// iOS
final iosInfo = await deviceInfo.iosInfo;
final iosOsVersion = iosInfo.utsname.machine!;

最近、記事を書かれた@iseruuuuuさんの記事にもある通り、iOSの場合機種名を取得すると内部名での取得になります。

https://qiita.com/iseruuuuu/items/4e62ef270ec96598b403#説明

自分も内部名から一般名の変換に悩んでいたところ、@iseruuuuuさんの記事から名称を相互変換してくれるパッケージがあることを最近知りました(@iseruuuuuさん記事執筆ありがとうございます)

https://pub.dev/packages/apple_product_name

こんな感じで変換できます

final iosInfo = await deviceInfo.iosInfo;
final iosOsVersion = AppleProductName().lookup(iosInfo.utsname.machine!);

他Androidの使いそうな端末情報を取得したい

以下の情報もdevice_info_plusパッケージで取得できます

// Android
final androidInfo = await deviceInfo.androidInfo;
final sdkVersion = androidInfo.version.sdkInt!; // これはint
final brand = androidInfo.brand!; // 例 楽天、Google

(セマンティックバージョンニングでの)Version比較がしたい

versionパッケージが便利です

https://pub.dev/packages/version

サンプルコードより

Version currentVersion = new Version(1, 0, 3);
Version latestVersion = Version.parse("2.1.0"); // 文字列からいい感じにパースしてくれるstaticメソッド

if (latestVersion > currentVersion) {    
  print("Update is available");
}

試し

以下コードで色々OS判定、情報取得、バージョン比較を実機で動かしてみました

環境

Flutter: 2.5.3(fvm使用)

version: 1.0.0+1

environment:
  sdk: ">=2.14.0 <3.0.0"

dependencies:
  apple_product_name: ^1.0.1
  device_info_plus: ^3.2.1
  flutter:
    sdk: flutter
  flutter_hooks: ^0.18.2
  hooks_riverpod: ^1.0.1
  package_info_plus: ^1.3.0
  version: ^2.0.0

dev_dependencies:
  flutter_test:
    sdk: flutter

https://github.com/kentomiya89/k_flutter_playground/blob/main/lib/samples/device_and_packge_info/device_and_package_info_screen.dart

Android

アプリバージョンや端末情報列挙

ダイアログでOSバージョンの比較結果表示

iOS

アプリバージョンや端末情報列挙

ダイアログでOSバージョンの比較結果表示

iOSのシュミレーターは、iosInfo.utsname.machineで機種名を取得した場合にその実行している機種名ではなくシュミレーター名になるので注意です

何か間違いや他の端末情報もよく取るだろうみたいな例があれば気軽にご連絡ください

GitHubで編集を提案

Discussion