Showing posts with label Android Device Monitor. Show all posts
Showing posts with label Android Device Monitor. Show all posts

Friday, 19 May 2017

HB Blog 136: Android Automation Testing Using Espresso Framework.

Android tests are based on JUnit, and you can run them either as local unit tests on the JVM or as instrumented tests on an Android device. This post provides an introduction to the concepts and tools for building Android tests.
When using Android Studio to write any of your tests, your test code must go into one of two different code directories (source sets). For each module in your project, Android Studio includes both source sets, corresponding to the following test types:
Local unit tests:-
Located at module-name/src/test/java/.
These tests run on the local JVM and do not have access to functional Android framework APIs.

Instrumented tests:-
Located at module-name/src/androidTest/java/.
These are all tests that must run on an Android hardware device or an Android emulator.
Instrumented tests are built into an APK that runs on the device alongside your app under test. The system runs your test APK and your app under tests in the same process, so your tests can invoke methods and modify fields in the app, and automate user interaction with your app.
        Building Instrumented Unit Tests: Build complex unit tests with Android dependencies that cannot be satisfied with mock objects.
        Automating User Interface Tests: Create tests to verify that the user interface behaves correctly for user interactions within a single app or for interactions across multiple apps.
        Testing App Component Integrations: Verify the behavior of components that users do not directly interact with, such as a Service or a Content Provider.
However, the local unit tests and instrumented tests described above are just terms that help distinguish the tests that run on your local JVM from the tests that run on the Android platform (on a hardware device or emulator). The real testing types that you should understand when building a complete test suite are described in the following table.

TypeSubtype Description
Unit tests
Local Unit Tests Unit tests that run locally on the Java Virtual Machine (JVM). Use these tests to minimize execution time when your tests have no Android framework dependencies or when you can mock the Android framework dependencies.
Instrumented unit tests Unit tests that run on an Android device or emulator. These tests have access to Instrumentation information, such as the Context of the app you are testing. Use these tests when your tests have Android dependencies that mock objects cannot satisfy.
Integration Tests
Components within your app only This type of test verifies that the target app behaves as expected when a user performs a specific action or enters a specific input in its activities. For example, it allows you to check that the target app returns the correct UI output in response to user interactions in the app’s activities. UI testing frameworks like Espresso allow you to programmatically simulate user actions and test complex intra-app user interactions.
Cross-app Components This type of test verifies the correct behavior of interactions between different user apps or between user apps and system apps. For example, you might want to test that your app behaves correctly when the user performs an action in the Android Settings menu. UI testing frameworks that support cross-app interactions, such as UI Automator, allow you to create tests for such scenarios.
JUnit
You should write your unit or integration test class as a JUnit test class. The framework offers a convenient way to perform common setup, teardown, and assertion operations in your test.
A basic JUnit test class is a Java class that contains one or more test methods. A test method begins with the @Test annotation and contains the code to exercise and verify a single functionality (that is, a logical unit) in the component that you want to test.
The following snippet shows an example JUnit integration test that uses the Espresso APIs to perform a click action on a UI element, then checks to see if an expected string is displayed.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
@RunWith(AndroidJUnit4.class)
@LargeTest
public class MainActivityInstrumentationTest {

    @Rule
    public ActivityTestRule mActivityRule = new ActivityTestRule<>(
            MainActivity.class);

    @Test
    public void sayHello(){
        onView(withText("Say hello!")).perform(click());

        onView(withId(R.id.textView)).check(matches(withText("Hello, World!")));
    }
}

In your JUnit 4 test class, you can call out sections in your test code for special processing by using the following annotations:
  • @Before: Use this annotation to specify a block of code that contains test setup operations. The test class invokes this code block before each test. You can have multiple @Before methods but the order in which the test class calls these methods is not guaranteed.
  • @After: This annotation specifies a block of code that contains test tear-down operations. The test class calls this code block after every test method. You can define multiple @After operations in your test code. Use this annotation to release any resources from memory.
  • @Test: Use this annotation to mark a test method. A single test class can contain multiple test methods, each prefixed with this annotation.
  • @Rule: Rules allow you to flexibly add or redefine the behavior of each test method in a reusable way. In Android testing, use this annotation together with one of the test rule classes that the Android Testing Support Library provides, such as ActivityTestRule or ServiceTestRule.
  • @BeforeClass: Use this annotation to specify static methods for each test class to invoke only once. This testing step is useful for expensive operations such as connecting to a database.
  • @AfterClass: Use this annotation to specify static methods for the test class to invoke only after all tests in the class have run. This testing step is useful for releasing any resources allocated in the @BeforeClass block.
  • @Test(timeout=): Some annotations support the ability to pass in elements for which you can set values. For example, you can specify a timeout period for the test. If the test starts but does not complete within the given timeout period, it automatically fails. You must specify the timeout period in milliseconds, for example: @Test(timeout=5000).
Use the JUnit Assert class to verify the correctness of an object's state. The assert methods compare values you expect from a test to the actual results and throw an exception if the comparison fails. Assertion classes describes these methods in more detail.

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.

Saturday, 1 August 2015

HB Blog 86: Android Device Monitor Tools.

The Android SDK includes a variety of tools that help you develop mobile applications for the Android platform. Android Device Monitor is a stand-alone tool that provides a graphical user interface for several Android application debugging and analysis tools. The Monitor tool does not require installation of an integrated development environment, such as Android Studio, and encapsulates the following tools:
DDMS :-
Android Studio includes a debugging tool called the Dalvik Debug Monitor Server (DDMS), which provides port-forwarding services, screen capture on the device, thread and heap information on the device, logcat, process, and radio state information, incoming call and SMS spoofing, location data spoofing, and more. On Android, every application runs in its own process, each of which runs in its own virtual machine (VM). Each VM exposes a unique port that a debugger can attach to.
When DDMS starts, it connects to adb. When a device is connected, a VM monitoring service is created between adb and DDMS, which notifies DDMS when a VM on the device is started or terminated. Once a VM is running, DDMS retrieves the VM's process ID (pid), via adb, and opens a connection to the VM's debugger, through the adb daemon (adbd) on the device. DDMS can now talk to the VM using a custom wire protocol.
Start DDMS :-
To use it, launch the Android Device Monitor, and click the DDMS menu button. DDMS works with both the emulator and a connected device. If both are connected and running simultaneously, DDMS defaults to the emulator.

Hierarchy Viewer :-
The Hierarchy Viewer allows you to debug and optimize your user interface. It provides a visual representation of the layout's View hierarchy (the Layout View) and a magnified inspector of the display (the Pixel Perfect View).
Start Hierarchy Viewer :-
From Android Studio, choose Tools > Android Device Monitor or click the Android Device Monitor icon. Click the Open Perspectives icon and select Hierarchy View.

Systrace :-
The Systrace tool helps analyze the performance of your application by capturing and displaying execution times of your applications processes and other Android system processes. The tool combines data from the Android kernel such as the CPU scheduler, disk activity, and application threads to generate an HTML report that shows an overall picture of an Android device’s system processes for a given period of time.
The Systrace tool is particularly useful in diagnosing display problems where an application is slow to draw or stutters while displaying motion or animation. 
Start Systrace :-
The Systrace tool has different command line options for devices running Android 4.3 (API level 18) and higher versus devices running Android 4.2 (API level 17) and lower.
The general syntax for running Systrace from the command line is as follows.
$ cd android-sdk/platform-tools/systrace
$ python systrace.py [options] [category1] [category2] ... [categoryN]
Traceview :-
Traceview is a graphical viewer for execution logs that you create by using the Debug class to log tracing information in your code. Traceview can help you debug your application and profile its performance. When you have a trace log file (generated by adding tracing code to your application or by DDMS), you can load the log files in Traceview, which displays the log data in two panels:
    A timeline panel -- describes when each thread and method started and stopped
    A profile panel -- provides a summary of what happened inside a method

Start Traceview :-
In the Android Device Monitor tool bar, click DDMS and select a process.
Click the Start Method Profiling icon to start method profiling.
After the profiling is complete, click the Stop Method Profiling icon to display the traceview.