Author avatar

Pavneet Singh

Boost Android Development Skills To Produce Quality Apps

Pavneet Singh

  • Dec 15, 2018
  • 27 Min read
  • Dec 15, 2018
  • 27 Min read


Android OS has several releases over the past 2 years. These updates have introduced astonishing features thus causing several significant functionalities to become deprecated. This technological evolution has led to Android development challenge of keeping an app compatible with the different levels of Android OS, while keeping UI and UX elegant.

Throughout this tutorial, You will learn about how you can implement UI, UX, code quality, security, and third party libraries, along with tips and tricks to boost the quality of application with minimal efforts.

Quick Start Guide

The following guide will give you an instant notion about the basic android development terminologies in simplest terms, that is being used throughout this tutorial.

  • View: A View represents a graphical rectangular on the screen. Every GUI component like Button, TextView, EditText are inherited from View class.
  • ViewGroup: A ViewGroup is a layout container, which is responsible for positioning multiple views on the screen. There are various decedents of ViewGroup like LinearLayout, RelativeLayout, ConstraintLayout etc, to position child views in linear or relative fashion.

  • Activity: An Activity is a single screen view that is visible to user. An application can consist multiple Activities for separate functionalities, for e.g splash, Login , signUp etc.
1// To create activity, a class must extend Activity or AppCompatActivity class
2 // AppCompatActivity is used to support ActionBar and design features for older version
3public class MainActivity extends AppCompatActivity {
5    @Override
6    protected void onCreate(Bundle savedInstanceState) {
7        super.onCreate(savedInstanceState);
8        // static view for MainActivity
9        setContentView(R.layout.activity_main);
10    }

Using a backward compatibility component from a support package requires additional dependencies, which will result in increasing the APK size.

  • Layout XML file: XML is a tag based file which represents a static layout design view, which can be embedded into activities. A layout file can be attached to an Activity by calling setContentView(int) method.

    A single XML file can be attached with multiple activities and there are many types of XML files, to design menu, shapes, selectors or to store global constant values.**

    The design can also be created at run time (while the app is running) using Java or Kotlin code. This is helpful when you have no idea about the number of views to be drawn on the screen in dynamic environment.

  • Application: An application is a single entity which represents the whole app. It is the first instance to be initialized by Android OS, so often being used to declare global constants or configure services like crash-reposting, analysis, dependency injections which are required to run the app.

    You can provide your own implementation by creating a subclass and specifying the fully-qualified name of this subclass as the "android:name" attribute in your AndroidManifest.xml's tag.

  • LifeCycle: LifeCycle corresponds to a series of methods which will be invoked by the Android OS according to the current state of the process. LifeCycle methods are described below:
1public class MainActivity extends AppCompatActivity {
3	 // called only once when activity is created
4	 // so optimal place to initialize GUI component and services
5	 @Override
6     protected void onCreate(Bundle savedInstanceState){...};
8 	// called everytime when user comes to this activity
9	 @Override
10     protected void onStart(){...};
12 	// called when activity is completely visible
13	 @Override
14     protected void onResume(){...};
16 	// called when activity is partially visible
17 	// covered by some dialog
18	 @Override
19     protected void onPause(){...};
21     // called when current activity is covered by another activity
22     // when user go to next activity
23     protected void onStop(){...};
25 	// called when activity's object is destroyed and no longer accessible
26 	// when user press back-press button
27	 @Override
28     protected void onDestroy(){...};
29 }

These methods are invoked in a serial order in normal scenarios. There are many other methods, which can be overridden when required, as shown in below image.


  • Context : A context is a special object which is used to access the resources and files (assets, XML constants) contained in application. Activities has their own context and can be used as YourActivityName.this which is internally initialized by Application object.

    getContext() will give current host activity's context and getApplicationContext() will give the context of the application. These methods are not accessible in normal classes but they can be passed as values.

  • Manifest : manifest.xml contains information about app which is required by android OS to grant permission to access resources like storage, Internet, SMS and registered activities etc. Every activity or customize application class (if there is any) should be registered in manifest.xml.

    A boilerplate manifest file

1<?xml version="1.0" encoding="utf-8"?>
2<manifest xmlns:android=""
3	package="">
5 	<!--needs to be added to get access to Internet -->
6	<uses-permission android:name="android.permission.INTERNET"/>
8    <application
9 	  <!--app icon-->
10        android:icon="@mipmap/ic_launcher"
11 	  <!--app name-->
12        android:label="@string/app_name"
13 	  <!--aa-->
14        android:roundIcon="@mipmap/ic_launcher_round"
15 	  <!--support for right to left languages-->
16        android:supportsRtl="true"
17 	  <!--XML based theme file-->
18        android:theme="@style/AppTheme">
20    <!--Register Activity, declare this activity as launcher using intent-filter
21    mean first activity to be opened, on click of app icon-->
22        <activity android:name=".MainActivity">
23            <intent-filter>
24                <action android:name="android.intent.action.MAIN" />
26                <category android:name="android.intent.category.LAUNCHER" />
27            </intent-filter>
28        </activity>
30        <activity android:name=".AnotherDefaultActivityYetToBeCreated"/>
32    </application>
34 </manifest>
  • Gradle: The build system used to download dependencies, tools and to manage application configuration settings to build project.

    • There are two gradle files:
      • Project : which is used to configure project and sub-projects
      • Module : which is used to configure app, dependencies,SDK versions etc.
  • A final Java class file that consists of static final int constants and array constants. Every file or unique id ([email protected]/name attribute of views), is given an int value by the gradle and these constants are used to access those components and files in project.

    • This file is created under app\generated\source\r\debug\your_package_name\ directory and should never be modified by hand.
    • The R file is especially useful when trying to get access views in code. For example, the View method findViewById() takes in an value based on the component to be selected, such as


An Android application should provide a simplified, engaging interface with meaningful motion like elevation, ripple, and material design.

Android 5.0 Lollipop introduced the concept of Material design, which can also be implemented on older versions by using the Android Design library which provides material design components to make an elegant app.

Steps to include design library as dependency

  1. Open build.gradle (module)
  2. Add the following dependency inside the dependencies block

    1compile ''

    or use implementation for Android studio 3.0. Note that the version number 27.0.2 may differ in to future releases:

    1implementation ''

FloatingActionButton (fab)

A FloatingActionButton (fab) is a round button with an icon, which denotes a quick primary action on the interface such as:

  • Adding a Note or alarm
  • Sending an email or text



Snackbar appears from the bottom for a short time then disappears. It shows a brief message along with an action button to perform corresponding task. Using the SnackBar is best when trying to:

  • Undo the item deletion
  • Display an exit action when back button pressed


Move up the Fab when SnackBar appears

If fab button is at the bottom of the screen, you can coordinate with the SnackBar to move the fab up when the SnackBar appears. This is done by using coordinator layout as the root ViewGroup.


3import android.os.Bundle;
8import android.view.View;
10public class FoatingAndSnakBarActivity extends AppCompatActivity {
12    @Override
13    protected void onCreate(Bundle savedInstanceState) {
14        super.onCreate(savedInstanceState);
15        setContentView(R.layout.activity_foating_and_snak_bar);
17        FloatingActionButton fab = findViewById(;
18        fab.setOnClickListener(new View.OnClickListener() {
19            @Override
20            public void onClick(View view) {
21                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
22                        .setAction("Action", new View.OnClickListener() {
23                            @Override
24                            public void onClick(View view) {
25                                // sncakbar button clicked
26                            }
27                        }).show();
28            }
29        });
30    }

By default the width of SnakBar is same as screen, so view here should be a child of your ViewGroup to retrieve the width internally.


1<?xml version="1.0" encoding="utf-8"?>
2< xmlns:android=""
3    xmlns:app=""
4    xmlns:tools=""
5    android:layout_width="match_parent"
6    android:layout_height="match_parent"
7    tools:context="">
10    <
11        android:id="@+id/fab"
12        android:layout_width="wrap_content"
13        android:layout_height="wrap_content"
14        android:layout_gravity="bottom|end"
15        android:layout_margin="@dimen/fab_margin"
16        app:srcCompat="@android:drawable/ic_dialog_email" />

Tip: Design library provides many other elegant views like NavigationDrawer, CollapsingToolbarLayout.


TextInputLayout is like an EditText which supports floating label as hint and it moves up when user stats typing.

2        android:layout_width="match_parent"
3        android:layout_height="wrap_content">
5    <
6            android:layout_width="match_parent"
7            android:layout_height="wrap_content"
8            android:hint="@string/form_username"/>


Android supports variety of animations which can be created via Java and XML as well.

  • Value Animator used to animate the objects
  • Object Animator are used to animate the attribute properties like objects
  • View Animation are collections of multiple animations like scaling, rotating into a single animation file
  • Drawable Animations are often used to create waiting/processing dialogs to display collection of images one after another according to given transition time
  • overridePendingTransition : This function can be overridden in Activities to add your own customize enter and exit animations(via XML) during activities transitions.
1startActivity(new Intent(YourCurrentActivity.this,DestinationActivity.class));
2// animate by applying fade in and fade out animations
3overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);

Material Design

Material design standards are the design guidelines for an application's user interface, appearance, and motion. Features of material themes are as follows:

  • CardView: CardView is a rounded corner rectangular view which supports elevation (shadow) and ripple animation.
  • RecyclerView: RecyclerView is an enhance version of ListView in terms of efficiency and it also supports - Linear View - Grid View - Staggered View
  • Circular Image: Android provides inbuilt support to crop and display in circular shape which efficient than creating a customize one.
1// fetch the image as bitmap
2Bitmap b= BitmapFactory.decodeResource(getResources(),R.drawable.norml);
3// create a rounded drawable
4RoundedBitmapDrawable drawable= RoundedBitmapDrawableFactory.create(getResources(),b);
5// create a circular image

Code Optimization

Serializable and Parcelable

Serialization is the process of converting your object into bytes to persist them. This can be achieved by implementing both the Serializable and Parcelable interfaces.

The important difference is that Parcelable is implemented via the Android native (C++) framework which requires less resources per single instruction resulting in overall better performance. Serializable is best when sending singular objects from one activity to another. Parcelable is far better for larger transfers, however, such as sending lists of customized objects to the next Activity. Learn more about the difference here.


Like every system, the Android OS has limited resources, so it's always better to avoid using large size bitmaps or images. There are other options that be applied, such as


To achieve better performance for simple layout(without multiple nested ViewGroups), it is preferred to use LinearLayout due to support of linear flow-based UI drawing whereas the Relative layout always use two measure passes.

LinearLayout is also quite handy for allocating the available width or height as per the weight property.

  • Set the attribute value as 0dp of either height or width
  • As per the weight property, 0dp of space (either height or width) will be allocated.
1<?xml version="1.0" encoding="utf-8"?>
2<LinearLayout android:layout_height="match_parent"
3    android:layout_width="match_parent"
4    xmlns:android="" >
6    <View
7        android:background="#c44cd4"
8        android:layout_width="0dp"
9        android:layout_weight="1"
10        android:layout_height="match_parent"/>
11    <View
12        android:layout_weight="1"
13        android:background="#7bf2dc"
14        android:layout_width="0dp"
15        android:layout_height="match_parent"/>

Clean-Code Architecture

Clean-Code Architecture separates the background logic from the UI so that both user interface and background logic can be tested independently.

MVP: Model View Presenter is the talk of the town amongst Android developers when it comes to implementing clean-code architecture.

  • Model: Object structure to store data.
  • View: A dumb view who receives the actions from user and pass it on to presenter.
  • Presenter: A relay that acts upon the model and the view. It retrieves data from model, and formats it to display in the view.

IDE Support

Live template

Live template offers quick code insertion shortcut, so you don't have to write the whole statement. Instead just press ctrl+j and select the Toast or any other option to insert respective code.

Refactoring code

Use shift+f6 to rename components, variables or module across project.

There are lots of other useful options under Refactor menu like extract, change signature, and more that save us a lot of time and prevent mistakes.

Patterns & Principals

  • Builder patterns: Builder patterns are widely used to create APIs and libraries and reducing the complexity of and effort needed for object creation.

  • SOLID: SOLID is an acronym for principals widely used to make a stable, scalable and effective software design. The five parts of SOLID are discussed in depth in the linked article.

There are several patterns that have been invented to solve specific problems. These patterns and problems are discussed here. Read more to create better quality applications.

UI Testing

Android studio provides built-in support to test user interface actions via recoding an Espresso test. Espresso tests state expectations, interactions, and assertions.

A simple example would be to perform a button click and check whether the text of TextView has changed or not.

1onView(withId(; // perform click
2onView(withText("Hello")).check(matches(isDisplayed())); // check a view is visible with text "Hello"

To Record a test: Click "run" in menu Select "Record Esprsso Test" This will open the app on a device and record user actions, generating a UI test.

Best Practices


An APK is like an archive. It contains a classes.dex archive which is a collection of .class files.

Anyone having access to dex2-jar tool can obtain the original source code (java files) and can build a personal version of your market app to harm your product value by uploading a free version of your app.

The process is called Reverse engineering, and it is a major security threat to app revenue.

By default, Android Studio built a debug version of project as an APK, from which the original source code can be easily obtained.

Never share your debug APK with any outside user.


Unfortunately, there is currently no way to protect our app from reverse engineering so the optimal solution is to use obfuscation.

To generate obfuscated code, the apk should be generated as a release version. A release version is signed with a SHA1 key and outputs a working obfuscated source code apk.

  • Result of reverse-engineering on debug apk
1public class MainActivity extends AppCompatActivity
3    private ArrayAdapter<String> adapter;
4    private ListView listView;
6    protected void onCreate(Bundle paramBundle)
7    {
8        super.onCreate(paramBundle);
9        setContentView(2130968605);
10        this.listView = ((ListView)findViewById(2131558552));
11        this.adapter = new ArrayAdapter(this, 17367046, Util.DEMO_LIST_ITEMS);
12        this.listView.setAdapter(this.adapter);
13    }
  • Result of reverse-engineering on release apk
5public class MainActivity extends s
7    private ListView i;
8    private ArrayAdapter<String> l;
10    protected void onCreate(Bundle paramBundle)
11    {
12        super.onCreate(paramBundle);
13        setContentView(2130968602);
14        this.i = ((ListView)findViewById(2131558552));
15        this.l = new ArrayAdapter(this, 17367046, Util.DEMO_LIST_ITEMS);
16        this.i.setAdapter(this.l);
17    }


This file contains the instructions to obfuscate source code for release apk. ProGuard is a command line tool that shrinks the size of apk by optimizing, obfuscating and eliminating the files (java/bytecode/resources) which results in smaller size apk.

Enable progurad:

  • Open build.gradle (module)
  • set "minifyEnabled" flag to true
1android {
2    compileSdkVersion 26
3    buildToolsVersion "26.0.1"
4    defaultConfig {
5        applicationId ""
6        minSdkVersion 15
7        targetSdkVersion 26
8        versionCode 1
9        versionName "1.0"
10        testInstrumentationRunner ""
11    }
12    buildTypes {
13        debug {
14            minifyEnabled true
15            proguardFiles getDefaultProguardFile('proguard-android.txt'), ''
16        }
17        release {
18            minifyEnabled true
19            proguardFiles getDefaultProguardFile('proguard-android.txt'), ''
20        }
21    }

The above configuration is for testing purposes. It will obfuscate the APK for every build. Please do not use the minifyEnabled true for debug because it will result in longer project buld duration.

Often you might be required to disable obfuscation for POJO classes and libraries to meet proper naming convention during JSON parsing or placing network calls. To accommodate for this, you can define customize rules for which code to keep.


Hide Sensitive Information

There is basically no way that you can protect your API key from a hacker but the safest way is to use an NDK, or a Native Developers Toolkit. Through the NDK, corresponding C and C++ functions can be implemented in Android project.

The NDK ports C and C++ code into separate libraries that are hard to decompile although the NDK compiled code can still be opened with hexadecimal code, it is still hard to detect an API key out of hex code.

Learn more about NDKs and security.

API Levels

Every Android release introduces new features that might not be backward compatible with older versions, making it important to make your app compatible with older versions. You can put a check to verify the current android OS version and process according as

1if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
2	// current os is marshmallow or above
3}else{/* perform alternative actions for older version */}

Common Issues:

Do not reinvent the wheel

Android has a huge open source development community and there are thousands of developers who has published their great work in open source community which saves lot of time and efforts while offering tons of features.

For example, do not use background threads to download and display images just because you can write lengthy code use Picasso, an image downloading library which offers lot other functionalities like cache, resizing, error handling and easily customizable.

2  .load(url)
3  .resize(50, 50)
4  .centerCrop()
5  .into(imageView)



  • Follow the Google Java Style Guide for readable code.
  • Don't reinvent the wheel, and always use libraries design, CardView, RecyclerView, retrofit etc.
  • Enhance UI with swipeToRefresh , BottomBarNavigation, and the design library.
  • Add meaningful animations, ripple, elevation, transition.
  • Use pro-guard rules to obfuscate your code.
  • Perform UI and logical testing for quick deployment for beta testing.
  • Use the job scheduler for longer running background tasks.
  • Add support for the latest APIs using runtime permissions, Doze, or StandBy mode.

I am glad that you have made this far! Thanks for reading and I hope this guide helped you with your Android endeavors!