can I capture global variables in android, with ionic 5 capacitor? - android

I need to do a configuration, with android and iOS that when doing the deployment accepts the change, it is configured with firebase, which when I create a project and configure it, gives me a file google-services.json and in iOS a GoogleService-Info.plist, what I need is that for different environments, which are created in firebase, for example I would like to add the file google-service.json for the production environment, but if it is in staging, use the google settings- service-staging.json and so on.
So when you call the change in the project's build.gradle, pass it a global variable (I don't know if it can really be done)
def servicesJSON = file('google-services'+enviroment+'.json')
Something like this, so that depending on what comes to you, you know in what environment they are deploying...

For flavors (stage,prod) you should place separate json files in corresponding directories for android project.
e.g. https://android.jlelse.eu/how-to-use-different-google-services-json-file-with-multiple-product-flavors-android-7853d98dd6c0

Related

Releasing Mobile (React Native) Artifacts with Config File

Taking inspiration from The Twelve-Factor App: V. Build, release, run, I'm working on updating our CI/CD pipeline with these three distinct steps in mind for an app being built with react-native-web.
Specifically, I want to:
Build: generate an environment agnostic artifact of the code for each platform (web, android, ios)
Release: take an artifact and a config file (API URLs, API keys, debug settings, etc), and release to each platform
This is trivial for web, which is what The Twelve-Factor App had in mind. My question is how do I read a config file on mobile platforms and how can I incorporate this with react-native-web build artifacts? Does my artifact need to contain all of the source code and dependencies so I can pull in the config at release time and build then?
Ideally, each artifact would contain code compiled for each platform that somehow knows how to pull in a config file and do something with it. Next best would be to have the source code for each platform that I can compile with a config file at release time. Third best is have a way to give each distribution enough information at release time so it can request the config at runtime.
Full disclosure, I know nothing about building and deploying mobile apps so I apologize if there is an obvious solution for this!
It's similar for Android. Once the build binary is created it's immutable.
So unfortunately that negates option #1. We can't do anything else with the binary once we build it.
I think for react-native option two is the best approach.
Essentially you'll need to build the apps at release time once you have resolved what your configs need to be. That avoids any overhead of loading stuff at runtime in option #3 and still matches nicely to Twelve Factor. You'll still have a mobile binary that matches the same configuration as your release type.
For actually reading those values, you can just drop the config file into the project's root and we can help with the setup to pull them in.
I'll be glad to discuss those details if you'd like.
UPDATE:
Anything iOS does we can do (almost as well)
Current build tools compile all code into bytecode classes.dex and compress all resrouces into resrouces.arc but res/raw is left untouched.
This gives us a place to inject our files.
From there, the app will be able to read and parse at runtime.
For iOS, the build and (non-App Store) release process works like this at a high level:
Archive your project in Xcode, which results in an .xcarchive artifact.
Export your archive which signs and generates an .ipa file.
Either host this .ipa file yourself (with some additional metadata files) or upload it to a service like HockeyApp for distribution.
There are a few ways that you can manage config inside an Xcode project. One fairly common and straightforward way is to use the info.plist file to store custom keys and values. The app can then look up and use these values at runtime.
In the scenario you describe, it sounds like you want to be able to inject specific config values after step 2 but before step 3. Fortunately, the .ipa file generated during step 2 can be extracted, which will reveal a Payload folder containing an .app file. This file can be inspected, and inside you will see, amongst other things, the app's Info.plist. Modifying this file will allow for injection of whatever config values you want to set.
This will save needing to manage configs inside the Xcode project, and creating a separate archive for each configuration of the app. However what this doesn't solve is step 3. You are still going to need to distribute each configured .ipa file separately.

How to build multiple apps from one project with different app name, icon, settings,

Building iOS and Android apps with only one project is pretty awesome. But is it also possible to build multiple apps with different names, icons, etc.
This could be very helpful if you build apps with the same layout and maybe 95% same of the functions/code/algorithms:
different target-groups (recipes app for fitness, vegans, veggies, eco,...)
different sports (news for football, basketball, tennis ...)
different customers (business app for customer A, B and C)
...
Things, which could be different per app:
App name
App icons
SplashScreen
Design
Settings (API URL, ...)
Some code (default function/components maybe could get overwritten by app-based custom files)
Maybe it would be the perfect solution if you have a directory flavors where you can put all the files which you want to use to overwrite the default code-base.
Somebody here who released something similar or any ideas how to solve this?
This is a problem I have been solving in my projects last days. And I think I have some good (not perfect) solution so far.
Idea. We don`t have any built-in functions to help us handle this case, so we can use some external manipulation that can do the job. What we need is just multiple Android and iOS projects and single JS code base.
Implementation. I`ve come to this project structure:
ios
android
manager
src
ios and android folders is well known to you, they are native project folders.
src is a folder with JS code, you can organize it whatever you want
manager is most interesting one. Here we can store multiple native project files. We can have multiple native project folders in it, for example app1-android app1-ios app2-android app2-ios. And when we want to work on app1 we just copy app1-ios and app1-android to our root ios and android folders, so the actual project is app1. When we are done with app1 we can save android and ios folders to our manager and then just copy app2-ios and app2-android to root ios and android. And we are all good to develop our app2.
We can do it manually. But we are developers and we can make it much easier. I`ve written a PHP script that makes it as easy as php save.php -a app1 and php set.php -a app1 to copy from manager to root and backwards. Moreover, it takes care of not copying some unimportant staff (pods folder in ios, build in android etc.) and running pod install to ensure we have all pod in actual project.
I stick to one package.json file to have all npm modules installed once, so I don`t have to run npm install after each project switch.
Afterall, we can have as much projects as we wish in one repo, we can customize each one independently.
PS If you want me to share my scripts I`ll do it as fast as I can (need some time to prepare it for github and to write some more detailed instructions), just let me know.
I did this for about 100 different native apps per platform (iOS/Android), sharing the same code base. I manage this setup for about 2 years now and I am still happy with it.
Here is the iOS part:
I use targets with different plist/pch files.
Save files that shuld differ per app in a separate directories, named by the app name. Check the corresponding target, if adding the file to the project:
By using the same filename you can "override" the file for different targets.
The Android part:
I use one gradle module for the common part and one module per app for the customizing. I also use gradle variables for common values definitions (minSdkVersion, compileSdkVersion etc.). Only the following settings differs per app: applicationId, versionCode, versionName. Here is an example file for a custom app:
apply plugin: 'com.android.application'
android {
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
defaultConfig {
applicationId "..."
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 28
versionName "1.0"
}
signingConfigs rootProject.ext.signingConfigs
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release
}
}
}
dependencies {
compile project(':apps:common')
}
You can override the resources (app icon, images, strings etc.) in the corresponding res folder of an app module (use the same filename for the same resource).
Don't forget to include all your modules in the settings.gradle.
You can use multiple targets.
You can create target by below steps :
Go to project navigator -> Right Click on your app name under target -> Select Duplicate -> from popup select Duplicate only .
And you will find duplicate target. Now you can take another or extra app icon and launch image in your assets and for that target you can set it.
Refer below screenshots for better understanding!
So, select newly maded target and make changes by selecting it from general tab.
You can refer this great tutorial by Appcoda!
We do something similar to what you want do, but on a much more limited range. We have various builds of our app, each with a name, logo, design, API URL...
It's only built for android, so it's essentially a few flavors as mentioned in the comments above. (I don't know what the equivalent system is for iOS)
But we also use https://github.com/luggit/react-native-config that provides a way to share these specific variables/settings between both the native (android and iOS) and javascript code. All you need is setup a .env.myversion file which contains the settings you need, something like:
API_URL=https://my.server.com/
LOGO_FILE=/path/to/the/right/logo
COLORSET=shades_of_blue
The correct file is pulled in at build-time so your app has the correct version of each setting and you can then call these variables from within your code, and branch based on what version you're using. The benefit is that it works everywhere. The downside to this is that you might be shipping some extra stuff with your apps if you have all this in the JS layer rather than defining it in the build system with flavors. I guess it's a tradeoff between convenience and performance/efficiency that you need to decide on based on your use-case.
In Xcode you can simply duplicate your Target and create a new one with a new plist which means you can change the app name, icon, splash bundle and other settings as required.
In XCode you can Make different build confiugrations for different-different apps in single project(means Dev,alpha,beta,Prod,Debug,Release),With the help of this solution you are able to change AppName,AppIcon,BundleId,URLs,SplashScreen etc for different builds.
I created a website, where users can specify their content, icons, name and package name, and many other options like including advertisement SDK in app. After small payment, user can get created APK with certificate or sign app manually. Generation of apk takes a few seconds. APK is ready to upload to PlayStore. This is project was with high price, but my customer is happy.
How it done?
Create some templates for code. You can buy it on some sites.
Split optional code in separate files
If you can't splite code in separate file (for AndroidManifest.xml, for example), you can include comment with some keys (instructions for post-processing)
Generate icons from user content/specified icons.
On user request, just copy all selected files in same directory, with simple text processor remove unnecessary code (use comments from step 3), complile it, ship APK to user.
Basically there are two different options:
Option 1: OS Builds/android flavours:
Using iOS Builds and/or android flavours have some disadvantages in a react-native project:
React-native link only links the first target on Xcode. You’ll have to manually link libraries for further targets. However in react-native 0.60+ there is auto-linking, and this could be fixed with a little tweak to the podfile
React-native run-android may fail to launch the app if the app id differs from the package id.
Might be complex overtime to maintain a single native project with all the different builds/flavours and all the assets and resources that are included in a single project.
Requires some extra knowledge with xcode and android studio/gradel.
Option 2: Natives approach (which I personally prefer)
Based on the answer of Roman Osypov, I have came up with this approach with an implementation.
Currently each react-native project has two native folders, ios and android, each one represents the native project of the platform.
Lets assume we have two different bundles/apps with the same code base but different resources/assets etc..
CabApp TaxiApp
The main idea is to swap but keep in sync the root ios and android folders with their "natives" source.
create a folder in the root of the project called natives
copy the current ios and android folder of the main project to the
natives folder, lets assume it's CabApp, and rename those folder
into the following: CabApp-ios CabApp-android
do the same for TaxiApp, but remember to change the bundleId, the
identifiers, assets etc.. of the native projects
delete ios and android main folders in the root of the project
and add them the .gitignore
install the following dev dependencies yarn add -D rimraf sync-directory ttab
now the first time the project is pulled you need to set your "app"
for example if you want to work on TaxiApp you can execute the
following: yarn ios-TaxApp which you can define in the scripts in
the package.json
yarn rimraf ios && yarn rimraf android && yarn syncdir natives/TaxiApp-ios ios -c && yarn syncdir natives/TaxiApp-android android -c && cd ios && pod install && yarn
Basically this command deletes the root folders ios + android and sync the folders from the natives folders to the root ones.
The final step would be syncing back and watching the modifications from the "temp" ios and android folders back to the natives respective app-platform.
now in your start script for ios for example, you can add the following script
yarn ios-TaxiApp which you can define as:
yarn ttab 'yarn syncdir ios natives/TaxiApp-ios -w -c' & yarn ttab 'yarn syncdir android natives/TaxiApp-android -w -c' & yarn ttab 'yarn react-native run-ios --simulator=\"iPhone 11\"'

Modifying code to suit different configurations in Android Studio

I have different configurations for my Android project (e.g. google, amazon). Gradle allows generating BuildConfig parameters, that can be checked at runtime, but this isn't what I am really after. I want to have a particular code (method, class, etc) to be present or absent (not just bypassed) in the project, depending on configuration.
This is how I implement that in Eclipse. I have a folder in an Eclipse project (named e.g. platform-specific), not included in BuildPath as well as several Ant scripts (make-google, make-amazon), that copy relevant files from platform-specific folder to src folder and delete irrelevant files from src folder.
Since Eclipse provides an Ant window to view all scripts, I can run a particular script and reconfigure the project to suit chosen configuration.
Is there a way to do that in Android Studio? I know that Gradle allows running and even importing an Ant script, but it isn't a convenient as with 'true' Ant, and I can't find a way to choose a script to run. Maybe Gradle provides its own way to do that?
For two flavours it will work, but if I have say 3 flavours, module 1 appears in flavours 1 and 2, module 2 in flavours 1 and 3, will it mean replicating those modules in each folder? So, every time I modify a code a such a module, I need to replicate the modification in another folder.
Not if you organize your code.
You appear to be using "modules" generically. Android Studio has a specific definition of that term (what Gradle refers to as sub-projects). And you can leverage those to help your cause.
Suppose that you create google, amazon, and yandex product flavors. Then:
Any code that is common to all three goes in src/main/.
Any code that is unique to a single flavor goes in that flavor's source set (e.g., src/yandex/).
Any code that is shared by two flavors goes into a library module that is added to the appropriate flavors using flavor-specific dependencies (e.g., yandexCompile and amazonCompile).
In all cases, there is one copy of your code. Whether it can go in the application module (e.g., app/) or goes into a library module depends on which flavors need that code. For a scenario like this, dependency injection will help you manage what code then gets wired together for each flavor.

What is the Structure/Architecture for White Label Application

I am preparing a white label application (called product later in this post) and I want to set up a very good architecture. This will easily and quickly set up a new client by changing the design, activating features...
I have several servers (dev, pre-prod, prod) so the flavorDimensions server are present in the product and the flavorDimension client is on the client side.
I thought of this solution:
Set up one git per customer and one git for the product.
Clients will have access to the product code by git submodule. This allows me to separate the specific code from my client and the source code of the product.
Git -> Client 1
Submodule -> Product v1
Git -> Client 2
Submodule -> Product v1.2
...
Git -> Product v1.4
But I have a problem how to run it all correctly. The use of flavorDimensions client is hard because I need to make a copy-paste (with gradle) from my submodule to the app module before the build.
The generation of this structure breaks Gradle because its need to be synced every time. (Always Sync Now flag on Android Studio)
So I ask myself, is a good architecture or not ? What do you think ?
Or do you have other ideas and how to implement them?
Thanks for your support.
Hmm interesting take on it.
I have done similar things, but not quite like that. I use flavors for the deltas only. For example, themes, skins, app_icons, and Strings.xml. Maybe a few variations in layout or activities, but do my best to keep it generically served to minimize the maintenance of the code for various customer deployments as each additional flavor slows down the CI process significantly.
However, one key difference in what you are doing is you are not building a platform (aka everyone uses the same code GIT repo and API Server per se, you are building stand alone applications to supply full code and everything else to individual customers.
This sounds like it could be a maintenance nightmare, but if your situation requires that customer's get access to the code base for their product flavor, then I guess it makes sense. Not sure why they would get access to the code though as it is your product you are reskinning for customers right?
At any rate, you aren't asking for me to ask your reasoning haha, you are asking about architectural solutions. So here is my thoughts.
Make a task that copies the respective folders into a new module structure exactly like the modules you have now, but with changes to the package name so that they all slightly differ, then run your GIT push. You can run bash files from Gradle, so you can either write scripts and execute them from relative paths or you can write it directly in your Gradle file itself.
So I would update my Gradle to have separate dependency file like libs.gradle
->Put dependencies in that file like ext.libs {gson:"com.whatever:version"}
->apply from ../libs.gradle
->dependencies { libs.gson, etc..}
So i would assume your build task would do
->Create a new Module from All Source by copying files properly with new names if necessary to rename
->if using maven server, then deploy aar or jar for compiled new module
->Create a new dynamic Gradle file libs.gradle to replace current libs.gradle file that is updated source pointer to deployed artifacts
or created module
->run gradlesync, when complete run assembleRelease, then you can do your git push etc..
All of this can be synchronized and done from terminal and localized into commands. Flavors may not help a ton in this area as they are part of the build process so you kinda need pre build processes which you can create tasks to do pre-build, but the key is the packaging of dependencies and updating your libs.gradle file and making sure that you replace it per flavor. Or if you have fixed flavors you can just make a specific libs.gradle for each flavor and update it based on the compiled dependencies.
I don't know your overall picture, but it is all doable. Hope that helps. Goodluck.

In iOS do we have something like Gradle Build Flavors on Android

In iOS do we have something like Gradle Build Flavors on Android.
Basically I want to integrate Applause SDK with my app but I dont want that code to be part of the release build. I only want to use applause sdk only to distribute the app internally and for bug reporting.
If there is nothing like flavors then what is the best way to do this.
You can make use of Schemes and Build configurations in Xcode. Here's the official documentation: https://developer.apple.com/library/ios/recipes/xcode_help-project_editor/Articles/BasingBuildConfigurationsonConfigurationFiles.html
After you create a build configuration, you should edit your scheme to use that build configuration. For that click on your scheme and select Edit Scheme.
In short, the process is:
Create a build configuration
Set some custom flags for that configuration. For this, go to your target, select Build Settings tab, and search for Preprocessor Macros. There you'll be able to add custom flags
Edit your scheme, or create a new scheme, to use your build configuration.
In your code, you'll have to ask if the flag is available using preprocessor macros:
#ifdef APP_STORE
//do something
#endif
There are several approaches you can take to build an iOS app in different flavors:
Different versions of a resource file
Use a custom build variable to switch between different versions of a resource file. This article discusses how to build an app with different icons.
For *.strings files and resources linked in *.storyboard files the suffixing approach suggested in the first item did not work for me. So I added a Run Script build phase early in the pipeline. Using a script you are free to do whatever you want before the usual build chain handles your files. This is great for dynamic file generation or advanced file selection logic. As a switch you can (again) use a custom build variable.
Modifiying code
Use a compiler flag as suggested here. These can be checked using the preprocessor.
Alternatively you can (again) check custom build variables. To make them accessible add them as a key in a plist file.

Categories

Resources