2. AppCenter.ms integration


Prepare Flutter project

Grab the latest version of AppCenter packages from the provided links below and add them to your project.

  1. flutter_appcenter_bundle - pub.dev
  2. package_info - pub.dev
  3. run flutter pub get

Adding package_info allows us to easily access various bundle properties such as ID, identifier, version, etc. Useful for enterprise apps when updates must be handled manually.

Note: Official AppCenter packages are not yet available for flutter, thus for the time being we must resort to community driven implementations.


Appframe packages in pubspec.yaml

If you are consuming Appframe packages from Azure DevOps repositories you must provide a Private Access Token (PAT) in the package url.

The PAT you provide must have read access to the reposities you are targeting. Read more at docs.microsoft.com

Otherwise, the AppCenter build agent will fail while trying to execute 'flutter pub get' as it will not be able to fetch the necessary packages without proper authentication.

Example of how your Appframe package dependencies should look like

   
  appframe_resource_api:
    git:
        url: 'https://YOUR PAT@dev.azure.com/OmegaAS/MobileTeam%20-%20Core/_git/ResourceAPI''
        ref: 0.1.0


Integrate services

After the dependencies are fetched we are ready to integrate AppCenter into the project. We do this by starting AppCenter services in main() method. The GUIDs can be added later when the AppCenter apps are created. Change the placeholders when you have correct GUIDs to ensure that crash reporting and analytics are properly reported.

Make changes in main.dart:

1. main() function changes:


        void main() async {
            WidgetsFlutterBinding.ensureInitialized();
            await AppCenter.startAsync(
                appSecretAndroid: 'AppCenter GUID', // Replace when you've created Android app in AppCenter.ms
                appSecretIOS: 'AppCenter GUID',     // Replace when you've created iOS app in AppCenter.ms
                enableDistribute: true,
            );
            await AppCenter.configureDistributeDebugAsync(enabled: false);
            
            runApp(MyApp());
        }
        

2. _MyAppState variables:


            PackageInfo _packageInfo;
            bool _isCrashesEnabled;
            bool _isAnalyticsEnabled;
            bool _isDistributeEnabled;
            

3. _MyAppState override initState():


            @override
            void initState() {
                super.initState();
               
                AppCenter.trackEventAsync('_MyAppState.initState');
                PackageInfo.fromPlatform().then((v) {
                    setState(() {
                        _packageInfo = v;
                    });
                });
                AppCenter.isCrashesEnabledAsync().then((v) {
                    setState(() {
                        _isCrashesEnabled = v;
                    });
                });
                AppCenter.isAnalyticsEnabledAsync().then((v) {
                    setState(() {
                        _isAnalyticsEnabled = v;
                    });
                });
                AppCenter.isDistributeEnabledAsync().then((v) {
                    setState(() {
                        _isDistributeEnabled = v;
                    });
                });
            }
            



Add build scripts

Flutter is not a first class citizen in AppCenter, thus we have to provide it with our own build scripts. Luckily, the guys at AppCenter have us covered.

Build files repository can be found at github.com but it's recommended to use the scripts from the platform specific sections below to avoid common issues such as build versioning, etc.

In addition, for your Android project, you must alter it's .gitignore file to comment out or remove the following lines:


        gradlew
        gradew.bat
        gradle-wrapper.jar
        

After doing so build your android project to and commit the these files to your repository.


iOS build script

#!/usr/bin/env bash
#Place this script in project/ios/

# fail if any command fails
set -e
# debug log
set -x

# Uninstall current cocoapods version
sudo gem uninstall cocoapods
# Install newest cocoapods version
sudo gem install cocoapods
# Install Flutter SDK
cd ..
git clone -b beta https://github.com/flutter/flutter.git
export PATH=`pwd`/flutter/bin:$PATH

# Ensure current channel is the STABLE branch
flutter channel stable
flutter upgrade

# Debug Flutter info
flutter doctor -v
flutter pub get -v
flutter precache --ios

# Sets the FLUTTER_ROOT path
echo "##[section]Installed flutter to `pwd`/flutter"
export FLUTTER_ROOT=`pwd`/flutter

# Get CocoaPods
echo "##[section]Starting: POD's"
cd ios/
pod update AppCenter/Distribute
pod install --repo-update
echo "##[section]Finished: POD's"

# Build app
flutter build ios --release --no-codesign


Android Build Script

#!/usr/bin/env bash
#Place this script in project/android/app/

cd ..

# fail if any command fails
set -e
# debug log
set -x

cd ..
git clone -b beta https://github.com/flutter/flutter.git
export PATH=`pwd`/flutter/bin:$PATH

flutter channel stable
flutter doctor

echo "Installed flutter to `pwd`/flutter"

# make gradlew an executable
chmod a+rx android/gradlew

# if you need build an APK in addition to your AppBundle, uncomment lines below and last line of this script.
# build APK
flutter build apk --release --build-number=`date +%s`

# copy the APK where AppCenter will find it
mkdir -p android/app/build/outputs/apk/; mv build/app/outputs/apk/release/app-release.apk $_

# if you need build bundle (AAB) in addition to your APK, uncomment line below and last line of this script.
flutter build appbundle --release --build-number=`date +%s`

# copy the AAB where AppCenter will find it
mkdir -p android/app/build/outputs/bundle/; mv build/app/outputs/bundle/release/app-release.aab $_


Android Prerequisites

Google Play Store requires an initial version to be published before AppCenter is able to deploy new builds to it.

You need to publish your app in Alpha, Beta or Production track for AppCenter to be able to push new versions. Your build versions must be in line as follows Alpha > Beta > Production.

For up-to-date documentation for the publishing process please refer to flutter docs at flutter.dev


Add AppCenter apps

In your AppCenter organizations you will have to create an app per desired platform for your project. So if you are targeting both Android and iOS, you will add an app for each platform.



Acquire app GUIDs

After creating an app, you can find the unique identifier in the Overview section. Replace the android placeholder in your main.dart with this value.



Connect to repository

In the Build page select Azure DevOps and navigate to your project repository. Then in each app you will be able to see a list of branches in your repository. The little cog-wheel on the right of the branch allows to add a build configuration.


iOS build configuration

AppCenter requires the developer to upload the first app version manually to AppStore or TestFlight before it can distribute any new builds.

To configure an iOS build you will to get the provisioning profile and a signing certificate for the iOS app to be tested on a real device in AppCenter and distributed to desired stores.

Read on how to setup profile and certificate in your build here - https://docs.microsoft.com/en-us/appcenter/build/ios/uploading-signing-files

Make sure you provide a Distribution provisioning profile if you wish to deploy to AppSTore or TestFlight. Make sure that your provisioning profile includes the certificate you're providing.


Android build configuration

Mobile team recommends to configure your gradle build to automatically sign android builds.

Android can be setup to be distributed to Google PlayStore, AppCenter private distribution groups or distributed publicly with a shared link.

If you're publishing to GooglePlay Store, it's recommended to Build Android App Bundle in addition to your APK, as it can drastically reduce the application size on the device. With Omega365 Timesheet a reduction of 60% was achieved.


Build configuration wrap-up

When you hit Save & Build AppCenter will start to build from the last commit on the configured branch. You can configure many builds from different branches, with only one concurrent build per app. Configuring different distribution groups for different branches allow you to simply configure both beta and release branches to distribute to testers or end users.

If all goes well, once the build completes you will be able to view the basic UI test you are provided for free. AppCenter will ensure the app at least starts up, giving confidence that the build worked correctly and there are no glaring errors in the code.

Any crashes found in apps built in AppCenter will be captured in the Diagnostics area, and analytic information recorded using the appcenter_analytics flutter package will appear in the Analytics section. As mentioned previously, the retention period is only 90 days, although the data can be exported to Azure blob storage or Application Insights for longer retention and analysis.


Link AppCenter to Developer accounts

AppCenter need to be linked to Google Play / Apple AppStore developer account. For up to date guidelines it's best to follow official AppCenter documentation.

The link only needs to be setup once per developer account and then will be used through-out AppCenter.

Google Play Store  - docs.microsoft.com

AppStore - docs.microsoft.com


Troubleshooting

Common issues that have been solved before.

Build failed on flutter pub get

If the pub get error states that the password could not be read for a git dependency, you need to include a PAT into the package URL. You can create and manage your PATs in Azure DevOps account settings. docs.microsoft.com


AppCenter builds with old package references

Run "flutter packages upgrade" and commit the updated pubspec.lock file to your branch before building again.

Grade does not have execute permission

You should change the ownership of the project directory to your user, or move the project to a directory with execute permissions

Execute the following command in Git Bash while in the root directory of your flutter project:


    chmod a+rx android/gradlew
    


Related articles

Placeholder "LocalizeWeb2016" failed