java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Boolean

Appcelerator JIRA | Mauro Parra-Miranda | 3 years ago
  1. 0

    When passing custom arguments using the <require> tag on an alloy controller main.xml <Require src="inputText" enableReturnKey="true" /> inputText.xml <Alloy> <View> <TextField id="textField" /> </View> </Alloy> 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> <View> <TextField id="textField" enableReturnKey="true" /> </View> </Alloy> 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 <Require> 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.

    Appcelerator JIRA | 3 years ago | Mauro Parra-Miranda
    java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Boolean
  2. 0

    When passing custom arguments using the <require> tag on an alloy controller main.xml <Require src="inputText" enableReturnKey="true" /> inputText.xml <Alloy> <View> <TextField id="textField" /> </View> </Alloy> 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> <View> <TextField id="textField" enableReturnKey="true" /> </View> </Alloy> 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 <Require> 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.

    Appcelerator JIRA | 3 years ago | Mauro Parra-Miranda
    java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Boolean
  3. 0

    Originally reported as an Alloy issue, this is a platform issue. Setting a property to a string that expects a boolean will work on iOS but throw an exception on Android. Test case: returnKeyEnabled expects boolean, drop the following into a new classic project, build for Android, tap the text field then with or without entering text in the field, tap the Done (return) button to cause the crash. App works as-is on iOS (7.0 simulator) {code} var win = Titanium.UI.createWindow({ backgroundColor:'#fff', layout: 'vertical' }); var txt = Ti.UI.createTextField({ top: 50, width: Ti.UI.FILL, color: 'black', borderStyle: Ti.UI.INPUT_BORDERSTYLE_ROUNDED, enableReturnKey: 'true' // change to true to "fix" }); win.add(txt); win.open(); {code} {code} [ERROR] TiApplication: (main) [12383,12383] Sending event: exception on thread: main msg:java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Boolean; Titanium 3.2.0,2013/12/20 10:57,d9182d6 [ERROR] TiApplication: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Boolean [ERROR] TiApplication: at ti.modules.titanium.ui.widget.TiUIText.onEditorAction(TiUIText.java:389) [ERROR] TiApplication: at android.widget.TextView.onEditorAction(TextView.java:4117) [ERROR] TiApplication: at com.android.internal.widget.EditableInputConnection.performEditorAction(EditableInputConnection.java:138) [ERROR] TiApplication: at com.android.internal.view.IInputConnectionWrapper.executeMessage(IInputConnectionWrapper.java:297) [ERROR] TiApplication: at com.android.internal.view.IInputConnectionWrapper$MyHandler.handleMessage(IInputConnectionWrapper.java:77) [ERROR] TiApplication: at android.os.Handler.dispatchMessage(Handler.java:99) [ERROR] TiApplication: at android.os.Looper.loop(Looper.java:137) [ERROR] TiApplication: at android.app.ActivityThread.main(ActivityThread.java:5041) [ERROR] TiApplication: at java.lang.reflect.Method.invokeNative(Native Method) [ERROR] TiApplication: at java.lang.reflect.Method.invoke(Method.java:511) [ERROR] TiApplication: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793) [ERROR] TiApplication: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560) [ERROR] TiApplication: at dalvik.system.NativeStart.main(Native Method) {code}

    Appcelerator JIRA | 3 years ago | Tim Poulsen
    java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Boolean
  4. Speed up your debug routine!

    Automated exception search integrated into your IDE

  5. 0

    Originally reported as an Alloy issue, this is a platform issue. Setting a property to a string that expects a boolean will work on iOS but throw an exception on Android. Test case: returnKeyEnabled expects boolean, drop the following into a new classic project, build for Android, tap the text field then with or without entering text in the field, tap the Done (return) button to cause the crash. App works as-is on iOS (7.0 simulator) {code} var win = Titanium.UI.createWindow({ backgroundColor:'#fff', layout: 'vertical' }); var txt = Ti.UI.createTextField({ top: 50, width: Ti.UI.FILL, color: 'black', borderStyle: Ti.UI.INPUT_BORDERSTYLE_ROUNDED, enableReturnKey: 'true' // change to true to "fix" }); win.add(txt); win.open(); {code} {code} [ERROR] TiApplication: (main) [12383,12383] Sending event: exception on thread: main msg:java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Boolean; Titanium 3.2.0,2013/12/20 10:57,d9182d6 [ERROR] TiApplication: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Boolean [ERROR] TiApplication: at ti.modules.titanium.ui.widget.TiUIText.onEditorAction(TiUIText.java:389) [ERROR] TiApplication: at android.widget.TextView.onEditorAction(TextView.java:4117) [ERROR] TiApplication: at com.android.internal.widget.EditableInputConnection.performEditorAction(EditableInputConnection.java:138) [ERROR] TiApplication: at com.android.internal.view.IInputConnectionWrapper.executeMessage(IInputConnectionWrapper.java:297) [ERROR] TiApplication: at com.android.internal.view.IInputConnectionWrapper$MyHandler.handleMessage(IInputConnectionWrapper.java:77) [ERROR] TiApplication: at android.os.Handler.dispatchMessage(Handler.java:99) [ERROR] TiApplication: at android.os.Looper.loop(Looper.java:137) [ERROR] TiApplication: at android.app.ActivityThread.main(ActivityThread.java:5041) [ERROR] TiApplication: at java.lang.reflect.Method.invokeNative(Native Method) [ERROR] TiApplication: at java.lang.reflect.Method.invoke(Method.java:511) [ERROR] TiApplication: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793) [ERROR] TiApplication: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560) [ERROR] TiApplication: at dalvik.system.NativeStart.main(Native Method) {code}

    Appcelerator JIRA | 3 years ago | Tim Poulsen
    java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Boolean
  6. 0

    Restore Defaults causes ClassCastException

    Eclipse Bugzilla | 8 years ago | euthanasia_waltz
    java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Boolean

    Not finding the right solution?
    Take a tour to get the most out of Samebug.

    Tired of useless tips?

    Automated exception search integrated into your IDE

    Root Cause Analysis

    1. java.lang.ClassCastException

      java.lang.String cannot be cast to java.lang.Boolean

      at ti.modules.titanium.ui.widget.TiUIText.onEditorAction()
    2. ti.modules.titanium
      TiUIText.onEditorAction
      1. ti.modules.titanium.ui.widget.TiUIText.onEditorAction(TiUIText.java:373)
      1 frame
    3. Android Platform
      TextView.onEditorAction
      1. android.widget.TextView.onEditorAction(TextView.java:4594)
      1 frame
    4. Android
      IInputConnectionWrapper$MyHandler.handleMessage
      1. com.android.internal.widget.EditableInputConnection.performEditorAction(EditableInputConnection.java:138)
      2. com.android.internal.view.IInputConnectionWrapper.executeMessage(IInputConnectionWrapper.java:297)
      3. com.android.internal.view.IInputConnectionWrapper$MyHandler.handleMessage(IInputConnectionWrapper.java:77)
      3 frames
    5. Android Platform
      ActivityThread.main
      1. android.os.Handler.dispatchMessage(Handler.java:99)
      2. android.os.Looper.loop(Looper.java:175)
      3. android.app.ActivityThread.main(ActivityThread.java:5279)
      3 frames
    6. Java RT
      Method.invoke
      1. java.lang.reflect.Method.invokeNative(Native Method)
      2. java.lang.reflect.Method.invoke(Method.java:511)
      2 frames
    7. Android
      ZygoteInit.main
      1. com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)
      2. com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)
      2 frames
    8. Android Platform
      NativeStart.main
      1. dalvik.system.NativeStart.main(Native Method)
      1 frame