For the last year, we’ve been using React Native more and more. During this time we’ve worked on several projects that had teams build up from developers with different backgrounds: native or frontend.
When you want to build a mobile app for both iOS and Android it is ideal to have at least one person in a team with knowledge about each platform, but it is not always possible. In these situations, developers have to quickly gain knowledge about other OS’s specifics or ask their colleagues for help.
That’s why we came up with the idea to gather a few important things you should know about Android if you are coming either from a frontend or iOS background.
Side note: This article won’t describe every detail about the subject. The main goal is to have all the important points in one place. I will also provide you links to the documentation or other sources where you will find more details about each topic.
Android project structure
The first thing to know is the basics about Android project structure; what folders or files you can find there and what they are responsible for. There is definitely more than I will show you here, but I would like to focus on files that you will most likely need to change during the development.
AndroidManifest.xml is the file that describes your app. This is the place where you can set your app name, icon and other attributes as part of the application tag. It also contains information about user permissions that need to be granted by the user in order to work correctly. Another useful tag in the manifest you can use is uses-feature. By adding it you can define what feature your app needs in order to be fully functional e.g. NFC. If its property required is set to “true”, then your app will not be available on devices that do not support that feature.
Another important file is build.gradle. It is actually two files because you can find two of them; one in at root folder and another in an app folder. The first one is the main build file for the whole project. It is used mostly for things that are common for all modules. In your newly created React Native app, you have only one module (app folder) so its build file will have much more information. Apart from the things like dependencies or repositories, that will be mostly edited by the react native linking functionality, you will also find android section.
Let’s have a look at build.gradle
files first:
// SampleProject/android/build.gradle
buildscript {
ext {
buildToolsVersion = "29.0.2"
minSdkVersion = 16
compileSdkVersion = 29
targetSdkVersion = 29
}
...
}
// SampleProject/android/app/build.gradle
android {
compileSdkVersion rootProject.ext.compileSdkVersion
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
defaultConfig {
applicationId "com.adamg.sampleproject"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "1.0"
}
...
}
When you look at android/app/build.gradle, you can see that some values are referred from rootProject
. What it means is that you app will use some project-wide properties that are defined in the top-level build.gradle
file that is located in android
folder. Using settings from the main build file lets you define configurations that apply to all modules in your project.
Now, let’s focus on module-level build.gradle
. There are a couple of important properties so let’s go through each one.
compileSdkVersion – it tells Gradle what version of Android SDK to compile your app with. It is recommended to compile with the latest SDK.
minSdkVersion – it describes the minimum Android OS version that your app will support. React Native supports all Android versions higher than 4.1 (API 16).
targetSdkVersion – it specifies the Android version your app is targeting. You can read more about these three properties in a very detailed post.
versionName – this is the version of your app that will be visible to users.
versionCode – this is basically an integer number that describes your build version. It is used to determine which application file is newer. You will not be able to upload new .apk with this number lower or equal to the previous version.
Res folder contains all application resources such as layouts, drawables or UI strings. In React Native you will most likely keep icons or images in a global folder (outside Android project) so you can share it with iOS version of the app, but here you will keep for instance your app icon. I will describe how you can do it in the next section.
Setting your app icon
If you’ve read this article up to this point you should already know that we have to put the app icon file inside res folder and then set it in the AndroidManifest.xml file. But let’s go one step back and see how we can easily create this icon and import it to your project.
Android is used on different devices that have different screen resolutions. Because of that, we need to generate our icons in a couple of different sizes. The easiest way to do this is to use Image Asset Studio in Android Studio. Take a look at the detailed instruction on how to do it. Alternatively, you can use Android Asset Studio but currently, it does not support adaptive icons.
Both solutions will generate icons in different sizes that you can import to your project. If you used the second option, check the gif below to see how to quickly import your files to the correct folders just by copying and pasting generated folders to the res folder. After that, you only have to set the icon in the AndroidManifest.xml file. It may not be required if you didn’t change the default file name.
Signing your app
Now you know how to set up your android app, and you also know how to add your beautiful icon. You have implemented your first screen in React Native and you want to distribute your app for testing purposes, let’s say, through Firebase App Distribution. After building the app and trying to upload it the error message appears, saying something like “You must sign your app in order to upload it”. So what does this signing mean?
Android requires that all .apk files are signed with a certificate. You can think about it as a digital fingerprint of your app. Thanks to this, no one without this certificate can build your app (even with the full source code) nor update the existing app with the original one.
How to sign the app?
1. Generate your Keystore file and key using Android Studio. This process is quite long to describe, so check the official instructions.
2. Add signing configuration to your build.gradle file (the one in the app folder). This step is not required but we all like to automate things. This will make it possible to build and sign your .apk with a single command ./gradlew assembleRelease.
To accomplish that, add these lines to your build file.
android {
...
defaultConfig { ... }
signingConfigs {
release {
storeFile file("my-release-key.jks")
storePassword "password"
keyAlias "my-alias"
keyPassword "password"
v2SigningEnabled false
}
}
buildTypes {
release {
signingConfig signingConfigs.release
...
}
}
}
This will automatically sign your app, but it is not an ideal solution. The build.gradle file is strictly related to the project so you have to keep it in your version control system, but you don’t necessarily want to keep Keystore passwords there as well. So, to improve this a little bit, we can add a new file in the root project directory named keystore.properties and write there all the secret data.
storePassword=password
keyPassword=password
keyAlias=my-alias
storeFile=myStoreFileLocation
After this step, we can edit the build file. First thing we have to do is to import the file and then read the values from it. See the updated build.gradle below:
def keystorePropertiesFile = rootProject.file("keystore.properties")
def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
android {
...
defaultConfig { ... }
signingConfigs {
release {
storeFile file(keystoreProperties['storeFile'])
storePassword keystoreProperties['storePassword']
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
v2SigningEnabled false
}
}
buildTypes {
release {
signingConfig signingConfigs.release
...
}
}
}
Thanks to this you can safely commit build.gradle file to your git repository and add the keystore.properties file to .gitignore so your secrets won’t be uploaded.
Summary
That would be it for now. I hope that after reading this post you will feel at least a little more comfortable while navigating through your Android project. There is still much to learn! I did not cover things like app release or fastlane configuration, but I didn’t want this to be to long 🙂