public void testOpenGraphActionAndObjectImageAttachments() throws JSONException {
    OpenGraphAction action = OpenGraphAction.Factory.createForPost();
    OpenGraphObject object = OpenGraphObject.Factory.createForPost("bar");
    action.setProperty("foo", object);

    FacebookDialog.OpenGraphActionDialogBuilder builder =
        new FacebookDialog.OpenGraphActionDialogBuilder(getActivity(), action, "foo", "foo");

    Bitmap bitmap = Bitmap.createBitmap(20, 20, Bitmap.Config.ALPHA_8);

    builder.setImageAttachmentsForAction(Arrays.asList(bitmap));
    builder.setImageAttachmentsForObject("foo", Arrays.asList(bitmap));

    List<String> attachmentNames = builder.getImageAttachmentNames();
    assertNotNull(attachmentNames);
    assertTrue(attachmentNames.size() == 2);

    List<GraphObject> objectImages = object.getImage();
    assertNotNull(objectImages);
    assertTrue(objectImages.size() == 1);

    String attachmentName =
        getAttachmentNameFromContentUri((String) objectImages.get(0).getProperty("url"));
    assertTrue(attachmentNames.contains(attachmentName));

    List<JSONObject> actionImages = action.getImage();
    assertNotNull(actionImages);
    assertTrue(actionImages.size() == 1);

    attachmentName = getAttachmentNameFromContentUri((String) actionImages.get(0).getString("url"));
    assertTrue(attachmentNames.contains(attachmentName));
  }
  public void testCantSetObjectAttachmentsWithoutObjectProperty() {
    try {
      OpenGraphAction action = OpenGraphAction.Factory.createForPost();
      FacebookDialog.OpenGraphActionDialogBuilder builder =
          new FacebookDialog.OpenGraphActionDialogBuilder(getActivity(), action, "foo", "foo");

      builder.setImageAttachmentsForObject("foo", new ArrayList<Bitmap>());
      fail("expected exception");
    } catch (IllegalArgumentException exception) {
    }
  }
  public void testOpenGraphDialogBuilderRequiresPreviewPropertyToExist() {
    try {
      FacebookDialog.OpenGraphActionDialogBuilder builder =
          new FacebookDialog.OpenGraphActionDialogBuilder(
              getActivity(), OpenGraphAction.Factory.createForPost(), "foo", "nosuchproperty");

      builder.build();
      fail("expected exception");
    } catch (IllegalArgumentException exception) {
    }
  }
  public void testOpenGraphDialogBuilderRequiresActionType() {
    try {
      FacebookDialog.OpenGraphActionDialogBuilder builder =
          new FacebookDialog.OpenGraphActionDialogBuilder(
              getActivity(), OpenGraphAction.Factory.createForPost(), null, "foo");

      builder.build();
      fail("expected exception");
    } catch (IllegalArgumentException exception) {
    }
  }
  public void testCantSetAttachmentsWithNullBitmaps() {
    try {
      OpenGraphAction action = OpenGraphAction.Factory.createForPost();
      action.setProperty("foo", "bar");

      FacebookDialog.OpenGraphActionDialogBuilder builder =
          new FacebookDialog.OpenGraphActionDialogBuilder(getActivity(), action, "foo", "foo");

      builder.setImageAttachmentsForAction(Arrays.asList((Bitmap) null));
      fail("expected exception");
    } catch (NullPointerException exception) {
    }
  }
  private void publish(JSONArray args, CallbackContext callbackContext) throws JSONException {
    JSONObject actionParams = args.getJSONObject(0);

    if (actionParams.has("object")) {
      RequestBatch requestBatch = new RequestBatch();

      OpenGraphObject object = buildOpenGraphObject(actionParams);

      Request objectRequest =
          Request.newPostOpenGraphObjectRequest(Session.getActiveSession(), object, null);
      objectRequest.setBatchEntryName("objectCreate");

      OpenGraphAction action =
          OpenGraphAction.Factory.createForPost(actionParams.getString("action"));

      action.setMessage(actionParams.getString("message"));
      action.setProperty("place", actionParams.getLong("place"));
      action.setExplicitlyShared(actionParams.getBoolean("explicitlyShared"));
      action.setProperty(actionParams.getString("objectType"), "{result=objectCreate:$.id}");

      Request request =
          Request.newPostOpenGraphActionRequest(Session.getActiveSession(), action, null);
      request.setBatchEntryDependsOn("objectCreate");

      requestBatch.add(objectRequest);
      requestBatch.add(request);

      List<Response> responses = requestBatch.executeAndWait();
      Response lastResponse = null;

      for (Response response : responses) {

        if (response.getError() != null) {
          callbackContext.error(response.getError().toString());
          return;
        }

        lastResponse = response;
      }

      callbackContext.success(lastResponse.getGraphObject().getInnerJSONObject());
    } else {
      OpenGraphAction action =
          OpenGraphAction.Factory.createForPost(actionParams.getString("action"));

      action.setMessage(actionParams.getString("message"));
      action.setProperty("place", actionParams.getLong("place"));
      action.setExplicitlyShared(actionParams.getBoolean("explicitlyShared"));
      action.setProperty(actionParams.getString("objectType"), actionParams.getString("objectId"));

      Request request =
          Request.newPostOpenGraphActionRequest(Session.getActiveSession(), action, null);

      Response response = request.executeAndWait();

      if (response.getError() != null) {
        callbackContext.error(response.getError().toString());
      } else {
        callbackContext.success(response.getGraphObject().getInnerJSONObject());
      }
    }
  }
  @Override
  protected void executeImpl() {
    if (FacebookDialog.canPresentOpenGraphActionDialog(
        sessionManager.getActivity(), OpenGraphActionDialogFeature.OG_ACTION_DIALOG)) {

      FacebookDialog shareDialog = null;

      /*
       * Publishing open graph can be in 2 ways: 1. Publish actions on
       * app-owned objects Means, you as developer of the app define Open
       * Graph Object on your server with <meta> tags or you have
       * published object to facebook server. This is predefined Object
       * and user can't change it. 2. Publish actions on user-owned
       * objects You didn't add anything to server, but you give the user
       * the option to define Object Graph properties from the app and
       * publish it.
       */

      String objectId = mStory.getStoryObject().getId();
      String objectUrl = mStory.getStoryObject().getHostedUrl();
      final boolean predefineObject;
      if (objectId != null || objectUrl != null) {
        predefineObject = true;
      } else {
        predefineObject = false;
      }

      // set the option 1
      if (predefineObject) {
        OpenGraphAction action = OpenGraphAction.Factory.createForPost(mStory.getPath());
        action.setProperty(
            mStory.getStoryObject().getNoun(), objectId != null ? objectId : objectUrl);
        Iterator<String> actionProperties = mStory.getStoryAction().getParams().keySet().iterator();
        while (actionProperties.hasNext()) {
          String property = actionProperties.next();
          action.setProperty(property, mStory.getStoryAction().getParams().get(property));
        }

        // set share dialog
        shareDialog =
            new FacebookDialog.OpenGraphActionDialogBuilder(
                    sessionManager.getActivity(), action, mStory.getStoryObject().getNoun())
                .build();

      } else {
        // set the option 2
        OpenGraphObject object = OpenGraphObject.Factory.createForPost(mStory.getObjectType());
        Iterator<String> objectProperties =
            mStory.getStoryObject().getObjectProperties().keySet().iterator();
        while (objectProperties.hasNext()) {
          String property = objectProperties.next();
          object.setProperty(property, mStory.getStoryObject().getObjectProperties().get(property));
        }

        // set custom object properties
        GraphObject data = mStory.getStoryObject().getData();
        if (data != null) {
          for (Entry<String, Object> property : data.asMap().entrySet()) {
            object.getData().setProperty(property.getKey(), property.getValue());
          }
        }

        OpenGraphAction action = OpenGraphAction.Factory.createForPost(mStory.getPath());
        action.setProperty(mStory.getStoryObject().getNoun(), object);

        // set custom action properties
        Iterator<String> actionProperties = mStory.getStoryAction().getParams().keySet().iterator();
        while (actionProperties.hasNext()) {
          String property = actionProperties.next();
          action.setProperty(property, mStory.getStoryAction().getParams().get(property));
        }

        shareDialog =
            new FacebookDialog.OpenGraphActionDialogBuilder(
                    sessionManager.getActivity(), action, mStory.getStoryObject().getNoun())
                .build();
      }

      PendingCall pendingCall = shareDialog.present();
      sessionManager.trackFacebookDialogPendingCall(
          pendingCall,
          new FacebookDialog.Callback() {

            @Override
            public void onError(PendingCall pendingCall, Exception error, Bundle data) {
              sessionManager.untrackPendingCall();
              Logger.logError(
                  PublishStoryDialogAction.class, "Failed to share by using native dialog", error);
              if ("".equals(error.getMessage())) {
                Logger.logError(
                    PublishStoryDialogAction.class,
                    "Make sure to have 'app_id' meta data value in your manifest",
                    error);
              }
              mOnPublishListener.onFail(
                  "Have you added com.facebook.NativeAppCallContentProvider to your manifest? "
                      + error.getMessage());
            }

            @Override
            public void onComplete(PendingCall pendingCall, Bundle data) {
              sessionManager.untrackPendingCall();
              boolean didComplete = FacebookDialog.getNativeDialogDidComplete(data);
              String postId = FacebookDialog.getNativeDialogPostId(data);
              String completeGesture = FacebookDialog.getNativeDialogCompletionGesture(data);
              if (completeGesture != null) {
                if (completeGesture.equals("post")) {
                  mOnPublishListener.onComplete(postId != null ? postId : "no postId return");
                } else {
                  mOnPublishListener.onFail("Canceled by user");
                }
              } else if (didComplete) {
                mOnPublishListener.onComplete(
                    postId != null
                        ? postId
                        : "published successfully. (post id is not availaible if you are not logged in)");
              } else {
                mOnPublishListener.onFail("Canceled by user");
              }
            }
          });
    } else {
      mOnPublishListener.onFail("Open graph sharing dialog isn't supported");
    }
  }