Saturday, May 26, 2012

Trust us! Why? Because we say so.

This is going to be follow up on a post I did a month ago because I found something interesting.

In a forum focused on pirated app releases I found a thread that linked to my previous blog post. I originally planned to post an answer in that thread but the thread was locked for some unknown reason.

Here's the 3 first posts of the thread:


My comments to the first post is that I never said that there is a trojan in it. I said it has been modified with added code and resigned. (I've even tried to "disassemble" the app but even the latest apktool fails decoding the added code.)

My comments on the second post is that it was not the demo version made pro. I've examined the untouched files and it's the pro version, no doubt about it. Someone told me these kind of guys uses "cracking" tools and it is of course very possible that this is people just using premade cracking tools to "crack" apps, not even knowing what these tools adds to the apps. I've tried to find out but the added code cannot be reverse engineered with the tools I've tried.

I also want comment the phrase "Nice try from the developer". The reason I started to google for my app in the first place was because sales suddenly doubled overnight and it stayed higher than normal for 4-5 days after the "cracked" version appeared on the net. It has happend once again just a week or two ago and the same thing happened then and I can still see the positive effects in my sales numbers. I wouldn't even have made the post if it had not been for the fact that the app was modified and resigned and I wanted to make people aware of the risks.

I can only speculate on why the sales increases when this happens but these pirate app releases replicates on a lot of sites, blogs and forums quickly and they even seem to run it through Google translate making it available in several languages. They "spread the word" and I suppose a lot of people actually uses their brains.

My last comment is about the line "You can trust Market Militia and red-colored users. Promised." And the answer to that "OK thanks I was a little bit worried". I'm not saying these guys are all bad and totally untrustworthy people but I wouldn't take an anonymous persons word for it, especially when the reasons he/she put forward for the modifications and resigning are false.

No wonder people get scammed on the net.

Saturday, May 19, 2012

The useful uses-feature tag

I've got a handful of mails from people who could not install my app External Keyboard Helper and in all cases it has been devices that lacks bluetooth hardware. The reason why Google Play flags the app as incompatible for them is that my manifest has this line it:

    <uses-permission android:name="android.permission.BLUETOOTH" />

This makes Google Play decide that my app only works on devices that supports bluetooth and I've believed the only way around this would be to create another app with the above line removed from the manifest.

Yesterday I realized this is not needed when I learned about the <uses-feature> tag. It turns out that Google Play translates the permissions your app request in to features required like this table describes. So my <uses-permission> tag above makes my app require the android.hardware.bluetooth feature.

With my app bluetooth hardware is not needed, but my app needs that permission on some Android versions in order to detect when a bluetooth keyboard is connected or disconnected. So what I needed to do is to add a line to my manifest to make this feature requirement optional.

    <uses-feature android:name="android.hardware.bluetooth" android:required="false" />

This tag can also be used to add a requirement by setting the required flag to true.

When publishing the new version to market, the number of available devices went from 1265 to 1288 and I've already got it confirmed from a user of the app that it can now be installed on a non-bluetooth-capable device.

In my case this was all that was needed but depending on how your app uses the optional features you specify you probably have to use the hasSystemFeature call to check if the feature is present or not.

Friday, May 4, 2012

How to write cross-API apps

If you are developing an Android application you probably want to make it available to as many devices as possible. However doing that forces you to target your app for an old api-level, sacrificing all the new stuff that has been since that api-level.

So you want to write an app that works even for Android 1.6 to so you target it for api-level 4. Then you start realizing that there are a handful of nice stuff, that while not being crucial for the application, still would be nice to be able to use.

But wait, what if you target your app for a newer api...


...and set minSDK to a lower api in your manifest?

    <uses-sdk android:minSdkVersion="4" />

Then you could add checks to make sure you only use the new stuff where it is supported...

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
    preference.setIcon(icon);

Well, that is what I thought would be enough but it turned out it would force close before it even reached that part of the code. In fact it crashes when it loads your class. After some searching on the net I found a solution that take advantage of something called "Lazy loading".

What it means is that if you put the high-api specific code in a separate class it will not be loaded unless that part of the code is reached and it will no longer force close on low-api devices.

So we change the example above to:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
    LazySetIcon.seticon(preference, icon);

Then we create the class LazySetIcon.java which looks like this:

package com.example.app;

import android.preference.Preference;

public class LazySetIcon { 
    public static void seticon(Preference preference, int icon) {
        preference.setIcon(icon);
    }
}

And that's it. Write an app for a low-api devices but use high-api goodies on newer devices, when possible. A little bit more work but if the high-api code you use is limited to simple things like setting a preference icon like in the example above then it will probably be worth it.