Sunday, February 24, 2013

SVG on Android

In my latest app I had a chance to use SVG images. I thought it might be useful for others to learn, how it can be done and what the main advantages/drawbacks of this approach are. Here's the whole story.


Motivation

I wanted to display a map of subway and suburban connections in Milan and let users zoom in and turn off some details they didn't need. However, the map image I was using was too big and I kept getting an OutOfMemoryError. I made the image smaller, but then the details became blurry and it looked bad when magnified. I could just settle on a compromise and load the biggest image that would fit into memory, but it wouldn't look perfect anyway and there would be a possibility, that some other data would cause an OutOfMemoryError. That's why I decided to give vector images a try.

What is SVG

Citing Wikipedia: "Scalable Vector Graphics (SVG) is an XML-based vector image format for two-dimensional graphics". It basically means, that images are not described by their pixels, but rather by shapes and objects they contain. This description is then saved as an XML file.
So, for example, instead of having:
pixel0: #ffa4c0, pixel1: #d49506, pixel2: #94ac3d, pixel3: #84850b, ..., pixel1000000: #de3a21
we might have:
line from x: 30, y: 20 to x:435, y: 847, color: #e93847, width: 4px
Of course it's not possible (or easily done), to transform all images into SVG. How would you describe a photograph by means of simple shapes? However, when creating logos, icons, buttons, backgrounds, maps or UI elements for your app you may choose to save them as SVG images. This way, they'll take up less space and remain infinitely scalable. If you don't believe that you can make them look as good, see the Inkspace's showcase.


Tools and Libraries

When you try to find some information about using SVG with Android, this post on Stack Overflow comes up, saying that only on Android's 3+ default browser can render this format. There is no native support for SVG images in apps though. That's not good news, but what do we have external libraries for?

After some searching, I managed to find svg-android library, but then it turned out, that it was last modified in May 2011 and therefore is slightly outdated. Fortunately, there's also a fork on github by Josef Pavlik fixing some bugs and adding extra features to it. The library only supports SVG Basic 1.1 specification, but it should be enough for most cases. You can see a sample image it can render on the left. Some more samples can be found here.

To make SVG images scalable, I used TouchImageView. I had to fix some bugs in it and add orientation change support, but otherwise, it did its job.

To create SVG images I first used Inkspace - a free open source graphic editor. I had some problems exporting files as SVG Basic 1.1 though, so I switched to Adobe Illustrator. You can download a 30-day trial version or buy one here.

Source Code

You might be surprised, how easy it is to use SVG images. To create a Drawable from an SVG file, all you need to do is:

SVG svg = SVGParser.getSVGFromResource(getResources(), R.raw.filename);
Drawable svgDrawable = svg.createPictureDrawable();
Then, you simply use it as a regular image:

ImageView myImageView = (ImageView) findViewById(R.id.myImageView);
imageView.setImageDrawable(svgDrawable);

Summary

SGV images are a good replacement for bitmaps in many cases. Although they are not supported natively by Android, they can be easily displayed by means of third party libraries. They take up much less space (especially the zipped version - svgz), scale indefinitely without losing any detail and don't require a separate version of an image for each screen density.

So why not use them in all cases? First of all, not all images can be transformed into SVG. As I said earlier, photographs or sophisticated images with shadows, transparency, gradients and reflections are much harder to represent in a vector format, because they are not just simple shapes.
Second, I noticed that large SVG images with thousands of objects (like the ones I'm using) take some time to load. For example, my map is stored in a 200kB svgz file and it needs a little more that a second to become ready for display. I have to load 4 versions of this map, so you can imagine, that it was taking so much time, I had to add a splash screen to my app, so users don't see a blank screen for 5 seconds or so. This might be a little extreme example, because you don't usually need so many objects in your image, but it's good to be aware of it. Regular bitmaps don't load longer if they contain more colors or more shapes, because it's the pixels that matter.
Finally, after publishing my subway map, I noticed an occurance of a weird exception:

java.lang.UnsupportedOperationException
  at android.view.GLES20Canvas.drawPicture(GLES20Canvas.java:911)
  at android.graphics.drawable.PictureDrawable.draw(PictureDrawable.java:73)
  at android.widget.ImageView.onDraw(ImageView.java:910)

After some digging on Google I found out that Canvas's drawPicture function is not supported while hardware acceleration is on. I certainly hadn't turned hardware acceleration on, so I kept searching and found out that on some versions of Android there's a bug which causes hardware acceleration to turn on by itself. I didn't have access to a device with Android 3.0 or one with hardware acceleration, so I couldn't reproduce this issue. All I managed to do was adding:

    android:hardwareAccelerated="false"
to my application manifest, just to make sure hardware acceleration was off. The exception has not reoccured since then, but it might as well be a coincidence...

All in all, SVG images turned out to be really useful, but it's definitely worth testing your app on multiple devices, to make sure everything works fine and doesn't produce any unexpected exceptions.


UPDATE
I just wrote another post on SVG images and using them in your apps without the need of any external libraries or code. Check it out:
http://androiddreamrevised.blogspot.it/2014/06/transforming-svg-images-into-android.html

Monday, February 18, 2013

Milan Subway Map

For the last week or so, I've been working on an app for browsing a map of subway and suburban trains in Milan. Well, here's the lite version and the one without adds. Now, let's have a short postmortem.

What went well

I managed to get hold of a subway map in a vector format. I only had to add the missing purple line and make some modifications, so it could be used on Android. Thanks to that, the quality of the map is very hight and it can be zoomed in indefinitely without the loss of any detail. Isn't that cool!

I also had a chance to practice my icon design skills and this time I'm really proud of myself. Just look at the color choice, the mild gradient and the simple shape of the letter M. Hell, I'm getting better and better at it.

What went wrong

Although the idea behind the app was pretty neat, I failed to check Google Play for similar ones. It turns out, that there are a couple apps which do almost the same thing. Their usability may not be as good, but they add some other features, like a detailed map of the suburban network or a satellite view.

Conclusion

SVG images are great! They take little space, look good even when zoomed in and you don't have to provide a separate version for each screen density. I'll definitely write the next post about how to use them.
Next time though, I have to be more careful when choosing an idea to implement. It's better to commit an hour or two checking Google Play for similar apps than to loose days/weeks to create something utterly unoriginal and with a strong competition.

Wednesday, February 13, 2013

Income Report

When I started my Android adventure, I was extremely excited about the passive income you could create this way. I hadn't really had any previous experience with ad networks or publishing your own paid adds, so I decided to just give it a try and see what I'd get. Well, here's what I have achieved so far.

AdMob

I have roughly 2000 active installs of my free apps containing ads. With these, I get about 1000 ad requests every day with eCPM euqal to $0.30. For all those, who are not into advertising business, it basically means that I earn $0.30 for every 1000 people who see an ad. Doing some very simple math, it gives you the amount that I make daily, which is $0.30, and monthly $9. The CTR is 0.64% which means that only one person in 156 clicks on an ad they see.

Is it much or could I be making much more from it? I don't know... yet. I will have to do some research on it and perhaps try some other ad networks. Some of them even started sending me invitation emails, asking if I want to join and giving me a starting bonus.

The thing I know right now is that the country specific apps that I wrote are making significantly less than Toilet Sounds. Their eCPM is only $0.02 which renders their revenue virtually negligible. They also impact the general statistic, which would look much better, had I not taken them into account. What is the reason for this? Bad ads targeted at Polish people? The way I display an ad (a showing and hiding panel at the top of the screen)? Or maybe something totally different?

Paid versions of Live Wallpapers

Having a little over 1000 free wallpapers downloaded, I sold 15 paid ones. I earn $1 for each copy sold, so it's very simple to calculate that I have earned $15. Not too much... Also, most of it was during the time, when they were on the main page of livewallpapers.org. Unless I find a better way to promote them, it's not a very profitable business.

MiKandi

There is one thing I haven't written so far. Some time ago I made three apps with adult content to see, if maybe there was money potential in them. As a matter of fact, I managed to make $90 (for the last couple of months). I haven't published them on Google Play though, because the policy forbids it. Instead, I put them on MiKandi - the biggest app market with adult content. I guess people there are more used to paying for the apps. Anyway, I don't really want to go that way and writing such apps is not what I like the most. I also lack the necessary content, so it would be difficult to think of something new.

Conclusion

Considering the time I spent learning how to program Android and then making the apps, it was totally not worth it. However, I will keep trying anyway, because I like it and I love the feeling when people actually download and use what you've created. It's also nice to be able to add your projects in the CV and consider yourself to be a real Android programmer.