The issue
It is not possible to call *setDisplayHomeAsUp* on the activity of a window with the *navBarHidden* property set to *true*. Otherwise, we get this error :
05-21 15:36:54.035: E/TiApplication(21464): (main) [163,163] Sending event: exception on thread: main msg:java.lang.NullPointerException; Titanium 3.1.0,2013/04/15 18:46,57634ef
05-21 15:36:54.035: E/TiApplication(21464): java.lang.NullPointerException
05-21 15:36:54.035: E/TiApplication(21464): at org.appcelerator.titanium.proxy.ActionBarProxy.handlesetDisplayHomeAsUp(ActionBarProxy.java:178)
05-21 15:36:54.035: E/TiApplication(21464): at org.appcelerator.titanium.proxy.ActionBarProxy.handleMessage(ActionBarProxy.java:201)
05-21 15:36:54.035: E/TiApplication(21464): at android.os.Handler.dispatchMessage(Handler.java:95)
05-21 15:36:54.035: E/TiApplication(21464): at android.os.Looper.loop(Looper.java:137)
05-21 15:36:54.035: E/TiApplication(21464): at android.app.ActivityThread.main(ActivityThread.java:4507)
05-21 15:36:54.035: E/TiApplication(21464): at java.lang.reflect.Method.invokeNative(Native Method)
05-21 15:36:54.035: E/TiApplication(21464): at java.lang.reflect.Method.invoke(Method.java:511)
05-21 15:36:54.035: E/TiApplication(21464): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:790)
05-21 15:36:54.035: E/TiApplication(21464): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:557)
05-21 15:36:54.035: E/TiApplication(21464): at dalvik.system.NativeStart.main(Native Method)
05-21 15:36:54.045: E/AndroidRuntime(21464): FATAL EXCEPTION: main
Code to reproduce
app.js :
function openNewWindow() {
var newWin = Ti.UI.createWindow({navBarHidden: true, backgroundColor: '#0F0'});
newWin.addEventListener("open", function() {
var newActionBar = this.activity.actionBar;
if (newActionBar) {
newActionBar.setDisplayHomeAsUp(true);
}
});
newWin.open();
}
(function() {
var win = Ti.UI.createWindow({backgroundColor: '#F00'});
win.addEventListener("open", openNewWindow);
win.open();
})();
tiapp.xml :
<?xml version="1.0" encoding="UTF-8"?>
<ti:app xmlns:ti="http://ti.appcelerator.org">
<id>com.tab.test</id>
<name>TabTest</name>
<version>1.0</version>
<publisher>johndoe</publisher>
<url>http://</url>
<description>not specified</description>
<copyright>not specified</copyright>
<icon>appicon.png</icon>
<persistent-wifi>false</persistent-wifi>
<prerendered-icon>false</prerendered-icon>
<statusbar-style>default</statusbar-style>
<statusbar-hidden>false</statusbar-hidden>
<fullscreen>false</fullscreen>
<navbar-hidden>false</navbar-hidden>
<analytics>false</analytics>
<guid>e96a483e-41b2-4212-b78a-910612e01548</guid>
<property name="ti.ui.defaultunit" type="string">system</property>
<iphone>
<orientations device="iphone">
<orientation>Ti.UI.PORTRAIT</orientation>
</orientations>
<orientations device="ipad">
<orientation>Ti.UI.PORTRAIT</orientation>
<orientation>Ti.UI.UPSIDE_PORTRAIT</orientation>
<orientation>Ti.UI.LANDSCAPE_LEFT</orientation>
<orientation>Ti.UI.LANDSCAPE_RIGHT</orientation>
</orientations>
</iphone>
<android xmlns:android="http://schemas.android.com/apk/res/android">
<tool-api-level>17</tool-api-level>
<manifest>
<uses-sdk android:minSdkVersion="8"/>
<!-- TI_MANIFEST -->
<application android:debuggable="false"
android:icon="@drawable/appicon" android:label="TabTest"
android:name="TabtestApplication" android:theme="@android:style/Theme.Holo.Light">
<!-- TI_APPLICATION -->
<activity
android:configChanges="keyboardHidden|orientation"
android:label="TabTest" android:name=".TabtestActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:configChanges="keyboardHidden|orientation" android:name="org.appcelerator.titanium.TiActivity"/>
<activity
android:configChanges="keyboardHidden|orientation"
android:name="org.appcelerator.titanium.TiTranslucentActivity" android:theme="@android:style/Theme.Translucent"/>
<activity
android:configChanges="keyboardHidden|orientation"
android:name="org.appcelerator.titanium.TiModalActivity" android:theme="@android:style/Theme.Translucent"/>
<activity
android:configChanges="keyboardHidden|orientation" android:name="ti.modules.titanium.ui.TiTabActivity"/>
</application>
</manifest>
</android>
<modules/>
<deployment-targets>
<target device="blackberry">false</target>
<target device="android">true</target>
<target device="ipad">false</target>
<target device="iphone">false</target>
<target device="mobileweb">false</target>
</deployment-targets>
<sdk-version>3.1.0.GA</sdk-version>
</ti:app>
If we set navBarHidden to false, the app will work :
var newWin = Ti.UI.createWindow({navBarHidden: false, backgroundColor: '#0F0'});
instead of
var newWin = Ti.UI.createWindow({navBarHidden: true, backgroundColor: '#0F0'});
Devices used
This problem is only reproducible on devices using *Holo*.
I have tested on these devices :
- Samsung S2 (GT-I9100P), android 4.0.3 -> *crash* (supports Holo)
- Nexus S, android 4.1.2 -> *crash* (supports Holo)
- Samsung S3 (GT-I93000), android 4.1.2 -> *crash* (supports Holo)
- HTC Desire HD A9191, android 2.2 -> *ok* (does not supports Holo)
- Samsung GT-S5830, android 2.3.3 -> *ok* (does not support Holo)
- HTC Wildfire A3333, android 2.2.1 -> *ok* (does not support Holo)
Trying to set displayHomeAsUp will trigger the crash when the ActionBarProxy tries to access the underlying Activity's ActionBar. Checking for existence (like in the fix for TIMOB-14215) would fix this. https://github.com/appcelerator/titanium_mobile/blob/3_2_X/android/titanium/src/java/org/appcelerator/titanium/proxy/ActionBarProxy.java#L323 Reading further along in the code though, it appears like the same issue can be triggered by trying to add an event listener/setOnHomeIconItemSelected-callback to the home button as well, if the onPropertyChanged()-method gets called directly on the main thread. https://github.com/appcelerator/titanium_mobile/blob/3_2_X/android/titanium/src/java/org/appcelerator/titanium/proxy/ActionBarProxy.java#L337
FYI