From 60dbdf1b10f4bc18e0284763732d8d0b8714a767 Mon Sep 17 00:00:00 2001 From: Ali Ahamed Thowfeek Date: Wed, 15 Apr 2020 17:37:42 +0530 Subject: [PATCH 1/3] implemented version checking, known issue: the code runs twice, as the widget gets initialized twice (with or without this code for version checking) --- ios/Podfile.lock | 8 ++-- lib/constants.dart | 8 ++++ lib/main.dart | 104 ++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 115 insertions(+), 5 deletions(-) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 389d714..08e67bd 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -75,9 +75,9 @@ PODS: - FMDB (2.7.5): - FMDB/standard (= 2.7.5) - FMDB/standard (2.7.5) - - geolocator (5.3.1): + - geolocator (5.3.0): - Flutter - - google_api_availability (2.0.4): + - google_api_availability (2.0.3): - Flutter - google_maps_flutter (0.0.1): - Flutter @@ -260,8 +260,8 @@ SPEC CHECKSUMS: Flutter: 0e3d915762c693b495b44d77113d4970485de6ec flutter_plugin_android_lifecycle: 47de533a02850f070f5696a623995e93eddcdb9b FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a - geolocator: 460cc8e850b616f8c0e90944c86517d91ccbb686 - google_api_availability: 15fa42a8cd83c0a6738507ffe6e87096f12abcb8 + geolocator: 7cdcf71180b80913b3cd84ab715d3b5365b378af + google_api_availability: 526574c9a5a0ae541e18c65f98e47afc11f53c8b google_maps_flutter: d0dd62f5a7d39bae61057eb9f52dd778d99c7c6c GoogleAppMeasurement: 434cc7be25e71dc04b8d0e3079125127b330e84a GoogleDataTransport: 166f9b9f82cbf60a204e8fe2daa9db3e3ec1fb15 diff --git a/lib/constants.dart b/lib/constants.dart index fc10903..7b339ed 100644 --- a/lib/constants.dart +++ b/lib/constants.dart @@ -1,3 +1,11 @@ final bool debugRelease = false; //final String testingServer = "https://test.covid-19.health.gov.lk/api"; final String testingServer = "https://test.covid-19.health.gov.lk/api"; + +//Constants defined for version checking +const String ANDROID_APP_BUILD_NUMBER_KEY = "android_app_builder_number_Key"; +const String IOS_APP_BUILD_NUMBER_KEY = "ios_app_builder_number_key"; +const String ANDROID_APP_URL = + "https://play.google.com/store/apps/details?id=app.ceylon.selftrackingapp"; +const String IOS_APP_URL = + "https://apps.apple.com/us/app/myhealth-sri-lanka/id1503349513"; \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index 3d57bcc..08daf6a 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,11 +1,13 @@ import 'dart:async'; -import 'dart:async'; import 'dart:io'; +import 'package:firebase_remote_config/firebase_remote_config.dart'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:get_it/get_it.dart'; +import 'package:package_info/package_info.dart'; import 'package:selftrackingapp/app_localizations.dart'; import 'package:selftrackingapp/networking/data_repository.dart'; import 'package:selftrackingapp/networking/db.dart'; @@ -14,6 +16,8 @@ import 'package:selftrackingapp/page/screen/welcome_screen.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:connectivity/connectivity.dart'; import 'package:flutter/services.dart'; +import 'package:url_launcher/url_launcher.dart'; +import 'constants.dart'; import 'utils/tracker_colors.dart'; import 'package:dropdown_banner/dropdown_banner.dart'; @@ -79,6 +83,7 @@ class _HomeScreenState extends State { @override void initState() { super.initState(); + _isTimeoutCompleted = false; SystemChrome.setPreferredOrientations([ DeviceOrientation.portraitUp, @@ -94,6 +99,7 @@ class _HomeScreenState extends State { }); loadLang(); + _appVersionCheck(); } Future loadLang() async { @@ -154,4 +160,100 @@ class _HomeScreenState extends State { checkReachability(); return _createSplashScreen(); } + +//check for the latest build number set in the firebase remote config +//and show update dialog if necessary + void _appVersionCheck() async { + String key = Platform.isIOS + ? IOS_APP_BUILD_NUMBER_KEY + : ANDROID_APP_BUILD_NUMBER_KEY; + + //Get Current buildNumber of the app + final PackageInfo info = await PackageInfo.fromPlatform(); + + //In Android this refers to [versionCode]. In iOS [CFBundleVersion] + int currentBuildNumber = int.parse(info.buildNumber); + + //Get Latest version info from firebase config + final RemoteConfig remoteConfig = await RemoteConfig.instance; + + try { + await remoteConfig + .setDefaults({key: currentBuildNumber}); + + // Using default duration to force fetching from remote server. + await remoteConfig.fetch(expiration: const Duration(seconds: 0)); + await remoteConfig.activateFetched(); + + int remoteBuildNumber = remoteConfig.getInt(key); + + print("remoteBuildNumber $remoteBuildNumber"); + if (remoteBuildNumber > currentBuildNumber) { + _showUpdateDialog(); + } + } on FetchThrottledException catch (exception) { + // Fetch throttled. + print(exception); + } catch (exception) { + print('Unable to fetch remote config. Default value will be used'); + } + } + + void _showUpdateDialog() async { + bool isIOS = Platform.isIOS; + String title = "New Update Available"; + String message = + "There is a newer version of the app available. Please update now."; + String affirmativeLabel = "Update Now"; + String negativeLabel = "Later"; + + isIOS + ? showCupertinoDialog( + context: context, + builder: (context) { + return CupertinoAlertDialog( + title: Text(title), + content: Text(message), + actions: [ + CupertinoDialogAction( + isDefaultAction: true, + child: Text(affirmativeLabel), + onPressed: () => launchAppStore(IOS_APP_URL), + ), + CupertinoDialogAction( + child: Text(negativeLabel), + onPressed: () => Navigator.pop(context), + ), + ], + ); + }) + : showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: Text(title), + content: Text(message), + actions: [ + FlatButton( + child: Text( + affirmativeLabel.toUpperCase(), + style: TextStyle(color: Colors.blue), + ), + onPressed: () => launchAppStore(ANDROID_APP_URL), + ), + FlatButton( + child: Text(negativeLabel.toUpperCase()), + onPressed: () => Navigator.pop(context), + ), + ], + ); + }, + ); + } + + void launchAppStore(String url) async { + if (await canLaunch(url)) { + launch(url); + } + } } From 4e974afbf174ff00a651ce02ce89d31566a0c0e7 Mon Sep 17 00:00:00 2001 From: Ali Ahamed Thowfeek Date: Wed, 15 Apr 2020 17:47:21 +0530 Subject: [PATCH 2/3] bumped the build number --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 355616d..36c1bef 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -11,7 +11,7 @@ description: Self tracking app # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 1.14.0+31 +version: 1.14.0+32 environment: sdk: ">=2.1.0 <3.0.0" From 0089af38d3070fcff083639eefaeeb0d1b7e5b9f Mon Sep 17 00:00:00 2001 From: Ali Ahamed Thowfeek Date: Wed, 15 Apr 2020 23:33:12 +0530 Subject: [PATCH 3/3] moved version checking code from HomeScreen to RootScreen --- lib/main.dart | 110 ++----------------------------- lib/page/screen/root_screen.dart | 107 ++++++++++++++++++++++++++++-- 2 files changed, 106 insertions(+), 111 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 08daf6a..1ce76fd 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,25 +1,20 @@ import 'dart:async'; -import 'dart:io'; - -import 'package:firebase_remote_config/firebase_remote_config.dart'; +import 'package:connectivity/connectivity.dart'; +import 'package:dropdown_banner/dropdown_banner.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:get_it/get_it.dart'; -import 'package:package_info/package_info.dart'; import 'package:selftrackingapp/app_localizations.dart'; import 'package:selftrackingapp/networking/data_repository.dart'; import 'package:selftrackingapp/networking/db.dart'; import 'package:selftrackingapp/page/screen/root_screen.dart'; import 'package:selftrackingapp/page/screen/welcome_screen.dart'; import 'package:shared_preferences/shared_preferences.dart'; -import 'package:connectivity/connectivity.dart'; -import 'package:flutter/services.dart'; -import 'package:url_launcher/url_launcher.dart'; -import 'constants.dart'; + import 'utils/tracker_colors.dart'; -import 'package:dropdown_banner/dropdown_banner.dart'; void main() { runApp(MyApp()); @@ -99,7 +94,6 @@ class _HomeScreenState extends State { }); loadLang(); - _appVersionCheck(); } Future loadLang() async { @@ -160,100 +154,4 @@ class _HomeScreenState extends State { checkReachability(); return _createSplashScreen(); } - -//check for the latest build number set in the firebase remote config -//and show update dialog if necessary - void _appVersionCheck() async { - String key = Platform.isIOS - ? IOS_APP_BUILD_NUMBER_KEY - : ANDROID_APP_BUILD_NUMBER_KEY; - - //Get Current buildNumber of the app - final PackageInfo info = await PackageInfo.fromPlatform(); - - //In Android this refers to [versionCode]. In iOS [CFBundleVersion] - int currentBuildNumber = int.parse(info.buildNumber); - - //Get Latest version info from firebase config - final RemoteConfig remoteConfig = await RemoteConfig.instance; - - try { - await remoteConfig - .setDefaults({key: currentBuildNumber}); - - // Using default duration to force fetching from remote server. - await remoteConfig.fetch(expiration: const Duration(seconds: 0)); - await remoteConfig.activateFetched(); - - int remoteBuildNumber = remoteConfig.getInt(key); - - print("remoteBuildNumber $remoteBuildNumber"); - if (remoteBuildNumber > currentBuildNumber) { - _showUpdateDialog(); - } - } on FetchThrottledException catch (exception) { - // Fetch throttled. - print(exception); - } catch (exception) { - print('Unable to fetch remote config. Default value will be used'); - } - } - - void _showUpdateDialog() async { - bool isIOS = Platform.isIOS; - String title = "New Update Available"; - String message = - "There is a newer version of the app available. Please update now."; - String affirmativeLabel = "Update Now"; - String negativeLabel = "Later"; - - isIOS - ? showCupertinoDialog( - context: context, - builder: (context) { - return CupertinoAlertDialog( - title: Text(title), - content: Text(message), - actions: [ - CupertinoDialogAction( - isDefaultAction: true, - child: Text(affirmativeLabel), - onPressed: () => launchAppStore(IOS_APP_URL), - ), - CupertinoDialogAction( - child: Text(negativeLabel), - onPressed: () => Navigator.pop(context), - ), - ], - ); - }) - : showDialog( - context: context, - builder: (BuildContext context) { - return AlertDialog( - title: Text(title), - content: Text(message), - actions: [ - FlatButton( - child: Text( - affirmativeLabel.toUpperCase(), - style: TextStyle(color: Colors.blue), - ), - onPressed: () => launchAppStore(ANDROID_APP_URL), - ), - FlatButton( - child: Text(negativeLabel.toUpperCase()), - onPressed: () => Navigator.pop(context), - ), - ], - ); - }, - ); - } - - void launchAppStore(String url) async { - if (await canLaunch(url)) { - launch(url); - } - } } diff --git a/lib/page/screen/root_screen.dart b/lib/page/screen/root_screen.dart index df66714..a6811e0 100644 --- a/lib/page/screen/root_screen.dart +++ b/lib/page/screen/root_screen.dart @@ -1,5 +1,9 @@ +import 'dart:io'; + import 'package:async/async.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; +import 'package:firebase_remote_config/firebase_remote_config.dart'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:package_info/package_info.dart'; import 'package:provider/provider.dart'; @@ -8,20 +12,17 @@ import 'package:selftrackingapp/models/news_article.dart'; import 'package:selftrackingapp/networking/api_client.dart'; import 'package:selftrackingapp/notifiers/registered_cases_model.dart'; import 'package:selftrackingapp/notifiers/stories_model.dart'; -import 'package:selftrackingapp/page/screen/case_list_screen.dart'; -import 'package:selftrackingapp/page/screen/contact_us_screen.dart'; import 'package:selftrackingapp/page/screen/dashboard_screen.dart'; import 'package:selftrackingapp/page/screen/faq_screen.dart'; import 'package:selftrackingapp/page/screen/privacy_policy_screen.dart'; import 'package:selftrackingapp/page/screen/welcome_screen.dart'; import 'package:selftrackingapp/utils/tracker_colors.dart'; -import 'package:selftrackingapp/widgets/custom_text.dart'; import 'package:titled_navigation_bar/titled_navigation_bar.dart'; +import 'package:url_launcher/url_launcher.dart'; import '../../app_localizations.dart'; -import '../ios_faq.dart'; -import 'case_details_screen.dart'; import 'case_details_map_screen.dart'; +import 'case_details_screen.dart'; enum RootTab { HomeTab, CaseTab, ContactTab, RegisterTab } @@ -67,6 +68,7 @@ class _RootScreenState extends State { } }); _fetchCaseLatest(); + _appVersionCheck(); } void _handleFCM(Map message) async { @@ -240,4 +242,99 @@ class _RootScreenState extends State { ]; } } + +//check for the latest build number set in the firebase remote config +//and show update dialog if necessary + void _appVersionCheck() async { + String key = Platform.isIOS + ? IOS_APP_BUILD_NUMBER_KEY + : ANDROID_APP_BUILD_NUMBER_KEY; + + //Get Current buildNumber of the app + final PackageInfo info = await PackageInfo.fromPlatform(); + + //In Android this refers to [versionCode]. In iOS [CFBundleVersion] + int currentBuildNumber = int.parse(info.buildNumber); + + //Get Latest version info from firebase config + final RemoteConfig remoteConfig = await RemoteConfig.instance; + + try { + await remoteConfig + .setDefaults({key: currentBuildNumber}); + + // Using default duration to force fetching from remote server. + await remoteConfig.fetch(expiration: const Duration(seconds: 0)); + await remoteConfig.activateFetched(); + + int remoteBuildNumber = remoteConfig.getInt(key); + + if (remoteBuildNumber > currentBuildNumber) { + _showUpdateDialog(); + } + } on FetchThrottledException catch (exception) { + // Fetch throttled. + print(exception); + } catch (exception) { + print('Unable to fetch remote config. Default value will be used'); + } + } + + void _showUpdateDialog() async { + bool isIOS = Platform.isIOS; + String title = "New Update Available"; + String message = + "There is a newer version of the app available. Please update now."; + String affirmativeLabel = "Update Now"; + String negativeLabel = "Later"; + + isIOS + ? showCupertinoDialog( + context: context, + builder: (context) { + return CupertinoAlertDialog( + title: Text(title), + content: Text(message), + actions: [ + CupertinoDialogAction( + isDefaultAction: true, + child: Text(affirmativeLabel), + onPressed: () => launchAppStore(IOS_APP_URL), + ), + CupertinoDialogAction( + child: Text(negativeLabel), + onPressed: () => Navigator.pop(context), + ), + ], + ); + }) + : showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: Text(title), + content: Text(message), + actions: [ + FlatButton( + child: Text( + affirmativeLabel.toUpperCase(), + style: TextStyle(color: Colors.blue), + ), + onPressed: () => launchAppStore(ANDROID_APP_URL), + ), + FlatButton( + child: Text(negativeLabel.toUpperCase()), + onPressed: () => Navigator.pop(context), + ), + ], + ); + }, + ); + } + + void launchAppStore(String url) async { + if (await canLaunch(url)) { + launch(url); + } + } }