Jonas Ostergaard
Jonas Ostergaard

Reputation: 319

cordova-plugin-facebook4 post with image error on Android

I'm developing a hybrid app with angular and ionic for iOS and Android and I have come upon an error when posting with an image to facebook. The error only appears when I run the app on an Android device. I am using the cordova-plugin-facebook4 and queries like get friends and login are working correctly.

The code for that specific part:

function makeCallToFacebookWithImage(url){
    console.log("share that to facebook with image");
    var facebookString = "/me/photos?method=post&url="+encodeURI(url)+"&caption="+$scope.comment;
    console.log("facebookString with image: "+facebookString);
    facebookConnectPlugin.getLoginStatus(function(loginStatus){
        // if already loggedIn
        if(loginStatus.status == "connected"){
            facebookConnectPlugin.api(facebookString, ["publish_actions"], function(response){
                // success
                console.log("success "+JSON.stringify(response));
            }, function(response){
                // error
                console.log("error "+JSON.stringify(response));
            });
        }
    }, function(error){
        console.log(error);
    })
}

The console.log of line 4:

facebookString with image: /me/photos?method=post&url=https://firebasestorage.googleapis.com/URL?alt=media&token=4420080a-41d8-4816-bf62-5bfb159d1da5&caption=FBTest

Error message:

error {"errorCode":"100","errorType":"OAuthException","errorMessage":"Invalid parameter","errorUserMessage":"Your photos couldn't be uploaded. Photos should be less than 4 MB and saved as JPG, PNG, GIF or TIFF files.","errorUserTitle":"Can't Read Files"}

As you can see I store the image in a firebase database (I replaced the exact url with URL to not publish it here), the image is already uploaded and compressed before I call the Facebook post function and it is in .jpg format, so the error message of the Facebook post is not accurate or does not help me. Besides that, the exact code works on iOS perfectly fine.

I am searching for a solution to this error for a few hours now, so may someone here can help me out with this issue. Did someone had this issue before and may know a solution?

EDIT:

The console.log with complete URL's:

iOS:

/me/photos?method=post&url=https://firebasestorage.googleapis.com/v0/b/appname-50cd0.appspot.com/o/post%252F-KbyHksSP_EV2MTjvCb5.jpg?alt=media&token=64f43c60-47fa-40b2-b85b-e1e5ae1dea13&caption=Rest

Android:

/me/photos?method=post&url=https://firebasestorage.googleapis.com/v0/b/appname-50cd0.appspot.com/o/post%252F-KbxypBFRqs6eyYNk8ZR.jpg?alt=media&token=4420080a-41d8-4816-bf62-5bfb159d1da5&caption=FB

Obviously different pictures, but the URL structures are the same.

EDIT2:

What I tried so far:

-> same error

I am using a Nexus 5 with Android 6.0.1 as test device, at the moment I don't have the access to another Android device, but I'll try it on a different device as soon as I get one.

EDIT 3:

EDIT 4 SOLVED

finally, the solution is in the comments. It was a bug of cordova-plugin-facebook4 on android devices when you use a download url that contains parameter characters like ? & and =, which firebase storage does.

Upvotes: 4

Views: 662

Answers (1)

Jonas Ostergaard
Jonas Ostergaard

Reputation: 319

SOLVED

after many of hours I found the Problem. The combination of cordova-plugin-facebook4 with an firebase storage does not work on Android, because the encoding inside of the plugin is wrong handled.

Inside of the file cordova-plugin-facebook4/src/android/ConnectPlugin.java there is this function:

private void makeGraphCall() {...}

This function decodes the whole "facebookString" and then sorts its segments by the special character ? & and =. A firebase storage download link does contain parameters for the security token, so at this point the plugin tries to interpret the firebase variables as facebook parameters and cuts the url parameter of the firebase url.

What I did was modifying this part of the function:

for (String query : queries) {
  int splitPoint = query.indexOf("=");
  if (splitPoint > 0) {
    String key = query.substring(0, splitPoint);
    String value = query.substring(splitPoint + 1, query.length());
    params.putString(key, value);
  }
}

to:

for (String query : queries) {
  int splitPoint = query.indexOf("=");
  if (splitPoint > 0) {
    String key = query.substring(0, splitPoint);
    String value = query.substring(splitPoint + 1, query.length());
    if(key.equals("url") || key.equals("caption")){
      value = URLDecoder.decode(value);
    }
    params.putString(key, value);
  }
}

And on the angular part I encoded the part of the original firebase URL which contains parameters, and after that I decoded the whole URL again before passing it to the facebookstring.

My Angular Code Snippet:

function makeCallToFacebookWithImage(url) {
  console.log("share to facebook with image");
  var newURL = url;
  var caption = $scope.comment;
  if (ionic.Platform.isAndroid()) { //prep only neccessary on android
    console.log("Is Android device");
    var index = url.indexOf("%2F"); //firebase link specific encoding for folders
    var leftSide = url.substring(0, index);
    var rightSide = url.substring(index, url.length);
    newURL = leftSide + encodeURIComponent(rightSide);
    caption = encodeURIComponent(caption);
  }
  newURL = encodeURIComponent(newURL);
  var facebookString = "/me/photos?method=post&url=" + newURL + "&caption=" + encodeURIComponent(caption);
...

I am going to contact the developers of the facebook4 plugin about this bug. I hope this helps others who may getting stuck on this specific bug.

Upvotes: 1

Related Questions