Best android questions in December 2011

How do I verify Android in-app-billing transactions on MY server?

13 votes

I have made an Android app where items can be purchased using in-app-billing. When an item is purchased the transaction can easily be synced between Android Market and the phone - to be used in the app. But, I need MY server to be aware of the purchase. The decision to deliver app-specific data should be made on my server, not in the client app.

E.g.

  1. User buys item X from Android Market.
  2. Transaction data Y is sent to the client.
  3. Client sends Y to my server.
  4. Client asks the server to deliver content for X.
  5. Server delivers content if Y is valid. How can this be accomplished?

Q: How do I verify that transaction data coming from the Android client (presumably originating from Google servers) is not fake? I.e. a hacker didn't generate the data.

Google Server -> Android client -> My server -> Android client

Perhaps this is more of a PHP question than anything else. Exactly what should my server script (PHP) do in order to verify that the retrieved data is real?

Use openssl_verify ($data, $signature, $key)

The variables $data and $signature should be sent from the android client to your php server using https. The transaction contains both of these items. Send that to your servers before you acknowledge the transaction on the client.(see documentation here - http://developer.android.com/guide/market/billing/billing_integrate.html)

The variable $key is your google public key available from your publisher account from the Licensing & In-app Billing panel. Copy the public key and use that in your php code, preferably using a config file you install on your servers rather than in your actual php code.

If the openssl_verify call succeeds you should store the order numbers on your servers and ensure they are unique so they cannot be replayed. Be aware that a single data receipt and signature pair could contain many order numbers though its usually one order.

Catching exceptions thrown from native code running on Android

13 votes

The project I'm currently working on requires me to code up the android portion of a cross platform program implementation.

A core set of functionality is built and included in my app through android-ndk. I've found that any exception/crash which happens in the native code is only reported now and again at best. When an error occurs I get one of the following behaviours:

  • A stacktrace / memory dump occurs and is written to the log file. The program disappears (no indication is given on the device as to why suddenly the app is no longer there).
  • No stacktrace / dump or other indication is given that the native code has crashed. The program disappears.
  • The java code crashes with a NullPointerException (usually in the same place per native code exception which is a massive pain). Usually causing me to spend quite a while trying to debug why the Java code has thrown an error only to discover the Java code is fine & the native code error has been entirely masked.

I can't seem to find any way to "insulate" my code against errors which occur in native code. Try/catch statements are resoundingly ignored. Apart from when my code is fingered as the culprit I don't even get a chance to warn the user than an error has occurred.

Can someone please help me out as to how to respond to the situation of crashing native code?

I used to have the same problem, it is true that in android (inside any VM in general when executing native code) if you throw a C++ exception an this one is not cached the VM dies (If I clearly understood I think it is your problem). The solution I adopted was to catch any exception in C++ and throw a java exception instead using JNI. The next code it is a simplified example of my solution. First of all you have a JNI method that catches a C++ exception and then in the try clause the Java exception is annotated.

JNIEXPORT void JNICALL Java_com_MyClass_foo (JNIEnv *env, jobject o,jstring param)
{
    try
    {
        // Your Stuff
        ...
    }
    // You can catch std::exception for more generic error handling
    catch (MyCxxException e)
    {
        throwJavaException (env, e.what());
    }
}


void throwJavaException(JNIEnv *env, const char *msg)
{
    // You can put your own exception here
    jclass c = env->FindClass("java/lang/RuntimeException");

    if (NULL == c)
    {
        //B plan: null pointer ...
        c = env->FindClass("java/lang/NullPointerException");
    }

    env->ThrowNew(c, msg);
}

Note that after a ThrowNew, the native method does not abruptly terminate automatically. That is, control flow returns to your native method, and the new exception is pending at this point. The exception will be thrown after your JNI method is finished.

I hope it was the solution you are looking for.

How to start a Service when .apk is Installed for the first time

11 votes

In my Application I am not having any UI part, so I need to start a Service as soon as the Applicaton gets installed on the Device. I saw many links from which the answer was that its not possible but I guess it is surely possible. Just have a look at PlanB Application on the Android Market that does fulfil my requirement. Below is my Manifest file how I tried, but the Service was not called at all. So, let me know what is the best possible way to start a Service when the Application gets Installed.

UPDATE

I also tried using android.intent.action.PACKAGE_ADDED it works fine for detecting the Package for the other Applications but not for itself.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.auto.start"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="8" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

    <application
        android:icon="@drawable/ic_launcher" >

        <service android:name=".MyService">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </service>

        <receiver android:name=".BootUpReceiver">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <action android:name="android.intent.action.PACKAGE_INSTALL" />
                <action android:name="android.intent.action.PACKAGE_ADDED" />
                <data android:scheme="package"/>
            </intent-filter>
        </receiver>
    </application>
</manifest>

Fortunately, Plan B does not work on Android 3.1+, as tested on a XOOM and a Galaxy Nexus.

What Plan B does is exploit a security hole that could be used by drive-by malware, which is specifically why Android prevents it from happening anymore.


UPDATE

To clarify: As inazaruk posted and I put into comments on other answers, all applications, upon installation, are placed in a "stopped" state. This is the same state that the application winds up in after the user force-stops the app from the Settings application. While in this "stopped" state, the application will not run for any reason, except by a manual launch of an activity. Notably, no BroadcastReceviers will be invoked, regardless of the event for which they have registered, until the user runs the app manually.

This block covers the Plan B scenario of remote-install-and-run, which they were taking advantage of previously. After all, with that, anyone with a hacked Google account would be at risk of having their device infected, hands-free as it were.

So, when the OP says:

I need to start a Service as soon as the Applicaton gets installed on the Device

the OP will be unsuccessful and will need to redesign the application to avoid this purported "need".

No key.store and key.alias properties found in build.properties

11 votes

I am using ant-release to do a 1-step build of my Android app.

My build.properties looks like this:

application.package=xxxxx
key.store=sonr
key.alias=sonr labs
key.store.password=xxxx
key.alias.password=xxxx

When I run ant-release everything is fine except for application signing. I get the error:

-release-prompt-for-password:

-release-nosign:
     [echo] No key.store and key.alias properties found in build.properties.
     [echo] Please sign /Users/syalam/Documents/git/joeborn-sonr/sonr/bin/SONR-release-unsigned.apk manually
     [echo] and run zipalign from the Android SDK tools.
[propertyfile] Updating property file: /Users/syalam/Documents/git/joeborn-sonr/sonr/bin/build.prop
[propertyfile] Updating property file: /Users/syalam/Documents/git/joeborn-sonr/sonr/bin/build.prop
[propertyfile] Updating property file: /Users/syalam/Documents/git/joeborn-sonr/sonr/bin/build.prop
[propertyfile] Updating property file: /Users/syalam/Documents/git/joeborn-sonr/sonr/bin/build.prop

How can I resolve this?

PS. I followed this tutorial for getting my build process down http://www.androidengineer.com/2010/06/using-ant-to-automate-building-android.html

I had this problem too recently, I think that that tutorial is out of date...

The key.alias etc directives need to be in a file named ant.properties. There's no file called build.properties any more.

Java Dates - What's the correct class to use?

10 votes

So the whole Java Date/Calendar/GregorianCalendar thing is obviously a joke. What's the right Date class to use?

Edit: Building an SDK for third parties on Android where the application needs to provide a date

More Edit: Things that make this so obviously a joke:

  • 99% of Date is deprecated
  • Date's Year is offset from 1900
  • Date's Month is zero-indexed while day is one-indexed
  • Dates are mutable
  • You're supposed to use a Calendar to create a date...
  • ... except you really have to use a GregorianCalendar
    • Do a significant percent of developers want to use a different calendar?
  • Calendar.getTime() returns a Date
  • There's no Date math (like how far apart are two dates in years)
    • Messing with milliseconds since epoch doesn't count
  • You can't chain parts together to get an expression (like the date one year ago today)
  • Probably more stuff

Joda-Time. Even on Android.

If you want to stick to JSE classes, it depends on what you're trying to do.

Edit: You keep changing your question. Date and Calendar.

What is the better way to get Context?

9 votes

According to this answer or the android's documentation there is several ways to get the Context in an app and pass it to an other class/method/whateveruneed.

Let's say i'm in the Foo Activity and in need to pass the context to Bar's constructor.

Bar bar  = new Bar(Foo.this);
Bar bar2 = new Bar(this); //same as first i guess
Bar bar3 = new Bar(getApplicationContext());
Bar bar4 = new Bar(getBaseContext());
Bar bar5 = new Bar(MyApp.getContext); // get context statically 

Taking into account of memory leaks, speed , general performance , what will be the better way between all those possibilities ? (A detailed answer would be apreciated)

Thanks

You should check out this question - which basicly covers the same as yours.

Also the Developer Docs on Avoiding memory leaks gives you a decent explanation of some situtations in which various of the methods are reasonable to use.

Does Android plan to support Java7?

9 votes

As Android does not currently support java7, I find myself wondering if they have made an official comment if they are working on supporting it?

Cheers,

I was under the impresssion that android didn't use oracle java, it uses a subset of apaches harmony java: http://en.wikipedia.org/wiki/Apache_Harmony#Use_in_Android_SDK

http://arstechnica.com/open-source/news/2010/11/apache-foundation-to-vote-down-java-7-protesting-oracle-abuses.ars

Why does the Command prompt screen open 2-3 times before Android emulator starts?

9 votes

When the Android emulator is launched in Windows XP/Windows 7), the command prompt opens 2-3 times. So why does that open?

Anyone know of a reason for this?

when you launches the emulator, by default it executes batch file for launching the emulator file. so because of running of these batch files , you can see the command prompt opened & closed.

Make the plus sign a string in java

9 votes

So I want the plus sign to be stored as a string and displayed to the screen later; so in this case I have

 String plusSign = "+";

but when I display the above on screen, I get a weird plus sign that has a circle around it. I am using the variable in an app that I'm making so using android may have something to do with the strange format. Is this how the plus sign is supposed to look or is there a way to make it look like a normal plus(a cross with no circle)?

Let me add some alternatives I've tried. The first thing I did was see if the unicode version of the plus sign would look any different but nothing appeared when I displayed it(the code was \u002B). I, also, looked at the ascii version but I wasn't sure how to convert it to a string.

Here is the code I use to display the string onScreen

 Addition = new Text(PositionX, PositionY, standardFont, "Intergers" + plusSign + "Integers");
 mScene.attachChild(Addition); 

I use andEngine, so here is the Text class http://code.google.com/p/andengine/source/browse/src/org/anddev/andengine/entity/text/Text.java

It looks like it is related to android: http://www.droidforums.net/forum/droid-x-faq/65474-what-those-icons.html

So it seems like if you use a font that does not support a certain character, it defaults to what ever android uses.

It looks to me like the most likely culprit is the font you are using. I would double check that the plus symbol doesn't have a circle in that font. There is another symbol, the "xor" symbol ("\u2295") that is a plus with a circle around it. I can't think of a reason why the plus symbol would be replaced with this symbol, but you might try displaying this character specifically to see if it looks like what you are seeing in the font you are using.

App file size differences in Android and iOS

8 votes

Working with both app distributions services (android market and Apple App store) I have discovered a mystery.

The file size of an app is in general larger for an Apple app than for a Android app. I can't seem to find any explanation for the differences, and it seems to be an untouched subject.

I have tried allot of different apps and the difference seems to vary between a couple of MB to 6-8 MB. So the question is, how come the file size is larger for Apple apps? What is the extra MB used for?

Examples:

BBC:

Android: 918K - https://market.android.com/details?id=bbc.mobile.news.ww

Apple: 6.7 MB - http://itunes.apple.com/dk/app/bbc-news/id364147881?mt=8

Due to some spam prevention, I'm unable to link directly to the rest.

British Airways

Android: 1.2 MB

Apple: 7.9 MB

Northern Bank

Android: 2.1 MB

Apple: 6.4 MB

Bank of America

Android: 727K

Apple: 2.1 MB

I could go on... If anyone can provide a statistics of file size for the two app distributions, confirming or disproving my theory. - I would appreciate it allot.

The binary executable in an iOS app is encrypted, and thus compresses very poorly or not at all. The binary executable in an iOS app is compiled with some library code statically linked, which can often make it larger than interpreted Dalvik byte code for similar stuff. iPhone apps tend to contain more high quality graphics content and artwork for multiple screen resolutions including the relatively large iPad display.

Android: Accessing images from assets/drawable folders

8 votes

The app I am currently working on has hundreds of images. At the moment I store them in the 'Drawable' folder. I was thinking about moving all of them to Assets folder.

My question is: Is there any difference in performance when using both approaches?

I don't think so there is bit difference in performance of using these two folders, I think using drawable folder you can get easily images (All will be indexed in the R file, which makes it much faster (and much easier!) to load them.), and If you want to use it from asset then you have to use AssetManager then using AssetFileDescriptor you have to get those images.

  • Assets can also be organized into a folder hierarchy, which is not supported by resources. It's a different way of managing data. Although resources cover most of the cases, assets have their occasional use.

  • In the res/drawable directory each file is given a pre-compiled ID which can be accessed easily through R.id.[res id]. This is useful to quickly and easily access images, sounds, icons...

AutoStart Application not working properly

8 votes

I am having a Simple AutoStart Application with TimerTask implementation, that works fine in almost many devices. The problem is that it is not working in Samsung Galaxy Y(2.3.6) and DELL XCD35(2.2). When the device boots TimerTask works for some seconds and then shuts down. I check in the Application->Manage Application, I saw that the Applcation was already in Force Stop State. That means some how my Application gets stopped after some seconds. So, what is the reason for this weird behaviour in these two devices, if anyone has the solution do share it.

Below is my code.

MyReceiver.java

public class MyReceiver extends BroadcastReceiver{

    private Timer mTimer = new Timer();
    @Override
    public void onReceive(Context context, Intent arg1) {
        Toast.makeText(context, "Device Booted", Toast.LENGTH_LONG).show();
        Log.d("TAG","Device Booted");
        mTimer.scheduleAtFixedRate(new MyTimerTask(), 2000,2000);
    }

    private class MyTimerTask extends TimerTask
    {
        @Override
        public void run() {
            Log.d("TAG","TimerTask executed....");
        }
    }
}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.autostart.app"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="8" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <receiver android:name=".MyReceiver">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
            </intent-filter>
        </receiver>
    </application>
</manifest>

I think in some of the Android OS sometimes the OS kills the threads that are running while the Devices Boots which Android is not familiar with or doesn't recognize it. This is the reason why the TimerTask is working in some Devices and in some Devices just works for a 5-10 seconds and then the Application is ForceStopped automatically by the Android OS on Device Boot(Note - Its Force Stop from Manage Application and not Force close so I am not getting any error in the Logcat).

So in that case the solution is to use the inbuilt Mechanism which Android OS recognizes and doesn't kill it and keeps it in a running mode. In this case I managed using AlarmManager to perform my task and it works.

I might not be right but my final solution was to use AlarmManager to make my Application working in every Device.

@Override
    public void onReceive(Context context, Intent arg1) {

        Log.v("Device Booted", "************ DEVICE BOOTED ******************");
        Intent myIntent = new Intent(context, AlarmService.class);
        PendingIntent pendingIntent = PendingIntent.getService(context, 0, myIntent, 0);
        AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 2000, 2000, pendingIntent);
    }