{ "id": "62291", "key": "TIMOB-1659", "fields": { "issuetype": { "id": "1", "description": "A problem which impairs or prevents the functions of the product.", "name": "Bug", "subtask": false }, "project": { "id": "10153", "key": "TIMOB", "name": "Titanium SDK/CLI", "projectCategory": { "id": "10100", "description": "Titanium and related SDKs used in application development", "name": "Client" } }, "fixVersions": [ { "id": "11240", "name": "Release 1.6.0 M07", "archived": true, "released": true, "releaseDate": "2011-01-31" } ], "resolution": { "id": "1", "description": "A fix for this issue is checked into the tree and tested.", "name": "Fixed" }, "resolutiondate": "2011-04-17T01:56:47.000+0000", "created": "2011-04-15T02:58:38.000+0000", "priority": { "name": "Low", "id": "4" }, "labels": [ "android", "defect", "release-1.6.0", "toimage", "ui" ], "versions": [], "issuelinks": [], "assignee": { "name": "nwright", "key": "nwright", "displayName": "Nolan Wright", "active": false, "timeZone": "America/Los_Angeles" }, "updated": "2011-04-17T01:56:47.000+0000", "status": { "description": "The issue is considered finished, the resolution is correct. Issues which are closed can be reopened.", "name": "Closed", "id": "6", "statusCategory": { "id": 3, "key": "done", "colorName": "green", "name": "Done" } }, "components": [ { "id": "10202", "name": "Android", "description": "Android Platform" } ], "description": "{html}
Calling toImage seems to blow up. I've tried it on buttons and\nviews now and I get the same results. It seems to work fine on\niPhone. (iOS 4.0.2 and Titanium Mobile SDK 1.4.1 from GitHub.)
\n\nvar appDirName = Titanium.Filesystem.applicationDataDirectory;\nvar imageFile = Titanium.Filesystem.getFile(appDirName, 'image.jpg');\n\nif (!imageFile.exists()) {\n Titanium.API.debug(\"File \" + imageFile.name + \" does not exist yet.\");\n}\n\nvar button = Titanium.UI.createButton({\n title:'Gargargar!',\n height:40,\n width:200,\n top:10\n});\n\nimageFile.write(button.toImage()); // blows up on Android\n\nif (imageFile.exists()) {\n // Note: Titanium.Filesystem.File.size attribute not mentioned in the API docs\n Titanium.API.debug(imageFile.name + \" exists, size: \" + imageFile.size);\n}
\n
\nAndroid stack trace:
\n\nD/TiAPI ( 569): (kroll$1) [880,926] File image.jpg does not exist yet.\nI/ActivityManager( 67): Displayed activity net.status.tstest/.TstestActivity: 4723 ms (total 4723 ms)\nW/TiAnalyticsSvc( 569): (Thread-10) [517,1443] Analytics Service Started\nD/AndroidRuntime( 569): Shutting down VM\nW/dalvikvm( 569): threadid=1: thread exiting with uncaught exception (group=0x4001d800)\nE/TiUncaughtHandler( 569): (main) [123,1566] Sending event: exception on thread: main msg:java.lang.IllegalArgumentException: width and height must be > 0\nE/TiUncaughtHandler( 569): java.lang.IllegalArgumentException: width and height must be > 0\nE/TiUncaughtHandler( 569): at android.graphics.Bitmap.nativeCreate(Native Method)\nE/TiUncaughtHandler( 569): at android.graphics.Bitmap.createBitmap(Bitmap.java:468)\nE/TiUncaughtHandler( 569): at org.appcelerator.titanium.util.TiUIHelper.viewToImage(TiUIHelper.java:417)\nE/TiUncaughtHandler( 569): at org.appcelerator.titanium.view.TiUIView.toImage(TiUIView.java:637)\nE/TiUncaughtHandler( 569): at org.appcelerator.titanium.proxy.TiViewProxy.handleToImage(TiViewProxy.java:435)\nE/TiUncaughtHandler( 569): at org.appcelerator.titanium.proxy.TiViewProxy.handleMessage(TiViewProxy.java:139)\nE/TiUncaughtHandler( 569): at android.os.Handler.dispatchMessage(Handler.java:95)\nE/TiUncaughtHandler( 569): at android.os.Looper.loop(Looper.java:123)\nE/TiUncaughtHandler( 569): at android.app.ActivityThread.main(ActivityThread.java:4627)\nE/TiUncaughtHandler( 569): at java.lang.reflect.Method.invokeNative(Native Method)\nE/TiUncaughtHandler( 569): at java.lang.reflect.Method.invoke(Method.java:521)\nE/TiUncaughtHandler( 569): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)\nE/TiUncaughtHandler( 569): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)\nE/TiUncaughtHandler( 569): at dalvik.system.NativeStart.main(Native Method)\nD/dalvikvm( 569): GC_FOR_MALLOC freed 6846 objects / 392464 bytes in 117ms\nD/TiApplication( 569): (main) [195,1761] Analytics Event: type=ti.crash\nD/TiApplication( 569): event=ti.crash\nD/TiApplication( 569): timestamp=2010-08-26T20:45:41.224-0800\nD/TiApplication( 569): mid=9774d56d682e549c\nD/TiApplication( 569): sid=715a773d-1c37-434d-b55d-09008336d89a\nD/TiApplication( 569): aguid=2ac80eec-55c8-4d03-9478-1b6255458ea5\nD/TiApplication( 569): isJSON=true\nD/TiApplication( 569): payload={\"value\":\"thread_namemain\\nthread_id1\\nerror_msgjava.lang.IllegalArgumentException: width and height must be > 0\\n<<<<<<<<<<<<<<< STACK TRACE >>>>>>>>>>>>>>>\\nandroid.graphics.Bitmap.nativeCreate(Native Method)\\nandroid.graphics.Bitmap.createBitmap(Bitmap.java:468)\\norg.appcelerator.titanium.util.TiUIHelper.viewToImage(TiUIHelper.java:417)\\norg.appcelerator.titanium.view.TiUIView.toImage(TiUIView.java:637)\\norg.appcelerator.titanium.proxy.TiViewProxy.handleToImage(TiViewProxy.java:435)\\norg.appcelerator.titanium.proxy.TiViewProxy.handleMessage(TiViewProxy.java:139)\\nandroid.os.Handler.dispatchMessage(Handler.java:95)\\nandroid.os.Looper.loop(Looper.java:123)\\nandroid.app.ActivityThread.main(ActivityThread.java:4627)\\njava.lang.reflect.Method.invokeNative(Native Method)\\njava.lang.reflect.Method.invoke(Method.java:521)\\ncom.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)\\ncom.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)\\ndalvik.system.NativeStart.main(Native Method)\\n\"}\nE/AndroidRuntime( 569): FATAL EXCEPTION: main\nE/AndroidRuntime( 569): java.lang.IllegalArgumentException: width and height must be > 0\nE/AndroidRuntime( 569): at android.graphics.Bitmap.nativeCreate(Native Method)\nE/AndroidRuntime( 569): at android.graphics.Bitmap.createBitmap(Bitmap.java:468)\nE/AndroidRuntime( 569): at org.appcelerator.titanium.util.TiUIHelper.viewToImage(TiUIHelper.java:417)\nE/AndroidRuntime( 569): at org.appcelerator.titanium.view.TiUIView.toImage(TiUIView.java:637)\nE/AndroidRuntime( 569): at org.appcelerator.titanium.proxy.TiViewProxy.handleToImage(TiViewProxy.java:435)\nE/AndroidRuntime( 569): at org.appcelerator.titanium.proxy.TiViewProxy.handleMessage(TiViewProxy.java:139)\nE/AndroidRuntime( 569): at android.os.Handler.dispatchMessage(Handler.java:95)\nE/AndroidRuntime( 569): at android.os.Looper.loop(Looper.java:123)\nE/AndroidRuntime( 569): at android.app.ActivityThread.main(ActivityThread.java:4627)\nE/AndroidRuntime( 569): at java.lang.reflect.Method.invokeNative(Native Method)\nE/AndroidRuntime( 569): at java.lang.reflect.Method.invoke(Method.java:521)\nE/AndroidRuntime( 569): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)\nE/AndroidRuntime( 569): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)\nE/AndroidRuntime( 569): at dalvik.system.NativeStart.main(Native Method)
\n
\nHere's what happens on iPhone (also see attached image.jpg).
\n\n[DEBUG] File image.jpg does not exist yet.\n[DEBUG] image.jpg exists, size: 6311
\n
Looked into this a bit. toImage doesn't force the native control\nto be laid out in the case above since it hasn't been added to a\nwindow so it's layout methods aren't called. This will be a tricky\nissue to deal with in that regard.
(from [5d1f301879f66a1342901923c47b0cdd5ed0acf2])\n[#1659 state:fixed-in-qa] allow toImage to be\ncalled on elements not yet layed out
\nChanged toImage call to force a measure on a UI element in order\nto get the needed width and height to be drawn even if it hasnt\nbeen laid out yet. If even after a measure the width and height are\ninvalid, a default value is set so the bitmap can be created and a\nerror is logged
\n\nhttps://github.com/appcelerator/titanium_mobile/commit/5d1f301879f6...
Please verify with the original test included with the first\npost.
This no longer crashes, but it's failing to write the file. I\nupdated the test app to report both cases.
\n\n\nvar appDirName = Titanium.Filesystem.applicationDataDirectory;\nvar imageFile = Titanium.Filesystem.getFile(appDirName, 'image.jpg');\n\nif (!imageFile.exists()) {\n Titanium.API.debug(\"File \" + imageFile.name + \" does not exist yet.\");\n} else {\n Titanium.API.debug(\"File \" + imageFile.name + \" EXISTS yet.\"); \n}\n\nvar button = Titanium.UI.createButton({\n title:'Gargargar!',\n height:40,\n width:200,\n top:10\n});\n\nimageFile.write(button.toImage()); // blows up on Android\n\nif (imageFile.exists()) {\n // Note: Titanium.Filesystem.File.size attribute not mentioned in the API docs\n Titanium.API.debug(imageFile.name + \" exists, size: \" + imageFile.size);\n} else {\n Titanium.API.debug(\"File \" + imageFile.name + \" does not exist yet.\");\n}
\n
(from [78001f43c0be0a0019079ca838a1475041a704da])\n[#1659 state:fixed-in-qa] fixed error causing\ntoImage file to actually be written
\nModified TiUIHelper to force layout on objects that had not yet\nbeen added to a view so toImage would corectly generate the image.\nFixed test to pass corect parameter to the write() call. Added\nexception to the write() call when the object passed in is\nunrecognized.
\n\nhttps://github.com/appcelerator/titanium_mobile/commit/78001f43c0be...
Please verify with the modified test client that now passes the\ncorrect value to the filesystem write call().
verified w/ test case on Nexus s 2.3.2