Showing posts with label ART. Show all posts
Showing posts with label ART. Show all posts

Friday, 15 September 2023

Demystifying the Android Toolchain: Building Blocks of App Development.

In the world of mobile technology, Android applications have become ubiquitous, enhancing our lives in countless ways. But behind every app's sleek interface lies a complex process powered by the Android toolchain. In this exploration, we'll unveil the essential components of this toolchain, demystifying the process that turns code into the apps we rely on daily. Join us on a journey through the heart of Android app development.

Understanding the Android Toolchain

The Android toolchain is a set of tools and utilities used by developers to compile, build, test, and package Android applications. It transforms your source code into an APK (Android Package) file, which can be installed and run on Android devices. Let's delve into its primary components:

Java Compiler (javac): Java is the primary language for Android app development. The Java compiler converts your Java source code (.java files) into bytecode (.class files).
Dalvik or ART (Android Runtime): Android uses a virtual machine to run applications. Dalvik, the earlier runtime, was succeeded by ART (Android Runtime) in later versions. These runtimes convert bytecode into machine code that is executed by the device's CPU.
Android Package Manager (aapt): This tool helps package your app's resources (like images, layouts, and XML files) into the APK file. It also handles resource localization, density, and other configuration-related tasks.
Android Asset Packaging Tool (aapt2): A more modern version of aapt, aapt2 further improves resource management, making it more efficient and robust.
Dex Compiler (dx): The Dalvik or ART runtime doesn't directly execute Java bytecode. Instead, it converts it into a specialized bytecode format called Dalvik Executable (DEX). The dx tool performs this conversion.
Android Debug Bridge (ADB): ADB is a versatile command-line tool for interacting with Android devices and emulators. It allows you to install, debug, and manage apps on devices.
Gradle and Android Studio: While not part of the Android toolchain per se, Gradle and Android Studio are essential development tools. Gradle is a build automation tool, and Android Studio is the official Integrated Development Environment (IDE) for Android development. These tools simplify the build and development process.

The Build Process

Now that we've introduced the Android toolchain components, let's explore how they work together during the build process:

  1. Source Code: You start with your app's source code, typically written in Java or Kotlin. You also have XML files for layouts and resources like images, strings, and themes.
  2. Compilation: The Java compiler (javac) translates your Java/Kotlin source code into bytecode (.class files). These files contain your app's logic.
  3. Resource Packaging: The Android Asset Packaging Tool (aapt or aapt2) packages your app's resources and assets into a format that can be efficiently used by Android. This includes XML layout files, images, and other resources.
  4. Dex Conversion: The Dex Compiler (dx) converts the bytecode (.class files) into Dalvik Executable (DEX) files. These DEX files are optimized for execution on Android devices.
  5. APK Assembly: The Android Package Manager (aapt) takes the DEX files, resources, and other necessary assets, and assembles them into an APK file. This file is the heart of your Android application.
  6. Signing and Debugging: Before distribution, you may need to sign the APK with a digital certificate. During development, you can use the Android Debug Bridge (ADB) to install and debug your app on emulators or physical devices.
  7. Distribution: Once your app is fully tested and ready for release, you can distribute the signed APK via the Google Play Store or other distribution channels.

Conclusion

The Android toolchain is the backbone of Android app development, seamlessly transforming your source code and resources into a functional application. Understanding its components and how they work together is crucial for any Android developer.

As the Android ecosystem evolves, new tools and optimizations are continually introduced, making app development more efficient and user-friendly. Stay updated with the latest developments in the Android toolchain to ensure your apps are at the forefront of innovation in the mobile world. Happy coding!

Tuesday, 20 June 2023

The Artistry of Code: Unleashing Creativity in the World of Programming.

 In the realm of technology, programming is often perceived as a purely technical pursuit, with its focus on logic, algorithms, and problem-solving. However, behind the lines of code lies a hidden truth: coding is an art form. Developers, much like painters or musicians, wield their keyboards and IDEs as tools to express their creativity and bring their visions to life. In this blog post, we will explore the concept of coding as an art form, delving into the parallels between coding and traditional art and highlighting the unique ways in which developers channel their creativity.

The Palette of Language:

Just as artists choose their mediums, developers select programming languages to communicate their ideas. Each language possesses its own syntax, grammar, and idioms, providing a unique set of tools for expression. From the elegance of Python to the precision of C++, developers navigate the language palette, selecting the right hues to shape their creation. Just as an artist understands the properties of paint and brushes, a skilled developer comprehends the intricacies of their chosen language, bending it to their will with finesse.

The Architecture of Design:

Architecture, the backbone of art and engineering alike, finds a home in the world of coding. Developers craft intricate systems, weaving together modules, functions, and classes to create a cohesive whole. They employ principles of design, such as modularity, abstraction, and encapsulation, to build robust and scalable software structures. Much like an architect designs a building with aesthetic appeal and functional purpose, developers shape their code to be both elegant and efficient, harmonizing form and function.

The Symphony of Algorithms:

Just as a composer crafts a symphony, developers compose algorithms that orchestrate complex operations. Algorithms are the melodies that guide the behavior of software, and their design requires a keen sense of creativity. Developers face the challenge of solving problems in innovative ways, discovering new patterns and techniques to optimize performance and user experience. The rhythm, flow, and tempo of their algorithms can transform mundane processes into something extraordinary, much like a musical composition.

The Canvas of User Experience:

While artists may work with physical canvases, developers work with the intangible canvas of user experience. They sculpt interactions, design intuitive interfaces, and create seamless flows that captivate and engage users. Just as artists consider color, composition, and visual hierarchy, developers consider usability, accessibility, and interactivity. Their aim is to evoke emotions, spark joy, and create memorable experiences that leave a lasting impact.

The Iterative Journey:

Artists rarely create masterpieces in a single stroke, and developers share a similar iterative journey. They sketch rough drafts, prototype ideas, and refine their work through constant feedback and improvement. The coding process, much like the creative process, involves experimentation, exploration, and the willingness to embrace mistakes as opportunities for growth. Developers learn from their failures, iterate on their designs, and ultimately shape their code into a work of art.

Conclusion:

Coding is more than a technical craft—it is an art form that allows developers to bring their creative visions to life. Through the careful selection of programming languages, the thoughtful design of architectures, the composition of algorithms, and the creation of captivating user experiences, developers transform lines of code into beautiful and functional creations. Embracing the artistry of coding can enhance the joy and fulfillment of developers, while also fostering innovation and pushing the boundaries of what is possible in the world of technology. So, the next time you sit down to write code, remember that you are not just a developer—you are an artist, painting your imagination onto the digital canvas.

Monday, 1 May 2017

HB Blog 134: Improve Android Applications Performance.

Hey guys, I hope you liked my previous post on app performance HB Blog 132: Does Your Phone Get Hang? Know Why...  . I got few mails and suggestions for posting similar kind of posts. So, here is my one more post for optimize your app's performance in various ways to improve its responsiveness and battery efficiency.
Basically, user expects app to launch app faster as well as load UI without any glitches. App launch can take place in one of three states, each affecting how long it takes for your app to become visible to the user: cold start, warm start, and lukewarm start. In a cold start, your app starts from scratch. In the other states, the system needs to bring the app from the background to the foreground.
At the beginning of a state, the system has three tasks. These tasks are:
  1.     Loading and launching the app.
  2.     Displaying a blank starting window for the app immediately after launch.
  3.     Creating the app process.
As soon as the system creates the app process, the app process is responsible for the next stages. These stages are:
  1.     Creating the app object.
  2.     Launching the main thread.
  3.     Creating the main activity.
  4.     Inflating views.
  5.     Laying out the screen.
  6.     Performing the initial draw.
There are few safety measures we can take for improving application performance such as,
  1. Remove unused resource IDs:- We often declare and find a view using android:id="@+id/view". But, while actual calling it in java classes is not needed. Sometimes, we don't need any changes in that particular view so e can avoid creating this ids. Because, these ids are creating public static final constant variable which are taking up unneeded memory.
  2. Remove unused resource:- Many times we keep on changing UI/UX so in that case we might add up resource but won't remove it once they are unused, so try to remove unused resource it may be images, icons as well as layout and other XML.
  3. Minimize load on onCreate():-  When your application launches, the blank starting window remains on the screen until the system finishes drawing the app for the first time. At that point, the system process swaps out the starting window for your app, allowing the user to start interacting with the app. If you’ve overloaded Application.oncreate() in your own app, the system invokes the onCreate() method on your app object. Afterwards, the app spawns the main thread, also known as the UI thread, and tasks it with creating your main activity. From Android 4.4 (API level 19), logcat includes an output line containing a value called Displayed. This value represents the amount of time elapsed between launching the process and finishing drawing the corresponding activity on the screen. We understand that which activity is taking more time for loading and using tools like Method Tracer, Inline Tracer, etc. It also gives which methods are the culprits, most of the time it is onCreate() method. We need to optimize the load of these method by initializing resource that are needed at startup itself. We can also use methods such as reportFullyDrawn() to let the system know that your activity is finished with its lazy loading.
  4. Use injection framework like Dagger:- Whether the problem lies with unnecessary initialization or disk I/O, the solution calls for lazy-initializing objects: initializing only those objects that are immediately needed. We can have a dependency injection framework like Dagger that creates objects and dependencies are when they are injected for the first time.
  5. Use Asynchronous operation:- Using a background thread ("worker thread") removes strain from the main thread so it can focus on drawing the UI. In many cases, using AsyncTask provides a simple way to perform your work outside the main thread. AsyncTask automatically queues up all the execute() requests and performs them serially. This behavior is global to a particular process and means you don’t need to worry about creating your own thread pool. For background database operations we can use compile statements can be used. Have a look on similar post for more information, HB Blog 95: How To Compile SQL Statement Into Reusable Pre-compiled Statement Object???
  6. Avoid Virtualization:- If you don't need to access an object's fields, make your method static. Invocations will be about 15%-20% faster. It's also good practice, because you can tell from the method signature that calling the method can't alter the object's state. In native languages like C++ it's common practice to use getters (i = getCount()) instead of accessing the field directly (i = mCount). This is an excellent habit for C++ and is often practiced in other object oriented languages like C# and Java, because the compiler can usually inline the access, and if you need to restrict or debug field access you can add the code at any time. However, this is a bad idea on Android. Virtual method calls are expensive, much more so than instance field lookups. It's reasonable to follow common object-oriented programming practices and have getters and setters in the public interface, but within a class you should always access fields directly.
  7. Use Enhanced For Loop Syntax:- The enhanced for loop (also sometimes known as "for-each" loop) can be used for collections that implement the Iterable interface and for arrays. There are several alternatives for iterating through an array:
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    static class Foo {
        int mSplat;
    }
    
    Foo[] mArray = ...
    
    public void zero() {
        int sum = 0;
        for (int i = 0; i < mArray.length; ++i) {
            sum += mArray[i].mSplat;
        }
    }
    
    public void one() {
        int sum = 0;
        Foo[] localArray = mArray;
        int len = localArray.length;
    
        for (int i = 0; i < len; ++i) {
            sum += localArray[i].mSplat;
        }
    }
    
    public void two() {
        int sum = 0;
        for (Foo a : mArray) {
            sum += a.mSplat;
        }
    }
    

    • zero() is slowest, because the JIT can't yet optimize away the cost of getting the array length once for every iteration through the loop. 
    • one() is faster. It pulls everything out into local variables, avoiding the lookups. Only the array length offers a performance benefit. 
    • two() is fastest for devices without a JIT, and indistinguishable from one() for devices with a JIT. It uses the enhanced for loop syntax introduced in version 1.5 of the Java programming language.
  8. Avoid complex Layout Hierarchies:- Layouts are a key part of Android applications that directly affect the user experience. If implemented poorly, your layout can lead to a memory hungry application with slow UIs. The Android SDK includes tools to help you identify problems in your layout performance, which will help to implement smooth scrolling interfaces with a minimum memory footprint. In the same way a complex web page can slow down load time, your layout hierarchy if too complex can also cause performance problems. If your application UI repeats certain layout constructs in multiple places, you can use the <include/> and <merge/> tags to embed another layout inside the current layout. Beyond simply including one layout component within another layout, you might want to make the included layout visible only when it's needed, sometime after the activity is running. Deferring loading resources is an important technique to use when you have complex views that your app might need in the future. You can implement this technique by defining a ViewStub for those complex and rarely used views.
  9. Use View Holder for listview:- Listview is one of the most important and very excessively used view. The key to a smoothly scrolling ListView is to keep the application’s main thread (the UI thread) free from heavy processing. Ensure you do any disk access, network access, or SQL access in a separate thread. The key to a smoothly scrolling ListView is to keep the application’s main thread (the UI thread) free from heavy processing. Ensure you do any disk access, network access, or SQL access in a separate thread. A way around repeated use of findViewById() is to use the "view holder" design pattern. A ViewHolder object stores each of the component views inside the tag field of the Layout, so you can immediately access them without the need to look them up repeatedly.
  10. Use 3rd party libraries carefully:- Actually, we use available libraries and resources for fasten our development time. It might not work as expected all the time and not all the design patterns and precautions are followed in these kinda libraries. So do explore complete libraries and then go for it. Android Arsenal is one of the interesting and helpful site which has categorized directory of libraries and tools for Android.

Saturday, 1 April 2017

HB Blog 132: Does Your Phone Get Hang? Know Why...

Android phone sometimes gets hang. Does your phone also have same problem? Don't blame OEMs the original equipment manufacturers or Open Handset Alliance for these problems. At least, not completely because Android applications are more responsible for that.
Developers call it as memory leaks in technical terms. Now a days, lot of devices with unlimited memory are coming in the market. But, it is not the SD card memory that we are having scarcity. It is the heap size or the application size.

So what is the heap size?
Android is a full multitasking system so it’s possible to run multiple programs at the same time and obviously each one can’t use all of your device memory. For this reason there is a hard limit on your Android application’s heap size: if your application needs to allocate more memory and you have gone up to that heap size already, you are basically going to get a “out of memory error”.
Heap size limit is device dependent and it has changed a lot over the years, the first Android phone (the G1) has 16MB heap size limit.

Even if you do not plan on using all of this memory, you should use as little as possible to let other applications run without getting them killed. The more applications Android can keep in memory, the faster it will be for the user to switch between his apps. If these memory is allocated more by the application, your phone gets hang and we get a memory leaks issues.

There are many reasons why we face these kind of problems such as large bitmaps, resources, etc. But, most of time it is the context that are kept long-lived references. In Android, a Context is used for many operations but mostly to load and access resources. This is why all the widgets receive a Context parameter in their constructor. In a regular Android application, you usually have two kinds of Context, Activity and Application. It's usually the first one that the developer passes to classes and methods that need a Context. This means that views have a reference to the entire activity and therefore to anything your activity is holding onto, usually the entire View hierarchy and all its resources. Therefore, if you leak the Context ("leak" meaning you keep a reference to it thus preventing the GC from collecting it), you leak a lot of memory. Leaking an entire activity can be really easy if you're not careful.
When the screen orientation changes the system will, by default, destroy the current activity and create a new one while preserving its state. In doing so, Android will reload the application's UI from the resources.

Basically, we can avoid configuration changes by locking screen rotation. But, it is something that wont provide user experience. Such as watching movie in just portrait mode without landscape feature. So we can go for config change attribute in Android Manifest file as below snippet,


1
2
3
<activity android:name=".MyActivity"
    android:configChanges="orientation|keyboardHidden"
android:label="@string/app_name">


also, do not keep long-lived references to a context-activity (a reference to an activity should have the same life cycle as the activity itself), try using the context-application instead of a context-activity.
Avoid non-static inner classes in an activity if you don't control their life cycle, use a static inner class and make a weak reference to the activity inside. And, many more ways to explore time to time while developing Android applications...

Tuesday, 1 November 2016

HB Blog 122: Android Tools For Analyzing RAM Usage.

Random-access memory (RAM) is a valuable resource in any software development environment, but it's even more valuable on a mobile operating system where physical memory is often constrained. Although both the Android Runtime (ART) and Dalvik virtual machine perform routine garbage collection, this does not mean you can ignore when and where your app allocates and releases memory. You still need to avoid introducing memory leaks, usually caused by holding onto object references in static member variables, and release any Reference objects at the appropriate time as defined by lifecycle callbacks.
Tools for analyzing RAM usage :-
Before you can fix the memory usage problems in your app, you first need to find them. Android Studio and the Android SDK include several tools for analyzing memory usage in your app,

  1. The Device Monitor has a Dalvik Debug Monitor Server (DDMS) tool that allows you to inspect memory allocation within your app process. You can use this information to understand how your app uses memory overall. For example, you can force a garbage collection event and then view the types of objects that remain in memory. You can use this information to identify operations or actions within your app that allocate or leave excessive amounts of objects in memory. 
  2. The Memory Monitor in Android Studio shows you how your app allocates memory over the course of a single session. The tool shows a graph of available and allocated Java memory over time, including garbage collection events. You can also initiate garbage collection events and take a snapshot of the Java heap while your app runs. The output from the Memory Monitor tool can help you identify points when your app experiences excessive garbage collection events, leading to app slowness.
  3. Garbage collection events also show up in the Traceview viewer. Traceview allows you to view trace log files as both a timeline and as a profile of what happened within a method. You can use this tool to determine what code was executing when a garbage collection event occurred. 
  4. The Allocation Tracker tool in Android Studio gives you a detailed look at how your app allocates memory. The Allocation Tracker records an app's memory allocations and lists all allocated objects within the profiling snapshot. You can use this tool to track down parts of your code that allocate too many objects.

Tuesday, 1 September 2015

HB Blog 91: Android Studio's Attractive Features.

Android Studio is the official IDE for Android application development, based on IntelliJ IDEA.
Android Studio offers:
    Flexible Gradle-based build system
    Build variants and multiple apk file generation
    Code templates to help you build common app features
    Rich layout editor with support for drag and drop theme editing
    lint tools to catch performance, usability, version compatibility, and other problems
    ProGuard and app-signing capabilities
    Built-in support for Google Cloud Platform, making it easy to integrate Google Cloud Messaging and App Engine
    And much more.


Most attractive features of android studio from a developer perspective are as follows:-

1)Android Studio allows you to work with layouts in both a Design View. Easily select and preview layout changes for different device images, display densities, UI modes, locales, and Android versions (multi-API version rendering).
From the Design View, you can drag and drop elements from the Palette to the Preview or Component Tree. The Text View allows you to directly edit the XML settings, while previewing the device display.
It updates preview of the layout xml while creating UI which provides read–eval–print loop (REPL) kind of features.

2)Android Studio provides a memory and CPU monitor view so you can more easily monitor your app's performance and memory usage to track CPU usage, find deallocated objects, locate memory leaks, and track the amount of memory the connected device is using. With your app running on a device or emulator, click the Android tab in the lower left corner of the runtime window to launch the Android runtime window. Click the Memory or CPU tab.
When you're monitoring memory usage in Android Studio you can, at the same time, initiate garbage collection and dump the Java heap to a heap snapshot in an Android-specific HPROF binary format file. The HPROF viewer displays classes, instances of each class, and a reference tree to help you track memory usage and find memory leaks.
Android Studio allows you to track memory allocation as it monitors memory use. Tracking memory allocation allows you to monitor where objects are being allocated when you perform certain actions. Knowing these allocations enables you to adjust the method calls related to those actions to optimize your app's performance and memory use.

3)Android Studio projects contain a top-level build file and a build file for each module. The build files are called build.gradle, and they are plain text files that use Groovy syntax to configure the build with the elements provided by the Android plugin for Gradle. In most cases, you only need to edit the build files at the module level. For example, the build file for the app module in the BuildSystemExample project looks like this:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
apply plugin: 'com.android.application'

android {
    compileSdkVersion 19
    buildToolsVersion "19.0.0"

    defaultConfig {
        minSdkVersion 8
        targetSdkVersion 19
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile project(":lib")
    compile 'com.android.support:appcompat-v7:19.0.1'
    compile fileTree(dir: 'libs', include: ['*.jar'])
}

 4)The build system can help you create different versions of the same application from a single project. This is useful when you have a demo version and a paid version of your app, or if you want to distribute multiple APKs for different device configurations on Google Play.
The build system uses product flavors to create different product versions of your app. Each product version of your app can have different features or device requirements. The build system also uses build types to apply different build and packaging settings to each product version. Each product flavor and build type combination forms a build variant. The build system generates a different APK for each build variant of your app.
To define two product flavors, edit the build file for the app module to add the following configuration:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
...
android {
    ...
    defaultConfig { ... }
    signingConfigs { ... }
    buildTypes { ... }
    productFlavors {
        demo {
            applicationId "com.buildsystemexample.app.demo"
            versionName "1.0-demo"
        }
        full {
            applicationId "com.buildsystemexample.app.full"
            versionName "1.0-full"
        }
    }
}
...
The product flavor definitions support the same properties as the defaultConfig element. The base configuration for all flavors is specified in defaultConfig, and each flavor overrides any default values. The build file above uses the applicationId property to assign a different package name to each flavor: since each flavor definition creates a different app, they each need a distinct package name.

5)With smart rendering, Android Studio displays links for quick fixes to rendering errors. For example, if you add a button to the layout without specifying the width and height attributes, Android Studio displays the rendering message Automatically add all missing attributes. Clicking the message adds the missing attributes to the layout.
While debugging, you can now right-click on bitmap variables in your app and invoke View Bitmap. This fetches the associated data from the debugged process and renders the bitmap in the debugger.
When referencing images and icons in your code, a preview of the image or icon appears (in actual size at different densities) in the code margin to help you verify the image or icon reference. Pressing F1 with the preview image or icon selected displays resource asset details, such as the dp settings.  

Friday, 4 July 2014

HB Blog 1: ART android runtime Ahead-of-time (AOT) compilation.

Ahead-of-time (AOT) compilation

ART introduces ahead-of-time (AOT) compilation, which can improve app performance. ART also has tighter install-time verification than Dalvik.
At install time, ART compiles apps using the on-device dex2oat tool. This utility accepts DEX files as input and generates a compiled app executable for the target device. The utility should be able to compile all valid DEX files without difficulty. However, some post-processing tools produce invalid files that may be tolerated by Dalvik but cannot be compiled by ART. For more information, see Addressing Garbage Collection Issues.

Improved garbage collection

Garbage collection (GC) can impair an app's performance, resulting in choppy display, poor UI responsiveness, and other problems. ART improves garbage collection in several ways:
  • One GC pause instead of two
  • Parallelized processing during the remaining GC pause
  • Collector with lower pause time for the special case of cleaning up recently-allocated, short-lived objects
  • Improved garbage collection ergonomics, making concurrent garbage collections more timely, which makes GC_FOR_ALLOC events extremely rare in typical use cases
ART currently does not use compacting GC, but this feature is under development in the Android Open Source Project (AOSP). In the meantime, don't perform operations that are incompatible with compacting GC, such as storing pointers to object fields. For more information, see Addressing Garbage Collection Issues.