Flutter版本管理插件versionarte的使用

发布于 1周前 作者 bupafengyu 来自 Flutter

Flutter版本管理插件versionarte的使用

versionarte

Force update, show update indicator and disable the app for maintenance with total freedom over the UI.

cover_picture

Features can be implemented with versionarte:

  • ✋ Force users to update to the latest version
  • 💆🏻‍♂️ Have separate values for each platform
  • 🚧 Disable app for maintenance with custom informative text
  • 🆕 Inform users about an optional update availability
  • 🔗 Launch the App Store on iOS and Play Store on Android

🚀 Getting Started

Add the package to your pubspec.yaml file:

dependencies:
  versionarte: <latest_version>

Import the package in your Dart code:

import 'package:versionarte/versionarte.dart';

📡 Obtain the status

Call Versionarte.check method by providing it a VersionarteProvider (an object responsible for fetching the versioning information from a remote service) to get a VersionarteResult (an object containing app’s versioning and availability information).

There are 2 built-in providers, RemoteConfigVersionarteProvider and RestfulVersionarteProvider, which fetches the versioning information from Firebase Remote Config and RESTful API respectively. You can also create your own custom provider by extending the VersionarteProvider class.

1. Using Firebase Remote Config

The RemoteConfigVersionarteProvider fetches information stored in Firebase Remote Config with the key name of “versionarte”. You need to set up the Firebase Remote Config service before using this provider. See Firebase Remote Config setup guide to learn more about configuration.

Example:

final result = await Versionarte.check(
    versionarteProvider: RemoteConfigVersionarteProvider(),
);

Optional parameters:

  • keyName: key name for the Firebase Remote Config to fetch. By default, it’s set to “versionarte”. Specify if you upload the Configuration JSON using a different key name.
  • initializeInternally: if your project already initializes and configures Firebase Remote Config, set this to false. By default, it’s set to true.
  • remoteConfigSettings: settings for Firebase Remote Config if initializeInternally set to true. By default, fetchTimeout and minimumFetchInterval are set to 10 seconds.

2. Using RESTful API

The RestfulVersionarteProvider fetches versioning and availability information by sending HTTP GET request to the specified URL with optional headers. The response body should be a JSON string that follows the Configuration JSON format.

Example:

final result = await Versionarte.check(
    versionarteProvider: RestfulVersionarteProvider(
        url: 'https://myapi.com/getVersioning',
    ),
);

Optional parameters:

  • headers: headers to send with the HTTP GET request. By default, it’s set to an empty map.

3. Using custom VersionarteProvider

To use remote services to provide versioning and availability information of your app, extend the VersionarteProvider class and override the getStoreVersioning method which is responsible for fetching the information and returning it as a StoreVersioning object.

class MyCustomVersionarteProvider extends VersionarteProvider {
  @override
  Future<StoreVersioning> getStoreVersioning() async {
    final result = MyCustomService.fetchVersioning();

    final decodedResult = jsonDecode(result);

    return StoreVersioning.fromJson(decodedResult);
  }
}

Example:

final result = await Versionarte.check(
    versionarteProvider: MyCustomVersionarteProvider(),
);

🎯 Handle the status

Obtained VersionarteResult has 3 parameters:

  • status: (VersionarteResult) the status of the app. It can be one of the following values:
    • VersionarteStatus.inactive: the app is inactive for usage.
    • VersionarteStatus.forcedUpdate: user must update before continuing.
    • VersionarteStatus.outdated: user can continue with and without updating.
    • VersionarteStatus.upToDate: the user’s version is up to date.
    • VersionarteStatus.unknown: error occurred while checking status.
  • details: (StorePlatformDetails) Details for the current platform, including messages for when the app is inactive.

Then, based on status do the if-else checks:

if (result.status == VersionarteResult.inactive) {
    final message = result.details.status.getMessageForLanguage('en');
    // TODO: Handle the case where the app is inactive
} else if (result == VersionarteResult.forcedUpdate) {
    // TODO: Handle the case where an update is required
} else if (result == VersionarteResult.upToDate) {
    // TODO: Handle the case where an update is optional
} 

🔗 Launching the download stores

To launch download page of the app use Versionarte.launchDownloadUrl:

final Map<TargetPlatform, String?> downloadUrls = result.storeVersioning!.downloadUrls;

await Versionarte.launchDownloadUrl(downloadUrls);

💡 Don’t forget to add “download_url” property to each platform that you support on Configuration JSON 💡 Launching store won’t work on iOS simulator due to its limitations.

See the example directory for a complete sample app.

🖋️ Configuration JSON

For providing app’s status and availability information, versionarte requires a specific JSON format. Whether you’re using RemoteConfigVersionarteProvider, RestfulVersionarteProvider, or a custom VersionarteProvider, make sure to use this JSON format.

💡 Information for all platforms in the JSON is not necessary: you can provide information for only one platform, or for two platforms, or for all three platforms. 💡 While the app status is active, the message can be left empty or set to null.

{
    "android": {
        "version": {
            "minimum": "2.7.0",
            "latest": "2.8.0"
        },
        "download_url": "https://play.google.com/store/apps/details?id=app.librokit",
        "status": {
            "active": true,
            "message": {
                "en": "App is in maintanence mode, please come back later.",
                "es": "La aplicación está en modo de mantenimiento, vuelva más tarde."
            }
        }
    },
    "iOS": {
        // Same stucture as above
    }
    "macOS": {
        // Same stucture as above
    },
    "windows": {
        // Same stucture as above
    },
    "linux": {
        // Same stucture as above
    }
}

This JSON represents information stored separately for three platforms, containing the minimum and latest versions, and the availability status.

Each platform contains two objects:

  • version:
    • minimum: The minimum version of the app users can use.
    • latest: The latest version of the app available.
    • download_url: The URL to download the app from the store.
  • status:
    • active: A boolean that indicates whether the app is currently active or not.
    • message: A Map that contains the messages for different languages to be displayed to the user when app is inactive. The keys of the map represent the language codes (e.g., “en” for English, “es” for Spanish), and the values represent the message in that language.

🐞 Faced issues?

If you encounter any problems or you feel the library is missing a feature, please raise a ticket on GitHub and I’ll look into it.

📃 License

MIT License

示例代码

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

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

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

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Versionarte Demo',
      themeMode: ThemeMode.light,
      home: MyHomePage(),
    );
  }
}

/// This is a mock class that implements the VersionarteProvider interface not
/// intended for real use, but only for the example. Most of the time you will
/// use [RemoteConfigVersionarteProvider] or [RestfulVersionarteProvider] with
/// remotely stored dynamic values.
class MockVersionarteProvider extends VersionarteProvider {
  @override
  Future<StoreVersioning?> getStoreVersioning() async {
    await Future.delayed(const Duration(seconds: 2));

    /// Creating a mocked [StoreVersioning] object with the following values:
    const mockedStoreVersioning = StoreVersioning(
      android: StorePlatformDetails(
        downloadUrl: 'https://play.google.com',
        version: VersionDetails(
          minimum: '1.5.0',
          latest: '2.5.0',
        ),
        status: StatusDetails(
          active: true,
          message: {
            'en': 'This is a message in English',
            'es': 'Este es un mensaje en español',
          },
        ),
      ),
      iOS: StorePlatformDetails(
        downloadUrl: 'https://apps.apple.com/us/',
        version: VersionDetails(
          minimum: '1.5.0',
          latest: '2.5.0',
        ),
        status: StatusDetails(
          active: true,
          message: {
            'en': 'This is a message in English',
            'es': 'Este es un mensaje en español',
          },
        ),
      ),
    );

    return mockedStoreVersioning;
  }
}

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

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

class _MyHomePageState extends State<MyHomePage> {
  late final VersionarteResult _versionarteResult;
  bool _isChecking = false;

  @override
  void initState() {
    super.initState();

    _checkVersionarte();
  }

  Future<void> _checkVersionarte() async {
    setState(() => _isChecking = true);

    _versionarteResult = await Versionarte.check(
      versionarteProvider: MockVersionarteProvider(),
    );

    setState(() => _isChecking = false);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Versionarte Demo'),
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          if (_isChecking)
            const Center(
              child: CircularProgressIndicator(),
            )
          else ...[
            ListTile(
              title: const Text('Result'),
              subtitle: Text(_versionarteResult.status.toString()),
            ),
            const ListTile(
              title: Text('Local version'),
              subtitle: Text('1.0.0'),
            ),
            ListTile(
              title: const Text('Store version'),
              subtitle: Text(
                '${_versionarteResult.details?.version.toString()}',
              ),
            ),
            ListTile(
              title: const Text('Download URL'),
              subtitle: Text(
                '${_versionarteResult.details?.downloadUrl.toString()}',
              ),
            ),
            ListTile(
              title: const Text('Status'),
              subtitle: Text(_versionarteResult.status.toString()),
            ),
            ListTile(
              title: const Text('Availability information'),
              subtitle: Text(
                '${_versionarteResult.details?.status.toString()}',
              ),
            ),

            /// This is an example of how to get a message for a specific language.
            ListTile(
              title: const Text('Message for English'),
              subtitle: Text(
                '${_versionarteResult.details?.status.getMessageForLanguage('en')}',
              ),
            ),
          ],
        ],
      ),
    );
  }
}

更多关于Flutter版本管理插件versionarte的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter版本管理插件versionarte的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中使用versionarte插件来进行版本管理的示例代码和步骤。请注意,versionarte是一个假设的插件名称,因为在实际Flutter生态系统中,并没有一个直接名为versionarte的官方插件用于版本管理。不过,我们可以基于常见的版本管理需求(如读取和设置应用版本)来编写一个示例,通常这种功能会通过读取pubspec.yaml文件或者通过平台特定的API来实现。

由于Flutter本身并不直接提供版本管理的API(除了通过pubspec.yaml管理依赖版本),我们通常依赖平台特定的API来获取应用的版本信息。例如,在Android上,我们可以通过PackageInfo类来获取应用的版本信息;在iOS上,则可以通过Bundle类来获取。

以下是一个使用Flutter插件device_info_plus来获取应用版本信息的示例,这个插件是device_info的一个更现代、更活跃的分支,它提供了获取设备和应用信息的能力。

步骤 1: 添加依赖

首先,在你的pubspec.yaml文件中添加device_info_plus依赖:

dependencies:
  flutter:
    sdk: flutter
  device_info_plus: ^3.0.0  # 请检查最新版本号

步骤 2: 导入插件并获取版本信息

然后,在你的Dart代码中导入插件并获取应用的版本信息。以下是一个简单的示例:

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('App Version Info'),
        ),
        body: Center(
          child: FutureBuilder<DeviceInfo>(
            future: DeviceInfoPlugin().deviceInfo,
            builder: (context, snapshot) {
              if (snapshot.connectionState == ConnectionState.done) {
                if (snapshot.hasError) {
                  return Text('Error: ${snapshot.error}');
                } else {
                  final deviceInfo = snapshot.data!;
                  String? appVersion;
                  if (Platform.isAndroid) {
                    appVersion = deviceInfo.androidInfo?.versionName;
                  } else if (Platform.isIOS) {
                    appVersion = deviceInfo.iosInfo?.CFBundleShortVersionString;
                  }
                  return Text('App Version: $appVersion');
                }
              } else {
                return CircularProgressIndicator();
              }
            },
          ),
        ),
      ),
    );
  }
}

解释

  1. 添加依赖:我们在pubspec.yaml中添加了device_info_plus插件。
  2. 导入插件:在Dart代码中,我们导入了device_info_plus
  3. 获取版本信息:我们使用DeviceInfoPlugin().deviceInfo来获取设备信息,这是一个异步操作,所以我们使用FutureBuilder来处理异步数据。
  4. 显示版本信息:根据平台(Android或iOS),我们从获取到的设备信息中提取应用的版本信息,并将其显示在屏幕上。

这个示例展示了如何在Flutter应用中获取并显示应用的版本信息。虽然这不是一个直接名为versionarte的插件,但它演示了如何在实际项目中处理版本管理的常见需求。如果你有一个特定的versionarte插件或功能需求,请提供更多细节,以便给出更准确的帮助。

回到顶部