Monday, January 18, 2016

Paperwork - a Gradle plugin to add build info to your project without breaking incremental builds


A common use case is that you want to include the git hash of the last commit and build time into your project, so that you can use their values in your crash reporting tool (for example).

The easiest way to do this is to generate them into your BuildConfig by adding these lines to your build.gradle:

But this will break incremental builds, resulting in increased build times all the time.

A solution could be to write information into an asset file instead of BuildConfig, and then read that file during runtime, which is exactly what Paperwork does:

https://github.com/zsoltk/paperwork

An added benefit is that you can now include any other information as well (output of a script maybe) that would result in a full recompile otherwise.


Friday, December 4, 2015

Overpasser - open source, fluid Java interface to OpenStreetMap data

Get the code at: https://github.com/zsoltk/overpasser

Provides an easy way to fetch POIs and other OpenStreetMap data. No more query string forging by hand!

Comes with a Retrofit adapter and an Android sample to get you up and running immediately:



Wednesday, September 2, 2015

Open source Conway's Game of Life for Android with editable rules

Android app on Google Play

Source: https://github.com/zsoltk/GameOfLife

You can use the codebase to implement your own cellular automata, as it was intentionally designed to be easy: implement your own rules (maybe color mapping for custom states) and you're good to go.

Even if you're not familiar with cellular automata, both playing with the app and discovering the solutions behind it can be fun.

You can also edit the rules in the app to have some pretty interesting results instantly:




Some Gradle tricks for Android

Just my two cents on my favorite gradle tips & tricks.

Friday, August 21, 2015

Some twists of using Google Maps in your Android app - Part 2: Adding a Floating Action Button and fighting BadParcelableException

Part 1: Smart follow

If you want to add a custom control over your custom MapFragment, there's actually more than one way to do that. Either you can add your control in the layout of your enclosing Activity, or you can override the onCreateView method in your Fragment and add the view there.

Because the previous will add an element that is visible on top of all your Fragments displayed in your Activity (which sometimes can be useful, too), now I'm gonna go with the latter:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
    View view = super.onCreateView(inflater, parent, savedInstanceState);
    TouchableWrapper touchableWrapper = new TouchableWrapper(getActivity(), this);
    touchableWrapper.addView(view);

    View controls = inflater.inflate(R.layout.map_overlay_controls, null);
    touchableWrapper.addView(controls);

    return touchableWrapper;
}
Here I'm inflating a TouchableWrapper (see Part 1 to see why) and adding a custom layout on top of that, but you could just skip those lines and call view.addView(controls) directly. In this case I'm adding a Floating Action Button from https://github.com/clans/FloatingActionButton among other things.

Now the problem might not appear immediately - unless of course your mommy have taught you to always use the Don't keep activities flag in the Developer options when you were a little toddler, as she should have.

The next time your app comes back after having been put to rest by the OS and tries to restore its state, there's a good chance that it will crash and burn with a BadParcelableException:
java.lang.RuntimeException: Unable to start activity ComponentInfo{...}: android.os.BadParcelableException: ClassNotFoundException when unmarshalling: com.github.clans.fab.FloatingActionButton$ProgressSavedState
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2314)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2388)
            at android.app.ActivityThread.access$800(ActivityThread.java:148)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1292)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5312)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:901)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:696)
     Caused by: android.os.BadParcelableException: ClassNotFoundException when unmarshalling: com.github.clans.fab.FloatingActionButton$ProgressSavedState
So what is the problem here and how can you solve it?

Wednesday, August 19, 2015

Some twists of using Google Maps in your Android app - Part 1: Smart follow

Following the user's location only when he hasn't panned the map away (as otherwise the view will animate back to the current location every now and then, providing quite a frustrating experience) is a commonly used functionality in applications with maps (say, tracking your route and such). I kinda feel there should be an out-of-the-box method for this in Google Maps SDK, but whatever, here you go if you want to implement it.

Saturday, August 15, 2015

Android Vision API

Back in the day if you wanted face detection, you had to code it yourself. How much easier and simpler it is now, with the new Vision API on Android:


It even tells you how much the detected face is smiling! Awesome.

Arjunu.com has a great tutorial on how to integrate it into your project, check it out.

Also, you can check out the official samples on GitHub.

On a slightly off-topic sidenote (using face detection, but not the Vision API), I just saw Boo! on Android Experiments yesterday: 

Little creatures gather on the screen. As soon as they see your face, they flee in panic. Too cute to not include it here :)