Saturday, 17 March 2018

Moved to Medium

Moved to Medium

I moved my blog to Medium. It is now part of a publication called AndroidPub.

Some of the new articles you can find there are:

Dagger2 Android tutorial
Writing Gradle custom tasks with Kotlin
Android Bound Services and MVP

See you there!

Sunday, 21 February 2016

Android App Profiling and Optimization - part 2

In the previous blog post, I talked about memory leaks, or more specifically, leaked Activity. We went through the process of how to identify the leak and what you should not do in order to avoid it. Finally, I showed you how to fix the issue, resulting in an improved performance and stability of your app.

In this blog post, I'm going to talk about an amazing open source Android library called LeakCanary by Square, which some even define it as a "life-saver" (me among them). Simply put, LeakCanary finds memory leaks in your app during runtime and provides detailed info of where this leak might occur. The info is provided in two forms, LeakCanary UI and a more detailed leak trace printed in LogCat.

LeakCanary App showing the source of the leak

Considering the code example given in part 1 where we observed a memory leak, let's see how we can detect the memory leak using LeakCanary.

Integrating LeakCanary


In your build.gradle:

dependencies {
   debugCompile 'com.squareup.leakcanary:leakcanary-android:1.4-beta1'
   releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.4-beta1'
   testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.4-beta1'
 }

You probably noticed that there are two types of dependencies. The one ending with no-op basically contains only method stubs, without any concrete implementation, so we don't need to worry about LeakCanary showing memory leak alerts in our release builds.

In your Application class:

public class App extends Application {
  @Override public void onCreate() {
    super.onCreate();
    LeakCanary.install(this);
  }
}

In case you didn't have your own Application class implementation, remember to also register it in AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="org.codepond.memoryleak" >
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:name=".App"
        android:theme="@style/AppTheme" >

LeakCanary is now integrated and will automatically catch any Activity instance that leaked memory as long as we're in debug mode. It is of course possible to configure LeakCanary to watch any object. For more info, please see LeakCanary readme.

LeakCanary in Action


Fire up the app and change the orientation, then wait a few seconds. If you're targeting Android API 23, you'll get a notification from LeakCanary, saying that it needs permission to external storage. At the same time you'll also see the following log message in LogCat: "Could not write to leak storage to dump heap." Once you enabled the storage permission, re-launch the app and repeat the same step to produce a memory leak.
LeakCanary notification asking for storage permission

An alert will be shown in the middle of the screen "Dumping memory, app will freeze" and at the same time you'll see a log message in LogCat: "hprof: heap dump/sdcard/Download/leakcanary/suspected_leak_heapdump.hprof" starting...".




This means that LeakCanary caught a memory leak and will now do a heap dump, which will block the UI for a few seconds. The heap dump is stored in the emulator/device's external storage.

Once it's done, the alert will disappear and you'll see a message in LogCat similar to: "hprof: heap dump completed (25MB) in 3.848s". It's not over yet, LeakCanary will now analyze the heap dump in a background thread and within a few seconds you'll get a notification in addition to a trace print in LogCat:

In org.codepond.memoryleak:1.0:1.
* org.codepond.memoryleak.Splash has leaked:
* GC ROOT android.os.MessageQueue.mMessages
* references android.os.Message.callback
* references org.codepond.memoryleak.Splash$1.this$0 (anonymous class implements java.lang.Runnable)
* leaks org.codepond.memoryleak.Splash instance
* Retaining: 1.8 KB.
* Reference Key: 086cbbfa-f610-438a-b28f-750aa0135d2d
* Device: LGE google Nexus 5 hammerhead
* Android Version: 6.0.1 API: 23 LeakCanary: 1.4-beta1 02804f3


First, let's check the log message. The most important part is between lines 2-7. Line 2 states which class has leaked and line 7 states what it leaked. In this case Splash Activity, or to be more precisely - the anonymous class that implements Runnable in the call to postDelayed(), has leaked Splash Activity instance. Just a quick recap of part 1, when we changed the orientation, Splash Activity was essentially destroyed and a new instance was created. The old instance was supposed to be garbage collected, but it didn't, since it was still referenced from the Handler's Runnable (which was set to be executed after a 5 seconds delay).

new Handler().postDelayed(new Runnable() {
   @Override
   public void run() {
      /* This block leaks Splash instance */
      Intent mainIntent = new Intent(Splash.this, MainActivity.class);
      Splash.this.startActivity(mainIntent);
      Splash.this.finish();
  }
}, SPLASH_DISPLAY_LENGTH); // 5 seconds delay
The code snippet containing the memory leak


Now let's check the notification. After tapping it, LeakCanary will show tree-like UI with the most important part of the trace print that we've just went through.



Note that LeakCanary doesn't delete the heap dumps it stores in the external storage. You'll have to delete them manually by either tapping the DELETE button in the UI or directly access the SDCARD and delete the files from there, though I've personally always done the former so I'm unsure how the latter will affect LeakCanary's UI. If you don't delete previously stored heap dumps, at some point, LeakCanary will reach its maximum capacity and won't do any more heap dumps until the old ones have been deleted.

Check out the previous blog post on how to fix this memory leak.

Summary


LeakCanary saved me a lot of headache before and nowadays is my preferred way of tracking down memory leaks. Memory leaks in Android come in different flavors. In most cases they occur when the developer isn't careful enough. The common cases for memory leaks are a registered listener that should have been unregistered in Activity onDestroy(), a close() method that wasn't called, an anonymous class that holds a reference to an outer class, as seen in the example presented in this blog post, and more. Square has published a more advanced blog post about memory leaks, which I highly recommend you to read once you get the hang of memory leaks in Android.

Now go hunt those buggers!

Sunday, 23 August 2015

Android App Profiling and Optimization

Android is vast and there're often many solutions to a certain problem. On Stackoverflow, solutions that get many votes tend to be our safest bet, especially when many users give positive feedback in the comments. The situation becomes trickier when there's a background operation involved, running asynchronously. I often stumble upon solutions that completely ignore the impact they have on the performance and stability of the app. In some cases this might cause slight performance decrease, but in other cases, it might cause the app to crash!


 The Splash Screen Example


Please note: the following is just an example of unoptimized code and is not a solution I would recommend for implementing a splash screen. For a proper solution please see Ian Lake's Pro-tip.

Let's say we want to create a splash screen. We have an idea how to do it, but we're unsure if that's the best way. Since we're keen on best practice, we google for it. In this case, we get different solutions, some from SO and some from blogs. For instance, this solution:


public class Splash extends Activity {
    /** Duration of wait **/
    private final int SPLASH_DISPLAY_LENGTH = 1000;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.splashscreen);

        /* New Handler to start the main Activity 
         * and close this Splash-Screen after a few seconds.*/
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                /* Create an Intent that will start the main Activity. */
                Intent mainIntent = new Intent(Splash.this, MainActivity.class);
                Splash.this.startActivity(mainIntent);
                Splash.this.finish();
            }
        }, SPLASH_DISPLAY_LENGTH);
    }
}



This is a very common solution found on the web. It has a dedicated Activity for the splash screen that instantiates a Handler and calls postDelayed with a Runnable. After the delay time passed it will execute the Runnable, starting the main Activity followed by closing the splash screen Activity.

You copy-paste the code and yey it works and you're happy. So far so good.


 Analyzing the Code


Looking at the code I see a couple of flaws:

1. An infinite splash screen when the user changes orientations continuously while the splash screen is shown.
2. Memory leak.

As this blog post is about profiling and optimization, I'll concentrate on issue #2.
But wait a second, why should you worry about memory leaks? It's Java you are programming here and unlike native languages, such as C++, Java is managed. So why should you care? After all, it's done automatically for you, right? WRONG!


 Profiling and Optimizing the Code


This issue is often known in the Android community as "Leaking an Activity". Now what exactly does that mean?

When configuration change occurs, such as orientation change, Android destroys the Activity and recreates it. Normally, the Garbage Collector will just clear the allocated memory of the old Activity instance and we're all good.

"Leaking an Activity" refers to the situation where the Garbage Collector cannot clear the allocated memory of the old Activity instance since it's being (strong) referenced from an object that out lived the Activity instance. Every Android app has a specific amount of memory allocated for it. When Garbage Collector cannot free up unused memory, the app's performance will decrease gradually and eventually crash with OutOfMemory error.

How to determine whether the app leaks memory or not? The fastest way is to open the Memory tab in Android Studio and pay attention to allocated memory as you change the orientation.
If the allocated memory keeps on increasing and never decreases then you have a memory leak.

Example of memory leak in action
So how do we solve it in this case?


public class Splash extends Activity {
 // 1. Create a static nested class that extends Runnable to start the main Activity
    private static class StartMainActivityRunnable implements Runnable {
        // 2. Make sure we keep the source Activity as a WeakReference (more on that later)
        private WeakReference mActivity;

        private StartMainActivityRunnable(Activity activity) {
         mActivity = new WeakReference(activity);
        }

        @Override
        public void run() {
         // 3. Check that the reference is valid and execute the code
            if (mActivity.get() != null) {
             Activity activity = mActivity.get();
             Intent mainIntent = new Intent(activity, MainActivity.class);
             activity.startActivity(mainIntent);
             activity.finish();
            }
        }
    }

    /** Duration of wait **/
    private final int SPLASH_DISPLAY_LENGTH = 1000;

    // 4. Declare the Handler as a member variable
    private Handler mHandler = new Handler();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.splashscreen);

        // 5. Pass a new instance of StartMainActivityRunnable with reference to 'this'.
        mHandler.postDelayed(new StartMainActivityRunnable(this), SPLASH_DISPLAY_LENGTH);
    }

    // 6. Override onDestroy()
    @Override
    public void onDestroy() {
     // 7. Remove any delayed Runnable(s) and prevent them from executing.
     mHandler.removeCallbacksAndMessages(null);

     // 8. Eagerly clear mHandler allocated memory
     mHandler = null;
    }
}



  1. We first create a static nested class called StartMainActivityRunnable. It is important that the class is declared 'static', as non-static nested classes have implicit reference to their parent class - yet another reason for memory leaks. You may also choose to create this class independent of the Activity class; either way is good. 
  2. Then in StartMainActivityRunnable, we declare a WeakReference to Activity as a member variable and instantiate it via the constructor. We use weak reference since StartMainActivityRunnable might run after the Activity has been destroyed (for instance, in case the user has changed the orientation), and therefore in that case we don't want to prevent the Garbage Collector from clearing its allocated memory. 
  3. Finally, when it comes to StartMainActivityRunnable implementation, we first check that the reference to Activity is still valid before we execute the code to start the main Activity.
  4. Next, dealing with the client code that uses StartMainActivityRunnable, we declare Handler as a member variable of Activity class. This is very important, because we want to control it later on in the Activity lifecycle.
  5. We then call postDelayed on mHandler, passing a new instance of StartMainActivityRunnable with a reference to the current activity instance.
  6. Last but not least, and this is the most important part here, we override onDestroy()
  7. and call removeCallbacksAndMessages(null) on mHandler. This method will clear any pending Runnable(s) from executing after the Activity is destroyed!
  8. And finally, we eagerly set mHandler to null so it can be garbage collected a.s.a.p.

Checking the memory tab again, we can see that the graph doesn't change and remains flat.

Great job! We've fixed a significant memory leak and improved the app's performance.
Make sure to read my the next blog post, where I describe how your app can notify you of memory leaks and provide you a more efficient way to track them down using a library called LeakCanary by Square.

Thursday, 28 May 2015

AndroidTV hackathon at Google Stockholm

On Saturday the 9th of May, I've taken a flight to Stockholm, Sweden to participate in AndroidTV Hackathon that was organized by Google Stockholm. Top 40 Android developers from across the nordics have gathered to participate in a hackathon of a technology, which was new to mostly everybody.

The event started by the organizer, Robert Nyman, presenting AndroidTV, followed by Erik Hellman, an Android Expert, who gave a quick intro into the new Leaback library for developing AndroidTV apps.

Shortly after the introduction, we jumped right into coding. Sitting next to Spotify's developer, Mattias Janson, who was working on Spotify's AndroidTV app, I started working on Rovio's Toons.TV AndroidTV app.
I'm sitting at bottom right side of the picture

The Leanback library seemed pretty straight forward and within a few hours I was able to develop a proof of concept of our Toons.TV app for AndroidTV. At the end of the event, we presented our work. Each team gave a quick demo of what they've accomplished.
Here I'm presenting proof of concept for Rovio's ToonsTV for AndroidTV
Finally, the top 3 demos won brand new Nexus Players. Unfortunately, I wasn't one of them, but I did make it to win a Chromecast and get AndroidTV dev kit! :) To my defense, I can say that the "competition" was a bit unfair, since other teams had 3 guys in them while I was a one man team ;)

All in all, it was a great experience and I enjoyed the company of professional Android developers. It was exciting to visit Google's offices in Stockholm. I got to learn new things and get tips from the experts.

Looking forward for my next hackathon.

Monday, 29 December 2014

WizarDroid 1.3.0 released

WizarDroid 1.3.0 released

It's been a while since the previous WizarDroid release. It's been a very busy year for me. Started working for Rovio Entertainment (the company that made Angry Birds) and we recently had our first born. I tried to answer emails and comment on issues on GitHub as much as I could. Finally, I got some spare time during Christmas holiday and decided to clear out the bugs reported on GitHub.

I decided to increment the version directly to 1.3.0 since it has major refactoring to the way WizarDroid processes next and back steps. This also affects the swipe sensitivity that was reported. The animation now looks smoother. The following were fixed in this release:

  • Context variable values are now persisted after orientation change
  • Swiping among steps is working smoothly and not sensitive as it was before
  • ContextManagerImpl.persistStepContext() threw NullPointerException when handling Date types
  • Crash occurred when having more than one required step marked completed
In addition to bug fixes, the following changes were made:
  • Gradle Wrapper - solving the need to upgrade Gradle everytime
  • New Feature: Automatically hide soft keyboard on step switch - contributed by @Alexander-
  • Removed: Installing WizarDroid.aar to local maven repository via 'gradle install' command is not supported anymore. Either use WizarDroid's global Gradle dependency via Maven Central or include it as a library project in your app.
  • Upgraded to Android API level 21, including build tools 21.1.2 and support-v4:21.0.3

The future plan for WizarDroid


I'm planning to rework the sample app and make real-life example, possibly some kind of fast food ordering app. This is aimed to be release in 1.4.0. In the same release I'm planning to have instrumentation tests, which will run against this sample app to increase the quality of each release.

I recently made a search in Stackoverflow and found out a few questions regarding WizarDroid. I'm definitely going to take this feedback into consideration and I'm planning to make WizarDroid more dynamic, in a sense that you can define logical tests that will affect the wizard flow. The aim is to release it under version 2.0.0 as I see major refactoring required for that.

Regarding the actual timetable... well, I don't have much free time :D LOL.

Tuesday, 1 January 2013

Swipe to strike out an item in ListView

I wanted to add some touch functionality to the basic Android's ListView to make it the way they did it in Any.DO app. I wanted to make each list item strike-able by just swiping my finger from left to right.

The first thing I had to do is to extend ArrayAdapter and then hook up the OnTouch event there. I called it SwipeArrayAdapter. Here is the code:

public class SwipeArrayAdapter extends ArrayAdapter implements OnTouchListener {

private static final String TAG = "SwipeArrayAdapter";
private float mLastX;


public SwipeArrayAdapter(Context context, int resource,
int textViewResourceId, List objects) {
super(context, resource, textViewResourceId, objects);
}


@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = super.getView(position, convertView, parent);
v.setOnTouchListener(this);
return v;
}


@Override
public boolean onTouch(View v, MotionEvent event) {
float currentX = event.getX();
TextView tv = (TextView) v;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mLastX = currentX;
Log.v(TAG, String.format("onTouch: ACTION_DOWN for %s", tv.getText().toString()));
break;
case MotionEvent.ACTION_MOVE:
Log.v(TAG, "onTouch: ACTION_MOVE " + currentX);
break;
case MotionEvent.ACTION_UP:
if ( currentX & mLastX + v.getWidth() / 6) {
Log.v(TAG, "Swiped!");
tv.setPaintFlags(tv.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
}
break;
}
return true;
}
}

As you can see in the code snippet, I extended ArrayAdapter and implemented OnTouchListener. I then override the getView method from ArrayAdapter and by calling the parent method first I guarantee that the view won't be null and wire the OnTouch event. Notice that I pass this to v.setOnTouchListener. Since I implemented OnTouchListener, we can conveniently pass it as an argument.

Now that I got each List Item wired to an OnTouch event, I proceed to the implementation of the OnTouch method. The most important part in this method is the MotionEvent argument which is passed to it. By switching through its getEvent method, I can query for the view's touch state. The most important states which we should look for are: ACTION_DOWN - when user touch the screen, ACTION_MOVE - when user moves the finger, ACTION_UP - when user picks up the finger off the screen.

I use simple calculation to check if the user swiped the finger from left to right to indicate that the item should be crossed out by storing the initial X position of the touch event and then when the user picks up the finger I check if the current X position is greater than the original X position. The formula I use here is probably not the best. I divide the screen to 6 parts and check if the current X is bigger than the original X + 1/6 of the screen. I would be happy to hear any other solutions for this scenario. But, for the purpose of this demo, I assume it will suffice. Finally, I set the paint flags of the TextView to strike out the text.

One more thing that's worth mentioning is that it's important to return true from the OnTouch method. The reason for that is that when we return true, we tell Android to keep sending OnTouch events to this method, therefore making sure that we also receive ACTION_MOVE and ACTION_UP. Otherwise, if we return false the event will be consumed by another event listener down the chain.