Friday, January 25, 2013

AIR Android Native Extensions: Part 6: Preventing Android activity from being recreated on orientation change and relaunch.

In my previous post, I explained how to package XHDPI and XLarge resources with the AIR app. In this post, I would cover how to prevent Android activities from being recreated on orientation change or resumption of app.

In the process, we'd see how to compile an AIR android app with a different Android SDK.

First, let's understand what the issue is. There are a lot of times, where you need to create native android activities. For example, if you want to use the Android WebView component to launch the web pages in your app, you'd need to create a new activity for the same.

By default, Android recreates the activity on various configuration changes, such as SoftKeyBoard open or Orientation change. To prevent the recreation of activity, we used to add the android:configChanges property to activity's declaration in the manifest:

<activity android:name="com.webview.Webview"
android:configChanges="keyboardHidden|orientation" >
</activity>

As you can notice above, we have added an attribute android:configChanges and the values for it are keyboardHidden|orientation. This much was sufficient to prevent the activity from getting recreated in Android below 3.2. However, these values alone are unable to prevent the activity from being killed in Android 3.2 and above.

Problem: Android introduced a new configuration property "screenSize" in Android 3.2, hence you need to add this as well as in the android:configChanges attribute like this:

<activity android:name="com.webview.Webview"
android:configChanges="keyboardHidden|orientation|screenSize" >
</activity>

This would tell Android to not recreate the activity on screenSize changes. However, you won't be able to use this property with the default android SDK AIR uses as it would not recognize this property and throw an error.

Solution: Updating Android SDK. No, the platformsdk compiler argument, as explained in my previous post, would not help here.

So, we'd need to replace the Android SDK in the AIR SDK's library folder. The old Android SDK JAR is at the following location:
{AIR_SDK_FOLDER}\lib\android\lib\resources\android-res.jar


You'd need to copy the JAR file from the android SDK folder, rename it as "android-res.jar" and paste it at the location above, replacing the old one. The Android SDK JAR, for say, Android 4.0, would be present at "platforms/android-15/android.jar". You can download the SDK for a particular version from the android website.

Once the above is done, you'd be able to successfully package the application with screenSize attribute added to the activity declaration.

Unfortunately, even after doing this, the Android activity may get recreated on resume on certain devices. Fortunately, adding a few lines to your manifest can fix this, see below:

<android>
<colorDepth>16bit</colorDepth>
<manifestAdditions><![CDATA[
<manifest android:installLocation="auto">
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.DISABLE_KEYGUARD"/>
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="15" />
<application android:enabled="true">
<activity android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity> </application>
</manifest>
]]>
</manifestAdditions>
</android>

As you'd notice above, I've added an activity node under the application node and assigned it a property android:launchMode="singleTop". This is what does the trick. The main thing is the launchMode, that we have set to singleTop. But, to set that we'd need to add the lines emboldened as well.

Well, this would ensure that your activity would never recreate unless you want it to. Hope this helps someone banging head against the wall, trying to figure out what to do. Like what I was doing sometime back, till I figured this out.

Do keep watching this space for my last article in this series: Launching AIR's main activity from other Android activities and passing information.

No comments:

Post a Comment