Androidsx Androidsx | android ninjas

 

Our blog, latest news, tips on software quality, monetization, etc.

 

New features in Java 7

September 27, 2011 at 10:37 pm | blog, general | No comment

 
New features in Java 7

Here’s a summary of the most exciting features of the upcoming Java 7, which is of interest for the Java community and, consequently, for Android developers!

Language enhancements

Left to right type inference

This basically allows you to write Map<String, List<String>> retVal = new HashMap<>(); instead of Map<String, List<String>> retVal = new HashMap<String, List<String>>();, which is unnecessarily verbose.

It also infers the type of the return type: in a method whose signature is Map<String, List<String>> parseSomething() you can just return new HashMap<>(); and have the generics information inferred.

Using strings in switch statements

A natural extension of the switch statement. No longer do we have to map those strings to integers or enums, or write error-prone anidated if statements. It’s also a bit more efficient. For details see the Compilation section in the initial proposal.

Automatic resource management

Not much ago, we spent quite some time tracking down a bug because some DB connections were not closed. In complex infraestructures (i.e., where you use Spring, define several aspects to AspectJ, but sometimes you also program at the low level for optimization purposes), this is not always a trivial topic. Making sure you free this type of resources will no longer be necessary.

With Java 7, you can write

try (InputStream is = new FileInputStream(new File("foo.txt"))) {
    // read the file and do something with it
} catch (IOException e) {
    // handle this
}

instead of the more verbose, error-prone:

InputStream is = null;
try {
    is = FileInputStream(new File("foo.txt"));
    // read the file and do something with it
} catch (IOException e) {
    // handle this exception
} finally {
    if (is != null) {
        try {
            is.close();
        } catch (IOException ex) {
            // ignore this exception
        }
    }
}

You can thank the java.lang.AutoClosable interface, that has just one method: void close() throws Exception;.

Improvements to literals

Underscores: now you can write int billion = 1_000_000_000; instead of int billion = 1000000000; in order to make sure you don’t miscount the 0s.

Binary literals: this is an obvious extension to the literals, now you can write int yourInteger = 0b100100101; // 293 in decimal.

Improved exception handling

It’s common (and not necessarily a bad sign) to deal with different exception types in the same way. Instead of duplicating code by copy-pasting the same exception routine, now we can use the OR (\|) operator to group the exceptions:

try {
    methodThatThrowsThreeExceptions();
} catch (ExceptionOne e) {
    // deal with ExceptionOne
} catch (ExceptionTwo | ExceptionThree e) {
    // deal with ExceptionTwo and ExceptionThree, even if they belong to different hierarchies
}

Somewhat related to this is the ability to rethrow exceptions with their original types, with no wrapping, and without the need to catch them separately. The following piece of code, valid in Java 7,

private void throwExceptions() throws A, B, C {
    try {
        // some operation that's declared to throw A, B or C exceptions
    } catch (Exception e){
        LOGGER.error("Caught " + e + " and rethrowing it", e);
        throw e;
    }
}

is exactly equivalent to

private void throwExceptions() throws A, B, C {
    try {
        throwAccordingToIndex(new Random().nextInt(2));
    } catch (A e){
        LOGGER.error("Caught " + e + " and rethrowing it", e);
        throw e;
    }
    catch (B e){
        LOGGER.error("Caught " + e + " and rethrowing it", e);
        throw e;
    }
    catch (C e){
        LOGGER.error("Caught " + e + " and rethrowing it", e);
        throw e;
    }
}

You could argue that you should be using AOP here for the instrumentation of this exceptions, but that’s another topic.

New I/O API version (NIO.2)

You’ve probably had issues at some point in time with working with absolute/relative paths, especially for programs that run in different operating systems. Also, deleting/renaming files lead to issues, as it did working with symbolic links. This version aims at making these uses cases easier.

Path

The class java.nio.file.Path will probably become the most commonly used in this package. It’s a substitute of our beloved java.io.Path, but better. You can do FileSystems.getDefault().getPath("hello.txt");, or Paths.get("file.data").getParent();. It’s basically simpler to use, especially in an environment with different filesystems.

Files

This utility class provides over 50 utility methods, such as copy(), move(), newInputStream(), readAllBytes(), createSymbolicLink(), …

Watch Service API

This new API lets you listen to some system events related to files and directories, such as when a new file is created in a directory. For details, check out the javadoc of the WatchService.

Fork and Join

The fork/join framework helps you make effective use of current architectures with many cores. It is an implementation of the well known ExecutorService, that uses a work-stealing algorithm to make sure that no worker threads idle by stealing tasks from those that are busy.

It seems fairly easy to use as long as you have a good way of splitting your processing needs into smaller tasks. There is a very handy guide in this tutorial by Oracle.

Dynamism

This does not affect us directly, but it’s a nice addition for the Java Virtual Machine, to which we are seriously tied to.

More and more dynamically typed languages want to leverage the JVM, but they are limited by the fact that the JVM was conceived to be statically typed, which implies that the type information is only checked at compile time, and thus the JVM executes this strongly-typed bytecoded without caring about the type information. This is a limitation for the dynamically typed languages where the type information is unresolved until runtime. A new feature, named invokedynamic, has been introduced in java.lang.invoke, which will allow to create performant, high quality implementations of such languages easier.

Share
 

How a simple dialog increased the sales of our Android app by 260%

March 28, 2011 at 8:08 pm | android, blog, monetizing | 12 comments

 
How a simple dialog increased the sales of our Android app by 260%

Short version. By introducing a dialog in our free application that encouraged the user to purchase the ad-free, paid version of it, we increased sales by 260% in the first week: 20% of the users clicked on the Go PRO button and, out of those, 15% finally bought our paid application.

Long version. We launched Spell Checker back in May 2010. It has been downloaded a million times (actually 985072, but come on, it sounds so much more cool), and has 60% active installs. It is ad-supported (by Admob, but it used to be Mobclix, see our experience with them here), and it doesn’t do too bad, with a eCPM of $0.09. The paid application is Spell Checker PRO, which is the same application, but without the ads. It used to be named Spell Checker Donate, in order to be very clear about the fact that there are no extra features.

It turns we need a user to click 70 times over our ads in our free version in order to generate more revenue than the paid one. We know this after doing a couple of operations over our Admob numbers. So, it is clear, we need to increase our conversion rate. (Still, we had a glance at our Flurry analytics, 18% of our users use our app more than 4 times a week. Not bad, but 40 clicks are way too many!)

What we did is dead simple: when you’ve used the application for 3 times, you get this dialog:

Go PRO dialog in Spell Checker

Go PRO dialog in Spell Checker

In order not to bother the user too much, we’ll wait until he has used it for 5 additional times before we show a similar dialog. Then, we’ll show it 8 times later, 13, 21, … (By the way, can you guess the next number in this sequence? :) ). The text will be slightly different each time, sort of like “So, do you like it now, or still not sure?”. Also, for existing users the message is a bit different.

While we analyzed this and other alternatives, we of course wanted to based our decision on numbers. Our estimate was that 2.5% of the active users would convert:

  • 50% of the users won’t even get to see the dialog in the first month. They are not active enough. This figure comes from our Flurry stats.
  • Out of the remaining half, 5% of them (1 out of 20) will hit the “Go PRO” button and buy it. This figure comes purely out of our air.

That sucks. We have no idea how many users will decide to buy it just because we suggest they do it. But now we know!

This pie chart shows the ratio of users that chose Free, 80%, versus those that decided to go PRO, 20%:

Users that choose PRO vs Free, from our Flurry stats

Users that choose PRO vs Free

We have matched the absolute numbers here with the actual revenue in Checkout, and it turns out that only 15% of them finally performed the purchase. That means, 3% of the users bought our application just because of our dialog. 3% is 15% of those 20%, and represents the magic ratio that we guessed out of air.

As a consequence, our daily revenue has grown by 260%, comparing the first week after we implemented this to the preceding weeks.

We are aware that the daily sales will considerably shrink after the dialog has reached most of the existing user base. So, of course this 260% won’t work for a new application. But it remains true that this has been the impact on our numbers, and hopefully all this helps you in your own estimates, which is our main objective with this post. Social behavior is so unpredictable!

We are just starting out in this fascinating world, and are aware that we are not good at selling. So help us a bit: how would you suggest we increase our conversion rate?

Share
 

Stop the spread of nulls

October 4, 2010 at 7:38 pm | blog, software quality | 2 comments

 
Stop the spread of nulls

Say we want to write an Android application that listens to everything you say, and tries to find the information that you might need before you even ask for it. For instance, you ask your friend over the phone Is there any good pizzeria near your place?, and this application will perform a query against Google Maps using your friend’s address retrieved from your phone contacts and provide you with a couple of recommendations.

To parse the user commands, after converting the speech to text, and provide the appropriate action handlers, we have these high level interfaces:

public interface Parser {
    Action findAction(String userInput);
}

public interface Action {
    void performAction();
}

There are two proposals for the implementation of the parser:

// Altenative A
class DbBasedParserA implements Parser {
    @Override
    public Action findAction(String userInput) {
        // Find the appropriate action in the DB
        return actionFound ? theAction : null;
    }
}

// Altenative B
class DbBasedParserB implements Parser {
    private static final Action DO_NOTHING = new Action() {
        @Override
        public void performAction() {
            // Do nothing
        }
    };

    @Override
    public Action findAction(String userInput) {
        // Find the appropriate action in the DB
        return actionFound ? theAction : DO_NOTHING;
    }
}

What are the consequences of this choice? Let’s see the code of the clients [1]:

// Client for alternative A
Parser parser = ParserFactory.getParser();
if (parser == null) {
    throw new IllegalStateException();
}

Action action = parser.findAction(someInput);
if (action == null) {
    // Do nothing
} else {
    action.performAction();
}
// Client for alternative B
ParserFactory
    .getParser()
    .findAction(someInput)
    .performAction();

And this is contagious. Those if (action == null) are going to keep on spreading over the different layers of the system unless some API stops it. Help save lines of code and NPEs by ensuring no nulls are passed around!

[1] There is also a ParserFactory, with two implementation alternatives that react differently when no parser is found: one returns null, while the other throws unchecked exceptions. Back to post.

Share
 

Can’t get our money out of Mobclix [Updated]

August 21, 2010 at 9:20 pm | android, blog, monetizing | 47 comments

 
Can’t get our money out of Mobclix [Updated]

This post is related with a comparison we did between Admob and Mobclix. Look at the Admob vs Mobclix: 1st round, 2nd round and 3rd round.

Find the updates below.

Will those numbers in your Mobclix analytics page ever turn into real money? Apparently it’s not so easy. And we are not the only ones, see here and here.

In short: we started generated revenue on March 2010 and now, in August 2010 and close to 5-figure numbers, we didn’t receive a single cent.

Long version: see our discussion with Mobclix support below.

Delayed payment

This is the e-mail that we sent on August 12 to Mobclix support:

During March, our first month with Mobclix, we generated $268.09 with our applications:

FML (803e8557-b71d-4937-b23a-8802ab22b125): $35.97
MLIA (cdf3868e-16b2-4611-ae83-4c6736400c50): $86.85
TFLN (cbc66b89-e88a-4e5e-8eb1-f3dbd36faf84): $145.27

Our questions are:
1) Why did we not receive any payment yet?
2) Why does the Invoice for June 2010 says $69.72? (Instead of $268.09)
3) Why didn’t we receive any payment yet? (We forgot this question in the original message)
These questions equally apply for the following month, April (whose invoice was generated during July)

The answer was just a document with the invoice for June (March’s revenue), splitting the contribution from every ad company. To this, we replied explaining what exactly were the mismatches between the figures in our Mobclix analytics and those in the invoice. In short, it should be 4 times bigger.

The answer was:

Mobclix will make payouts when we receive payments from ad networks. So while you may not be paid for a certain network in a month, we are working on collecting the payment and will remit it in your next invoice.

Irregularity in Revenue reporting

This is a different issue, and pretty worrying too. This was our ticket to Mobclix, on August 12:

In the Revenue tab for our applications, we noticed that, for 21-27 July, the generated revenue figures dropped a posteriori, after those days had passed. We can’’t find any reason or official explanation.

More specifically, here you have a table with the comparison of the figures that we observed before and after July 31:

DateBeforeAfter
27 July62.40$39.53$
26 July66.10$34.70$
25 July73.32$34.28$
24 July78.62$37.70$
23 July73.18$36.93$
24 July78.05$27.53$
23 July61.12$32.44$

We never got an answer.

What’s funny is that, if we hadn’t seen this, we would never have noticed. Maybe you think you made 100 dollars per day last month, but it has now magically to 40. No kidding.

Next steps

We still have hope that Mobclix will react, and understand how serious these issues are. We’ll keep you posted.

Updates

August 24: They just generated and executed the pending invoices. That was a quick reaction on their side! Still, we have not managed to match the figures of the monthly invoices with those on Mobclix’s Revenue tab (it would be great to know how exactly those are calculated).

Share
 

Admob vs Mobclix: 3rd round [Updated]

August 21, 2010 at 9:15 pm | android, blog, monetizing | 7 comments

 
Admob vs Mobclix: 3rd round [Updated]

This is the third part of a series of posts, look at the 1st round, 2nd round, and some related problems.

In our previous posts we didn’t cover a critical topic: how to cash out the revenue (ie, money) that you generate.

Admob

Every month you get paid the revenue you generated two months before. For instance, on July you get a transfer of the revenue you generated during May. As simple as that.

Mobclix

We started generated revenue on March 2010 and by now, end of August 2010, we have not seen a single dollar[1]. Ouch. That’s not a good business, is it?

This deserves a post on its own: Can’t get our money out of Mobclix.

[1] Update on August 24: We did get paid today.

Share
 

Admob vs Mobclix: 2nd round

June 9, 2010 at 10:55 pm | android, blog, monetizing | 23 comments

 

This is the second part of a series of posts, look at the 1st round, 3rd round, and some related problems.

It’s been three months since we migrated to Mobclix from Admob, where we stayed for over two months. So we want to share some data, mainly focused to get our fellow developers starting out in the Android world to better estimate what kind of revenue they can make out of advertising.

We will compare the results for four weeks, aligned by the week day, using the data from February/March for Admob, and April/May for Mobclix.

This is the revenue that we generated per day (*):

dyerware.com


And here, the revenue per click, which is our preferred indicator to compare how different ad providers perform:

dyerware.com


All this has been generated by three applications, that currently have 100k active users (after over 200k downloads). It is difficult to keep track of how many users we had in each ad provider at every point in time, so comparing absolute numbers, like we did in the first graph, does not yield relevant conclusions.

In an upcoming article, we’ll show values that analyze the long term figures!

(*): We have multiplied all figures by a factor k € [0.2, 5.0], in order not to disclose our real numbers while providing meaningful data. This correction is consistent, i.e. if you have 2x active users, expect a similar price per click but double the revenue per day.

Share
 

« Older Entries       

Categories:

Recent posts:

Search:

Subscribe