Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-1659] (Android) toImage functions blowing up with UI widgets

GitHub Issuen/a
TypeBug
PriorityLow
StatusClosed
ResolutionFixed
Resolution Date2011-04-17T01:56:47.000+0000
Affected Version/sn/a
Fix Version/sRelease 1.6.0 M07
ComponentsAndroid
Labelsandroid, defect, release-1.6.0, toimage, ui
Reporterzcopley
AssigneeNolan Wright
Created2011-04-15T02:58:38.000+0000
Updated2011-04-17T01:56:47.000+0000

Description

Calling toImage seems to blow up. I've tried it on buttons and views now and I get the same results. It seems to work fine on iPhone. (iOS 4.0.2 and Titanium Mobile SDK 1.4.1 from GitHub.)

var appDirName = Titanium.Filesystem.applicationDataDirectory;
var imageFile = Titanium.Filesystem.getFile(appDirName, 'image.jpg');

if (!imageFile.exists()) {
    Titanium.API.debug("File " + imageFile.name + " does not exist yet.");
}

var button = Titanium.UI.createButton({
    title:'Gargargar!',
    height:40,
    width:200,
    top:10
});

imageFile.write(button.toImage()); // blows up on Android

if (imageFile.exists()) {
    // Note: Titanium.Filesystem.File.size attribute not mentioned in the API docs
    Titanium.API.debug(imageFile.name + " exists, size: " + imageFile.size);
}

Android stack trace:

D/TiAPI   (  569): (kroll$1) [880,926] File image.jpg does not exist yet.
I/ActivityManager(   67): Displayed activity net.status.tstest/.TstestActivity: 4723 ms (total 4723 ms)
W/TiAnalyticsSvc(  569): (Thread-10) [517,1443] Analytics Service Started
D/AndroidRuntime(  569): Shutting down VM
W/dalvikvm(  569): threadid=1: thread exiting with uncaught exception (group=0x4001d800)
E/TiUncaughtHandler(  569): (main) [123,1566] Sending event: exception on thread: main msg:java.lang.IllegalArgumentException: width and height must be > 0
E/TiUncaughtHandler(  569): java.lang.IllegalArgumentException: width and height must be > 0
E/TiUncaughtHandler(  569):     at android.graphics.Bitmap.nativeCreate(Native Method)
E/TiUncaughtHandler(  569):     at android.graphics.Bitmap.createBitmap(Bitmap.java:468)
E/TiUncaughtHandler(  569):     at org.appcelerator.titanium.util.TiUIHelper.viewToImage(TiUIHelper.java:417)
E/TiUncaughtHandler(  569):     at org.appcelerator.titanium.view.TiUIView.toImage(TiUIView.java:637)
E/TiUncaughtHandler(  569):     at org.appcelerator.titanium.proxy.TiViewProxy.handleToImage(TiViewProxy.java:435)
E/TiUncaughtHandler(  569):     at org.appcelerator.titanium.proxy.TiViewProxy.handleMessage(TiViewProxy.java:139)
E/TiUncaughtHandler(  569):     at android.os.Handler.dispatchMessage(Handler.java:95)
E/TiUncaughtHandler(  569):     at android.os.Looper.loop(Looper.java:123)
E/TiUncaughtHandler(  569):     at android.app.ActivityThread.main(ActivityThread.java:4627)
E/TiUncaughtHandler(  569):     at java.lang.reflect.Method.invokeNative(Native Method)
E/TiUncaughtHandler(  569):     at java.lang.reflect.Method.invoke(Method.java:521)
E/TiUncaughtHandler(  569):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
E/TiUncaughtHandler(  569):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
E/TiUncaughtHandler(  569):     at dalvik.system.NativeStart.main(Native Method)
D/dalvikvm(  569): GC_FOR_MALLOC freed 6846 objects / 392464 bytes in 117ms
D/TiApplication(  569): (main) [195,1761] Analytics Event: type=ti.crash
D/TiApplication(  569):  event=ti.crash
D/TiApplication(  569):  timestamp=2010-08-26T20:45:41.224-0800
D/TiApplication(  569):  mid=9774d56d682e549c
D/TiApplication(  569):  sid=715a773d-1c37-434d-b55d-09008336d89a
D/TiApplication(  569):  aguid=2ac80eec-55c8-4d03-9478-1b6255458ea5
D/TiApplication(  569):  isJSON=true
D/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"}
E/AndroidRuntime(  569): FATAL EXCEPTION: main
E/AndroidRuntime(  569): java.lang.IllegalArgumentException: width and height must be > 0
E/AndroidRuntime(  569):    at android.graphics.Bitmap.nativeCreate(Native Method)
E/AndroidRuntime(  569):    at android.graphics.Bitmap.createBitmap(Bitmap.java:468)
E/AndroidRuntime(  569):    at org.appcelerator.titanium.util.TiUIHelper.viewToImage(TiUIHelper.java:417)
E/AndroidRuntime(  569):    at org.appcelerator.titanium.view.TiUIView.toImage(TiUIView.java:637)
E/AndroidRuntime(  569):    at org.appcelerator.titanium.proxy.TiViewProxy.handleToImage(TiViewProxy.java:435)
E/AndroidRuntime(  569):    at org.appcelerator.titanium.proxy.TiViewProxy.handleMessage(TiViewProxy.java:139)
E/AndroidRuntime(  569):    at android.os.Handler.dispatchMessage(Handler.java:95)
E/AndroidRuntime(  569):    at android.os.Looper.loop(Looper.java:123)
E/AndroidRuntime(  569):    at android.app.ActivityThread.main(ActivityThread.java:4627)
E/AndroidRuntime(  569):    at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime(  569):    at java.lang.reflect.Method.invoke(Method.java:521)
E/AndroidRuntime(  569):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
E/AndroidRuntime(  569):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
E/AndroidRuntime(  569):    at dalvik.system.NativeStart.main(Native Method)

Here's what happens on iPhone (also see attached image.jpg).

[DEBUG] File image.jpg does not exist yet.
[DEBUG] image.jpg exists, size: 6311

Attachments

FileDateSize
app.js2011-04-15T02:58:39.000+00001091
image.jpg2011-04-15T02:58:39.000+00006311

Comments

  1. zcopley 2011-04-15

    Related issue? https://appcelerator.lighthouseapp.com/projects/32238/tickets/817-android-imageviewtoimage-crashes-app"> https://appcelerator.lighthouseapp.com/projects/32238/tickets/817-a...

  2. Don Thorp 2011-04-15

    Looked into this a bit. toImage doesn't force the native control to be laid out in the case above since it hasn't been added to a window so it's layout methods aren't called. This will be a tricky issue to deal with in that regard.

  3. Opie Cyrus 2011-04-15

    (from [5d1f301879f66a1342901923c47b0cdd5ed0acf2]) [#1659 state:fixed-in-qa] allow toImage to be called on elements not yet layed out

    Changed toImage call to force a measure on a UI element in order to get the needed width and height to be drawn even if it hasnt been laid out yet. If even after a measure the width and height are invalid, a default value is set so the bitmap can be created and a error is logged
    https://github.com/appcelerator/titanium_mobile/commit/5d1f301879f66a1342901923c47b0cdd5ed0acf2"> https://github.com/appcelerator/titanium_mobile/commit/5d1f301879f6...

  4. Opie Cyrus 2011-04-15

    Please verify with the original test included with the first post.

  5. Don Thorp 2011-04-15

    This no longer crashes, but it's failing to write the file. I updated the test app to report both cases.

       
       var appDirName = Titanium.Filesystem.applicationDataDirectory;
       var imageFile = Titanium.Filesystem.getFile(appDirName, 'image.jpg');
       
       if (!imageFile.exists()) {
           Titanium.API.debug("File " + imageFile.name + " does not exist yet.");
       } else {
           Titanium.API.debug("File " + imageFile.name + " EXISTS yet.");  
       }
       
       var button = Titanium.UI.createButton({
           title:'Gargargar!',
           height:40,
           width:200,
           top:10
       });
       
       imageFile.write(button.toImage()); // blows up on Android
       
       if (imageFile.exists()) {
           // Note: Titanium.Filesystem.File.size attribute not mentioned in the API docs
           Titanium.API.debug(imageFile.name + " exists, size: " + imageFile.size);
       } else {
           Titanium.API.debug("File " + imageFile.name + " does not exist yet.");
       }
       
  6. Opie Cyrus 2011-04-15

    (from [78001f43c0be0a0019079ca838a1475041a704da]) [#1659 state:fixed-in-qa] fixed error causing toImage file to actually be written

    Modified TiUIHelper to force layout on objects that had not yet been added to a view so toImage would corectly generate the image. Fixed test to pass corect parameter to the write() call. Added exception to the write() call when the object passed in is unrecognized.
    https://github.com/appcelerator/titanium_mobile/commit/78001f43c0be0a0019079ca838a1475041a704da"> https://github.com/appcelerator/titanium_mobile/commit/78001f43c0be...

  7. Opie Cyrus 2011-04-15

    Please verify with the modified test client that now passes the correct value to the filesystem write call().

  8. Marshall Culpepper 2011-04-15

    verified w/ test case on Nexus s 2.3.2

JSON Source