Strange JSON error on some Android Devices
Monkey Forums/Monkey Programming/Strange JSON error on some Android Devices
| ||
I've had a few crashes with Chef Solitaire USA TriPeaks on some Android devices. I've been adding debug statements to find out the issue and I can finally see the issue, but unsure why it is happening... The error is this: java.lang.RuntimeException: musicSlider is null cnt=7 debugStr = SIMPLESLIDERS MUSİC at com.therevillsgames.csusatripeaks.bb_std_lang.error(MonkeyGame.java:157) at com.therevillsgames.csusatripeaks.c_OptionsScreen.p_Load(MonkeyGame.java:14582) Here is a cut down version of JSON: { "menu": { "offsetX": -150, "y": 60, "gap": 40, "orientation": 0, "soundMouseOver": "buttonmo", "soundMouseClick": "buttonclick", "buttons": { "button": [ { "name": "Resume", "image": "play", "offsetY": 20, "offsetX": 70, "redText": 255, "blueText": 255, "greenText": 255 }] }, "sliders": { "slider": [ { "name": "Music", "image": "slider", "borderX": 35, "borderY": 20, "x": 100, "y": 250 } ] } } } Notice the slider name is "Music".... And the code to parse it: And when in the game I go thru the Simple Menu objects: When I try to create the slider "Music", I use ToUpper to do the compare... but it changes "Music" to "MUSİC", see the dot over the upper case I - wtf!? And thats why my compare fails and musicSlider is null!! And it only happens on a few devices: * Android 4.2 - Galaxy Tab3 8.0 (lt01wifi) * Android 4.4 - Galaxy Tab3 Lite 7.0 (goyavewifi) * Android 5.0 - Galaxy TabS 8.4 (klimtwifi * Android 4.4 - A1-811 (mango) I've got a Galaxy Tab S 8.4 myself and it works fine... Any ideas? Cheers, Steve |
| ||
Well that was interesting. I set out to find information about dotted uppercase i and learned about the Turkish Locale bug. http://mattryall.net/blog/2009/02/the-infamous-turkish-locale-bug |
| ||
Nice find Floyd! In the Android Developer console you cant tell which language the Android device is running, but sometimes users do post messages with the bug report: app doesnt work and crash at startup = English neden acilmiyo bu oyun = Turkish solitair has stopped = Engish ;) açılmıyor maalesef oyun durdu yazıyor = Turkish oyun acilmiyor = Turkish Now how to fix it within MX....? |
| ||
I've managed to recreate it by setting my device to Turkish :) And I've got a workaround for the String compare... but within Monkey's own Map class it does a string compare and that means altering javatranslator.monkey file which I dont want to do :( Raised a bug issue: http://www.monkey-x.com/Community/posts.php?topic=10614 |
| ||
Well that was fun...not! I had to change all the .ToUpper and .ToLower calls with a custom function: #If TARGET="android" Then Function DiddyToUpper:String(lhs:String) = "diddy.toUpper" Function DiddyToLower:String(lhs:String) = "diddy.toLower" #Else Public Function DiddyToUpper:String(lhs:String) Return lhs.ToUpper() End Function DiddyToLower:String(lhs:String) Return lhs.ToLower() End #End Android: static String toUpper(String lhs) { return lhs.toUpperCase(Locale.ENGLISH); } static String toLower(String lhs) { return lhs.toLowerCase(Locale.ENGLISH); } |
| ||
yeah, what you need is a proper way to handle case folding/string normalization that is specific to your locale (if you're comparing directly to English strings internally) and ignores Turkish folding conventions, which as you've found out is what systems set to that locale will do if utilizing the underlying system's string conversion capabilities. monkey-utf8 handles this by bypassing the system's case folding capabilities entirely -- instead it populates a case folding map whenever ToLower and ToUpper are called. The map itself comes from the latest metadata info from Unicode, run through a conversion tool.... Perhaps it would be better if it could handle all locales through metadata files directly, but that might tie the lib to the filesystem... hm.. Anyway, depending on the target, you may run into a similar problem with German ß / ss, some Greek letters with composite forms, and more, but I think most systems default lcase/ucase conventions try to avoid messing with those letters whenever possible for backwards compatibility. The proper solution is to consider case folding and normalization separately....: https://www.w3.org/International/wiki/Case_folding#Recommendations_for_Case_Folding |
| ||
I've found a better way for Android by setting the default locale:static void setLocale(String language, String country) { System.out.println("setLocale = " + language + " " + country); Activity activity = BBAndroidGame.AndroidGame().GetActivity(); Context context = activity.getApplicationContext(); Configuration config = context.getResources().getConfiguration(); Locale locale = new Locale(language, country); Locale.setDefault(locale); config.locale = locale; context.getResources().updateConfiguration(config, context.getResources().getDisplayMetrics()); } In Diddy's OnCreate and OnResume it now calls: SetLocale(localeLanguage, localeCountry) Field localeLanguage:String = "en" Field localeCountry:String = "US" |