Titanium JIRA Archive
Alloy (ALOY)

[ALOY-894] Android proxies throwing ClassCastException on non string attributes

GitHub Issuen/a
TypeBug
Priorityn/a
StatusClosed
ResolutionWon't Fix
Resolution Date2014-01-16T19:04:05.000+0000
Affected Version/sn/a
Fix Version/sn/a
ComponentsXML
Labelsn/a
ReporterMauro Parra-Miranda
AssigneeTony Lukasavage
Created2013-11-21T22:49:52.000+0000
Updated2014-01-16T19:04:10.000+0000

Description

When passing custom arguments using the tag on an alloy controller main.xml inputText.xml inputText.js var args = arguments[0] || {}; $.textField.enableReturnKey = args.enableReturnKey; On iOS, it works. On Android, the app crashes with a ClassCastException because the string "true" is not boolean true. java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Boolean E/AndroidRuntime( 3277): at ti.modules.titanium.ui.widget.TiUIText.onEditorAction(TiUIText.java:373) E/AndroidRuntime( 3277): at android.widget.TextView.onEditorAction(TextView.java:4594) E/AndroidRuntime( 3277): at com.android.internal.widget.EditableInputConnection.performEditorAction(EditableInputConnection.java:138) E/AndroidRuntime( 3277): at com.android.internal.view.IInputConnectionWrapper.executeMessage(IInputConnectionWrapper.java:297) E/AndroidRuntime( 3277): at com.android.internal.view.IInputConnectionWrapper$MyHandler.handleMessage(IInputConnectionWrapper.java:77) E/AndroidRuntime( 3277): at android.os.Handler.dispatchMessage(Handler.java:99) E/AndroidRuntime( 3277): at android.os.Looper.loop(Looper.java:175) E/AndroidRuntime( 3277): at android.app.ActivityThread.main(ActivityThread.java:5279) E/AndroidRuntime( 3277): at java.lang.reflect.Method.invokeNative(Native Method) E/AndroidRuntime( 3277): at java.lang.reflect.Method.invoke(Method.java:511) E/AndroidRuntime( 3277): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102) E/AndroidRuntime( 3277): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869) E/AndroidRuntime( 3277): at dalvik.system.NativeStart.main(Native Method) The line being here: https://github.com/appcelerator/titanium_mobile/blob/master/android/modules/ui/src/java/ti/modules/titanium/ui/widget/TiUIText.java Boolean enableReturnKey = (Boolean) proxy.getProperty(TiC.PROPERTY_ENABLE_RETURN_KEY); This works fine if the attribute is set directly in the destination controller. inputText.xml Alloy is likely doing some lookahead on the proxy to change the xml string "true" to the object true. But this cannot be done when passing an argument through the tag. The workaround is: var args = arguments[0] || {}; $.textField.enableReturnKey = toBoolean(args.enableReturnKey); function toBoolean(str) { if (!str) { return false; } if (str == "true") { return true; } else if (str == "false") { return false; } return str; } But, this is not very elegant. The iOS proxies likely do some graceful type conversions when looking for booleans, but the Android ones do not. Unfortunately the fix is very difficult. Modify all Android proxies that want non string values, to pass through a utility that checks the type and converts to Boolean instead of a blind cast. Or, developers should understand that they are setting a string value on a boolean attribute in their controllers. I would just accept that and fix my code, but the fact that it works in iOS and not in Android is why this may be considered a bug.

Comments

  1. Todd Lindner 2013-12-07

    When trying bleeding edge SDK builds (3.2.x or 3.3.x) I am also seeing additional ClassCastExceptions. This time on a normal . Perhaps a related bug in alloy, not converting Strings to Boolean. java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Boolean at org.appcelerator.titanium.view.TiUIView.registerForTouch(TiUIView.java:1457)
  2. Tony Lukasavage 2013-12-07

    This is more developer error than it is Alloy or Android's fault. By nature, XML handles only strings in attributes. If a developer needs to use a value other than a string, they should be using TSS, which they should be using in the first place regardless. There are hacks I can put in Alloy to do type conversion based on attribute name, but they would be "improvements", not "bug fixes" as the expectation should be that any value specified in an XML attribute should be a string. I can start to assess some of these attributes and have Alloy do the conversion, but honestly, you should be using TSS to assign properties to your UI components and avoid this entirely.
  3. Todd Lindner 2013-12-10

    I agree, its poor development practice. Just thought it might be a parity issue since it works on iOS but not Android. I just assumed some type juggling happens in the proxies (beyond Alloy) on iOS, but obviously not in Android as direct Java casting is used.
  4. Tim Poulsen 2014-01-16

    This is probably a platform issue, not Alloy. Even in classic code, assigning a non-string value to a TextField/TextArea on Android will throw the class cast exception. iOS seems to cast values automatically.
  5. Tim Poulsen 2014-01-16

    I've opened TIMOB-16207 demonstrating that this behavior is present in classic projects. Recommend closing this ticket.
  6. Tim Poulsen 2014-01-16

    Because the cause is the underlying platform handling of data type casting, we're not going to add a workaround in Alloy. See the related TIMOB ticket opened to cover the platform issue.

JSON Source