@Kroll.method
  public void takeScreenshot(KrollFunction callback) {
    Activity a = TiApplication.getAppCurrentActivity();

    if (a == null) {
      Log.w(TAG, "Could not get current activity for takeScreenshot.", Log.DEBUG_MODE);
      callback.callAsync(getKrollObject(), new Object[] {null});
      return;
    }

    while (a.getParent() != null) {
      a = a.getParent();
    }

    Window w = a.getWindow();

    while (w.getContainer() != null) {
      w = w.getContainer();
    }

    KrollDict image = TiUIHelper.viewToImage(null, w.getDecorView());
    if (callback != null) {
      callback.callAsync(getKrollObject(), new Object[] {image});
    }
  }
  @Kroll.method
  public TiBlob getFilteredScreenshot(HashMap options) {
    if (options != null) {
      if (options.containsKey("callback")) {
        KrollFunction callback = (KrollFunction) options.get("callback");
        if (callback != null) {
          (new FilterScreenShotTask()).execute(options);
          return null;
        }
      }
    }

    //        View view = TiApplication.getAppCurrentActivity().getWindow()
    //                .getDecorView();
    View view =
        TiApplication.getAppCurrentActivity()
            .getWindow()
            .getDecorView()
            .findViewById(android.R.id.content);
    if (view == null) {
      return null;
    }

    Bitmap bitmap = null;
    try {
      if (TiApplication.isUIThread()) {
        bitmap = TiUIHelper.viewToBitmap(null, view);
      } else {
        bitmap =
            (Bitmap)
                TiMessenger.sendBlockingMainMessage(
                    getMainHandler().obtainMessage(MSG_GETVIEWIMAGE), view);
      }
      //            Rect statusBar = new Rect();
      //            view.getWindowVisibleDisplayFrame(statusBar);
      //            bitmap = Bitmap.createBitmap(bitmap, 0, statusBar.top,
      //                    bitmap.getWidth(), bitmap.getHeight() - statusBar.top,
      //                    null, true);
    } catch (Exception e) {
      bitmap = null;
    }
    return getFilteredImage(bitmap, options);
  }
 @Override
 protected TiBlob doInBackground(Object... params) {
   HashMap options = (HashMap) params[0];
   View view = TiApplication.getAppCurrentActivity().getWindow().getDecorView();
   Bitmap bitmap = null;
   try {
     bitmap = TiUIHelper.viewToBitmap(null, view);
     Rect statusBar = new Rect();
     view.getWindowVisibleDisplayFrame(statusBar);
     bitmap =
         Bitmap.createBitmap(
             bitmap,
             0,
             statusBar.top,
             bitmap.getWidth(),
             bitmap.getHeight() - statusBar.top,
             null,
             true);
   } catch (Exception e) {
     bitmap = null;
   }
   return getFilteredImage(bitmap, options);
 }
  @Kroll.method
  public void previewImage(KrollDict options) {
    Activity activity = TiApplication.getAppCurrentActivity();
    if (activity == null) {
      Log.w(TAG, "Unable to get current activity for previewImage.", Log.DEBUG_MODE);
      return;
    }

    KrollFunction successCallback = null;
    KrollFunction errorCallback = null;
    TiBlob image = null;

    if (options.containsKey("success")) {
      successCallback = (KrollFunction) options.get("success");
    }
    if (options.containsKey("error")) {
      errorCallback = (KrollFunction) options.get("error");
    }
    if (options.containsKey("image")) {
      image = (TiBlob) options.get("image");
    }

    if (image == null) {
      if (errorCallback != null) {
        errorCallback.callAsync(
            getKrollObject(), createErrorResponse(UNKNOWN_ERROR, "Missing image property"));
      }
    }

    TiBaseFile f = (TiBaseFile) image.getData();

    final KrollFunction fSuccessCallback = successCallback;
    final KrollFunction fErrorCallback = errorCallback;

    Log.d(TAG, "openPhotoGallery called", Log.DEBUG_MODE);

    TiActivitySupport activitySupport = (TiActivitySupport) activity;

    Intent intent = new Intent(Intent.ACTION_VIEW);
    TiIntentWrapper previewIntent = new TiIntentWrapper(intent);
    String mimeType = image.getMimeType();

    if (mimeType != null && mimeType.length() > 0) {
      intent.setDataAndType(Uri.parse(f.nativePath()), mimeType);
    } else {
      intent.setData(Uri.parse(f.nativePath()));
    }

    previewIntent.setWindowId(TiIntentWrapper.createActivityName("PREVIEW"));

    final int code = activitySupport.getUniqueResultCode();
    activitySupport.launchActivityForResult(
        intent,
        code,
        new TiActivityResultHandler() {

          public void onResult(Activity activity, int requestCode, int resultCode, Intent data) {
            Log.e(TAG, "OnResult called: " + resultCode);
            if (fSuccessCallback != null) {
              KrollDict response = new KrollDict();
              response.putCodeAndMessage(NO_ERROR, null);
              fSuccessCallback.callAsync(getKrollObject(), response);
            }
          }

          public void onError(Activity activity, int requestCode, Exception e) {
            String msg = "Gallery problem: " + e.getMessage();
            Log.e(TAG, msg, e);
            if (fErrorCallback != null) {
              fErrorCallback.callAsync(getKrollObject(), createErrorResponse(UNKNOWN_ERROR, msg));
            }
          }
        });
  }
  // This handler callback is tied to the UI thread.
  public boolean handleMessage(Message msg) {
    switch (msg.what) {
      case MSG_GETVIEW:
        {
          AsyncResult result = (AsyncResult) msg.obj;
          result.setResult(handleGetView());
          return true;
        }
      case MSG_ADD_CHILD:
        {
          AsyncResult result = (AsyncResult) msg.obj;
          handleAdd((TiViewProxy) result.getArg());
          result.setResult(null); // Signal added.
          return true;
        }
      case MSG_REMOVE_CHILD:
        {
          AsyncResult result = (AsyncResult) msg.obj;
          handleRemove((TiViewProxy) result.getArg());
          result.setResult(null); // Signal removed.
          return true;
        }
      case MSG_BLUR:
        {
          handleBlur();
          return true;
        }
      case MSG_FOCUS:
        {
          handleFocus();
          return true;
        }
      case MSG_SHOW:
        {
          handleShow((KrollDict) msg.obj);
          return true;
        }
      case MSG_HIDE:
        {
          handleHide((KrollDict) msg.obj);
          return true;
        }
      case MSG_ANIMATE:
        {
          handleAnimate();
          return true;
        }
      case MSG_TOIMAGE:
        {
          AsyncResult result = (AsyncResult) msg.obj;
          result.setResult(handleToImage());
          return true;
        }
      case MSG_GETSIZE:
        {
          AsyncResult result = (AsyncResult) msg.obj;
          KrollDict d = null;
          d = new KrollDict();
          d.put(TiC.PROPERTY_X, 0);
          d.put(TiC.PROPERTY_Y, 0);
          if (view != null) {
            View v = view.getNativeView();
            if (v != null) {
              TiDimension nativeWidth = new TiDimension(v.getWidth(), TiDimension.TYPE_WIDTH);
              TiDimension nativeHeight = new TiDimension(v.getHeight(), TiDimension.TYPE_HEIGHT);

              // TiDimension needs a view to grab the window manager, so we'll just use the
              // decorview of the current window
              View decorView = TiApplication.getAppCurrentActivity().getWindow().getDecorView();

              d.put(TiC.PROPERTY_WIDTH, nativeWidth.getAsDefault(decorView));
              d.put(TiC.PROPERTY_HEIGHT, nativeHeight.getAsDefault(decorView));
            }
          }
          if (!d.containsKey(TiC.PROPERTY_WIDTH)) {
            d.put(TiC.PROPERTY_WIDTH, 0);
            d.put(TiC.PROPERTY_HEIGHT, 0);
          }

          result.setResult(d);
          return true;
        }
      case MSG_GETRECT:
        {
          AsyncResult result = (AsyncResult) msg.obj;
          KrollDict d = null;
          d = new KrollDict();
          if (view != null) {
            View v = view.getNativeView();
            if (v != null) {
              TiDimension nativeWidth = new TiDimension(v.getWidth(), TiDimension.TYPE_WIDTH);
              TiDimension nativeHeight = new TiDimension(v.getHeight(), TiDimension.TYPE_HEIGHT);
              TiDimension nativeLeft = new TiDimension(v.getLeft(), TiDimension.TYPE_LEFT);
              TiDimension nativeTop = new TiDimension(v.getTop(), TiDimension.TYPE_TOP);

              // TiDimension needs a view to grab the window manager, so we'll just use the
              // decorview of the current window
              View decorView = TiApplication.getAppCurrentActivity().getWindow().getDecorView();

              d.put(TiC.PROPERTY_WIDTH, nativeWidth.getAsDefault(decorView));
              d.put(TiC.PROPERTY_HEIGHT, nativeHeight.getAsDefault(decorView));
              d.put(TiC.PROPERTY_X, nativeLeft.getAsDefault(decorView));
              d.put(TiC.PROPERTY_Y, nativeTop.getAsDefault(decorView));
            }
          }
          if (!d.containsKey(TiC.PROPERTY_WIDTH)) {
            d.put(TiC.PROPERTY_WIDTH, 0);
            d.put(TiC.PROPERTY_HEIGHT, 0);
            d.put(TiC.PROPERTY_X, 0);
            d.put(TiC.PROPERTY_Y, 0);
          }

          result.setResult(d);
          return true;
        }
      case MSG_FINISH_LAYOUT:
        {
          handleFinishLayout();
          return true;
        }
      case MSG_UPDATE_LAYOUT:
        {
          handleUpdateLayout((HashMap) msg.obj);
          return true;
        }
    }
    return super.handleMessage(msg);
  }
  public TiBubbleAndroidView(TiViewProxy proxy) {
    super(proxy);

    prop = proxy.getProperties();

    LayoutArrangement arrangement = LayoutArrangement.DEFAULT;

    if (proxy.hasProperty(TiC.PROPERTY_LAYOUT)) {
      String layoutProperty = TiConvert.toString(proxy.getProperty(TiC.PROPERTY_LAYOUT));
      if (layoutProperty.equals(TiC.LAYOUT_HORIZONTAL)) {
        arrangement = LayoutArrangement.HORIZONTAL;
      } else if (layoutProperty.equals(TiC.LAYOUT_VERTICAL)) {
        arrangement = LayoutArrangement.VERTICAL;
      }
    }

    TiCompositeLayout nativeView = new TiCompositeLayout(proxy.getActivity(), arrangement);
    setNativeView(nativeView);

    if (nativeBubbleView == null) {
      Activity currentActivity = proxy.getActivity();
      if (currentActivity == null) {
        currentActivity = TiApplication.getAppCurrentActivity();
      }
      nativeBubbleView = new NativeBubbleView(currentActivity);

      LayoutParams params = new LayoutParams();
      params.height = android.widget.FrameLayout.LayoutParams.MATCH_PARENT;
      params.width = android.widget.FrameLayout.LayoutParams.MATCH_PARENT;

      ViewGroup savedParent = null;
      int childIndex = -1;

      TiUIView parentView = proxy.getParent().getOrCreateView();
      View parentNativeView = (View) parentView.getNativeView();

      if (parentNativeView != null) {
        ViewParent nativeParent = (ViewParent) parentNativeView;

        if (nativeParent instanceof ViewGroup) {
          savedParent = (ViewGroup) nativeParent;
          childIndex = savedParent.indexOfChild(nativeView);
          savedParent.removeView(nativeView);
        }
      }

      nativeBubbleView.addView(nativeView, params);

      if (savedParent != null) {
        savedParent.addView(nativeBubbleView, childIndex, getLayoutParams());
      }

      if (prop.containsKey("bubbleRadius")) {
        float radius = 0;
        TiDimension radiusDim =
            TiConvert.toTiDimension(prop.get("bubbleRadius"), TiDimension.TYPE_WIDTH);
        if (radiusDim != null) {
          radius = (float) radiusDim.getPixels(getNativeView());
        }
        nativeBubbleView.setBubbleRadius(radius);
      }

      if (prop.containsKey("bubbleColor")) {
        nativeBubbleView.setBubbleColor(TiConvert.toColor(prop, "bubbleColor"));
      } else {
        Integer bgColor = TiConvert.toColor(prop, TiC.PROPERTY_BACKGROUND_COLOR);
        if (bgColor != null) {
          nativeBubbleView.setBubbleColor(bgColor);
        }
      }

      if (prop.containsKey("bubbleBeak")) {
        nativeBubbleView.setBubbleBeak(TiConvert.toInt(prop, "bubbleBeak"));
      }

      if (prop.containsKey("bubbleBeakVertical")) {
        nativeBubbleView.setBubbleBeakVertical(TiConvert.toInt(prop, "bubbleBeakVertical"));
      }

      parentView.remove(this);
      parentView.add(this);
    }
  }