First Play on Muzei

Muzei live wallpaper is a new opensource project from Roman Nurik which provide a nice API for other developers to build extension on it easily. Just a few days after its release on Feb 12, you can already find quite many different data source for it. So I played for a while today and found that it is… really easy to implement your own data source.

Here is a quick start on creating the extension.

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
public class MyArtSource extends RemoteMuzeiArtSource {

    private static final int UPDATE_INTERVAL = 60 * 60 * 1000; // 60min

    public MyArtSource() {
        super("my-art-source");
    }


    @Override
    public void onCreate() {
        super.onCreate();
        setUserCommands(BUILTIN_COMMAND_ID_NEXT_ARTWORK); // manual switch image
    }

    @Override
    protected void onTryUpdate(int reason) throws RetryException {
        // fetch title, imageUrl, id, url from remote or hardcode

        publishArtwork(new Artwork.Builder()
            .title(title)
            .imageUri(Uri.parse(imageUrl))
            .token(id)
            .viewIntent(new Intent(Intent.ACTION_VIEW, Uri.parse(url)))
            .build());

        scheduleUpdate(System.currentTimeMillis() + UPDATE_INTERVAL); // switch image after 60min
    }
}

You can find my Muzei 9GAG extension on Play store, source code available on Github

Implementing Zoomable View - Part 1

Last year I implemented a custom view that supports different gestures including zoom(scale), scroll, double tap. As a newbie on custom view, the whole measuring and drawing already spent me some time, so the gesture control turned out enough to use but was actually incomplete and not finished.

Recently, I have a task to embed my custom view to ViewPager and other custom ViewGroup that intercept touch events. As expected, my custom view takes all the touch events so the ViewPager cannot perform horizontal swipe. I woule like to take this chance to review my gesture handling and hopefully can make it work.

What I did last year is mostly referencing Chris Banes’s PhotoView library. The basic idea is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class ZoomableViewAttacher implements View.OnTouchListener {
    GestureDetector mGestureDetector;
    ScaleGestureDetector mScaleGestureDetector;

    ...

    @Override
    public final boolean onTouch(View v, MotionEvent ev) {
        boolean handled = false;

        ...

        if (null != mGestureDetector && mGestureDetector.onTouchEvent(ev)) {
            handled = true;
        }

        if (null != mScaleGestureDetector && mScaleGestureDetector.onTouchEvent(ev)) {
            handled = true;
        }

        return handled; // or just return true;
    }
}

So far this worked for me last year as I am using the view alone, I did not have to consider the case that the view’s parent intercepted the touch event.

Now the problem is, how do I prevent the ViewPager intercepting my touch event? After digging deeper, I found a requestDisallowInterceptTouchEvent method in ViewParent. According to the framework doc

Called when a child does not want this parent and its ancestors to intercept touch events with onInterceptTouchEvent(MotionEvent).

This parent should pass this call onto its parents. This parent must obey this request for the duration of the touch (that is, only clear the flag after this parent has received an up or a cancel.

Which means, if I call the method in correct time, I should be able to enable and disable ViewPager’s onInterceptTouchEvent. Googled a little bit on requestDisallowInterceptTouchEvent, found some example on StackOverflow like

1
2
3
4
5
6
7
8
9
10
11
switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:
        parent.requestDisallowInterceptTouchEvent(true);
        break;
    case MotionEvent.ACTION_CANCEL:
    case MotionEvent.ACTION_UP:
        parent.requestDisallowInterceptTouchEvent(false);
        break;
    default:
        break;
}

This is obviously not enough for me, since it disabled the parent for the whole touch motion, if I touch on my custom and actually want to perform a page swipe on ViewPager, thie code will definitely break the ViewPager usage.

My first attempt is something like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:
        parent.requestDisallowInterceptTouchEvent(true);
        break;
    case MotionEvent.ACTION_CANCEL:
    case MotionEvent.ACTION_UP:
        parent.requestDisallowInterceptTouchEvent(false);
        break;
    default:
        break;

    if (!canScroll()) {
        // re-enable parents' onInterceptTouchEvent
        parent.requestDisallowInterceptTouchEvent(false);
    }

}

It would be great if GestureDetector can directly give me the information needed for my canScroll() method. However, it seems that GestureDetector need a few events to determine if it is a scroll, there is a gap of 3-5 events between my first ACTION_DOWN and onScoll callback, so I need a better way to determine the condition for calling parent.requestDisallowInterceptTouchEvent().

In part 2, I will continue with the implementation of canScroll() method.

Android Development Resources Collections

Recently read

  • Facebook: mobile engi blog, github
    • Building a faster Messenger

      Michael Marucheck, had the idea to actually edit the Java byte code after compilation. We used ASM to improve our dependency injection system by detecting bindings that are safe to remove, adding static methods that instantiate a bound type, and rewriting calls to the injector to instead call the appropriate static method. By improving this process, we were able to have a well-crafted dependency injection system that lets us test at scale, but still with the 30% gain in speed.

Other

My 2013 Android Development

2013 was a fresh start for me. I joined a new team, started the Android product from scratch, get a nice number of active users and keep it growing. During my development, I referenced many opensource projects and learnt alot from them.

kevinsawicki/http-request

This is the very first library I added to my project (support-v4 does not count). This library provided a nice wrap of http call. I am not sure if this can be used with other network library like square/okhttp and android/volley, hope I have time to try it out in 2014.

jfeinstein10/SlidingMenu

This is the sliding menu I used at the beginning, I like the effect very much. Although I switched to Android DrawerLayout after it was introduced in support-v4, I do like the old SlidingMenu more. Personally I like to have the drawer push the content out, DrawerLayout is more like an overlay, they both make sense to me, let see will the design guideline include this kind of UI also.

square/otto

I am a big fan of Square opensource projects but I was not using any event bus so when I saw otto I did not get it at first. When things getting complicated that you cannot write everything in your Activity/Fragment, you will try to split the logic to different components. The old school way to communicate between components is implements some kind of listener, it works for a while, a short while… The app goes complicated way faster than I expect, so I decided to make a big structure change by using an event bus system. I have not compared other event bus library but otto works for me perfectly.

ActionBar

Before the official actionbar-compact was released after GoogleIO, I think most people will use ActionBarSherlock. However, I implmented my own. I think it gives me more flexibility if you implemented your own, especially when you dont need those inflate from menu support. The down side is you lost support from all opensource projects, I have to implement my own refresh/progress buttons, ShareActionProvider, cannot play with those fancy fading actionbar, not boring actionbar library, may even need to write my own android style pull to refresh. Those disadvantage are usually enough to stop me from using my own implementation, but I decided to keep it. Mostly because it turns out not that hard to migrate to my own actionbar as long as it is opensourced and I do not have to worry about two libraries not working together (because I am not using any…).

Github TODO List 2013

Found some cool projects on Github but still do not have time to play with it. Here is my list containing projects I found in last 6 months:

Action Bar

Facebook

  • facebook/rebound – though not everyone is happy with the facebook app on Android, it is so nice to see Facebook opensource some Android projects.

UI

Network

other

  • path/android-priority-jobqueue – I implemented my own, but it is always good to learn from other’s code
  • koush/ion – a full featured image download lib, with a gif player integration that could help me :p
  • dlew/android-movies-demo – some nice animations, though I don’t think this is a good way to use the ViewPager