0

Hey there I know a lot of people have asked this question but none of them could help me, this what I want is how to make a button onclick have to start a photo chooser and upload the chosen picture into facebook ?

Iam really stuck and none of the answers could help me. I have a code that it sending text and its working fine. But now I want to upload picture too, so how I can make it? Anyone can help me?

best regards

UPDATE --> This is what I have to post

public class TestPost extends Activity{
private Facebook mFacebook;
private CheckBox mFacebookCb;
private ProgressDialog mProgress;

private Handler mRunOnUi = new Handler();

private static final String APP_ID = "app id here";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.post);

    final EditText reviewEdit = (EditText) findViewById(R.id.revieew);
    mFacebookCb               = (CheckBox) findViewById(R.id.cb_facebook);

    mProgress   = new ProgressDialog(this);

    mFacebook   = new Facebook(APP_ID);

    SessionStore.restore(mFacebook, this);

    if (mFacebook.isSessionValid()) {
        mFacebookCb.setChecked(true);

        String name = SessionStore.getName(this);
        name        = (name.equals("")) ? "Unknown" : name;

        mFacebookCb.setText("  Facebook  (" + name + ")");
    }

    ((Button) findViewById(R.id.button1)).setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            String review = reviewEdit.getText().toString();

            if (review.equals("")) return;

            if (mFacebookCb.isChecked()) postToFacebook(review);
        }
    });
  private void postToFacebook(String review) {  
    mProgress.setMessage("Posting ...");
    mProgress.show();

    AsyncFacebookRunner mAsyncFbRunner = new AsyncFacebookRunner(mFacebook);

    Bundle params = new Bundle();

    params.putString("message", review);
    params.putString("name", "Dexter");
    params.putString("caption", "londatiga.net");
    params.putString("link", "http://www.londatiga.net");
    params.putString("description", "Dexter, seven years old dachshund who loves to catch cats, eat carrot and krupuk");
    params.putString("picture", "http://twitpic.com/show/thumb/6hqd44");

    mAsyncFbRunner.request("me/feed", params, "POST", new WallPostListener());
}

private final class WallPostListener extends BaseRequestListener {
    public void onComplete(final String response) {
        mRunOnUi.post(new Runnable() {
            @Override
            public void run() {
                mProgress.cancel();

                Toast.makeText(TestPost.this, "Posted to Facebook", Toast.LENGTH_SHORT).show();
            }
        });
    }

} }

Update 2 --> logcat and the error apper

    04-30 12:45:02.471: W/Bundle(29461): Key method expected byte[] but value was a java.lang.String.  The default value <null> was returned.
    04-30 12:45:02.476: W/Bundle(29461): Attempt to cast generated internal exception:
    04-30 12:45:02.476: W/Bundle(29461): java.lang.ClassCastException: java.lang.String
    04-30 12:45:02.476: W/Bundle(29461):    at android.os.Bundle.getByteArray(Bundle.java:1305)
    04-30 12:45:02.476: W/Bundle(29461):    at com.facebook.android.Util.openUrl(Util.java:155)
    04-30 12:45:02.476: W/Bundle(29461):    at com.facebook.android.Facebook.request(Facebook.java:559)
    04-30 12:45:02.476: W/Bundle(29461):    at com.facebook.android.AsyncFacebookRunner$2.run(AsyncFacebookRunner.java:208)
    04-30 12:45:02.476: W/Bundle(29461): Key format expected byte[] but value was a java.lang.String.  The default value <null> was returned.
    04-30 12:45:02.476: W/Bundle(29461): Attempt to cast generated internal exception:
    04-30 12:45:02.476: W/Bundle(29461): java.lang.ClassCastException: java.lang.String
    04-30 12:45:02.476: W/Bundle(29461):    at android.os.Bundle.getByteArray(Bundle.java:1305)
    04-30 12:45:02.476: W/Bundle(29461):    at com.facebook.android.Util.openUrl(Util.java:155)
    04-30 12:45:02.476: W/Bundle(29461):    at com.facebook.android.Facebook.request(Facebook.java:559)
    04-30 12:45:02.476: W/Bundle(29461):    at com.facebook.android.AsyncFacebookRunner$2.run(AsyncFacebookRunner.java:208)
    04-30 12:45:02.476: W/dalvikvm(29461): threadid=10: thread exiting with uncaught exception (group=0x4001e578)
    04-30 12:45:02.476: E/AndroidRuntime(29461): FATAL EXCEPTION: Thread-11
    04-30 12:45:02.476: E/AndroidRuntime(29461): java.lang.NullPointerException
    04-30 12:45:02.476: E/AndroidRuntime(29461):    at java.net.URLDecoder.decode(URLDecoder.java:104)
    04-30 12:45:02.476: E/AndroidRuntime(29461):    at java.net.URLDecoder.decode(URLDecoder.java:48)
    04-30 12:45:02.476: E/AndroidRuntime(29461):    at com.facebook.android.Util.openUrl(Util.java:167)
    04-30 12:45:02.476: E/AndroidRuntime(29461):    at com.facebook.android.Facebook.request(Facebook.java:559)
    04-30 12:45:02.476: E/AndroidRuntime(29461):    at com.facebook.android.AsyncFacebookRunner$2.run(AsyncFacebookRunner.java:208)

*This is the call *

    ((Button) findViewById(R.id.upload)).setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            try{
            selectImage();
                    } 
            catch (Exception e) {
                    Toast toast = Toast.makeText(TestPost.this, "Unable to retrieve the selected image.", Toast.LENGTH_LONG);
                    toast.show();
                } finally {   
                }
            }
    });
    }

Here is // TODO: upload to Facebook albums

private void uploadImageBytes(byte[] bytes) {
    // TODO: upload to Facebook albums

          Bundle params = new Bundle();
          params.putString(Facebook.TOKEN, mFacebook.getAccessToken());
          params.putString("method", "photos.upload");
          params.putByteArray("picture", bytes);

          AsyncFacebookRunner mAsyncRunner = new AsyncFacebookRunner(mFacebook);
          mAsyncRunner.request(null, params, "POST", new WallPostListener());
}

Solution Thx to #vorrtex with the answered question belowed he explained me the issue with his code I got it to work. here is full code for others if they will need it in future

A button calls the method

   ((Button) findViewById(R.id.upload)).setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            try{
            selectImage();
                    } 
            catch (Exception e) {
                    Toast toast = Toast.makeText(TestPost.this, "Unable to retrieve the selected image.", Toast.LENGTH_LONG);
                    toast.show();
                } finally {   
                }
            }
    });

And here the method and stream codes. The code is from the answered question

    private void selectImage() {

    Intent i = new Intent(Intent.ACTION_GET_CONTENT);
    i.setType("image/*");
    this.startActivityForResult(i, REQUEST_CODE_GALLERY);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (resultCode == RESULT_OK) {
        switch (requestCode) {
            case REQUEST_CODE_GALLERY:

                Uri selectedImage = data.getData();
                String filePath = null;

                String[] columns = { MediaColumns.DATA };
                Cursor cursor = this.getContentResolver().query(selectedImage, columns, null, null, null);
                if (cursor != null) {
                    cursor.moveToFirst();

                    int columnIndex = cursor.getColumnIndex(columns[0]);
                    filePath = cursor.getString(columnIndex);

                    if (!cursor.isClosed()) {
                        cursor.close();
                    }
                } else {
                    filePath = selectedImage.getPath();
                }

                if (filePath != null) {
                    this.uploadImagePath(filePath);
                } else {
                    Toast toast = Toast.makeText(this, "Unable to retrieve the selected image.", Toast.LENGTH_LONG);
                    toast.show();
                }

                break;
        }
    }
}

private void uploadImagePath(String filePath) {
    FileInputStream fileStream = null;
    try {
        fileStream = new FileInputStream(new File(filePath));
        byte[] bytes = convertStreamToBytes(fileStream);
        this.uploadImageBytes(bytes);
        placering = filePath; 
    } catch (Exception e) {
        Toast toast = Toast.makeText(this, "Unable to retrieve the selected image.", Toast.LENGTH_LONG);
        toast.show();
    } finally {
        closeStream(fileStream);
    }
}

private void uploadImageBytes(byte[] bytes) {
    // TODO: upload to Facebook albums

    Bundle params = new Bundle();
    params.putString(Facebook.TOKEN, mFacebook.getAccessToken());
    params.putString("method", "photos.upload");
    params.putByteArray("picture", bytes);

    AsyncFacebookRunner mAsyncRunner = new AsyncFacebookRunner(mFacebook);
    mAsyncRunner.request(null, params, "POST", new WallPostListener());
}


public static byte[] convertStreamToBytes(InputStream stream) throws IOException {
    if (stream == null) {
        return null;
    }

    ByteArrayOutputStream output = new ByteArrayOutputStream();

    copyStream(stream, output);

    return output.toByteArray();
}

public static void copyStream(InputStream from, OutputStream to) throws IOException {
    byte data[] = new byte[8192];
    int count;

    while ((count = from.read(data)) != -1) {
        to.write(data, 0, count);
    }

    from.close();
}

public static void closeStream(Closeable stream) {
    try {
        if (stream != null) {
            stream.close();
        }
    } catch (Exception e) {

    }
}
Tirolel
  • 928
  • 3
  • 17
  • 43
  • I have updated the question, I tried to follow some answers here on stackoverflow but most of them is like with given path but I want the user to choose the image to post – Tirolel Apr 29 '13 at 17:23

1 Answers1

1

Here are answers how to start a photo chooser: How to pick an image from gallery (SD Card) for my app?

Then you should upload the selected image to a Facebook album (/me/photos). You have to do this because me/feed accepts only URL strings, not binary images, so you upload your image so that you have a URL string to it.

Here is an answer how to do this: Android - Upload photo to Facebook with Facebook Android SDK. You should replace '/sdcard/viewitems.png' by the file path chosen from gallery.

Then you can post the link to the uploaded image:

// the onComplete method from the previous link
final String src = json.getString("src");

// ... create params ...
params.putString("picture", src);

mAsyncFbRunner.request("me/feed", params, "POST", new WallPostListener());

Edit: By the way, answers from the first link are not complete and aren't good, so here is the full code how to select an image from gallery and convert it to bytes:

private void selectImage() {
    Intent i = new Intent(Intent.ACTION_GET_CONTENT);
    i.setType("image/*");
    this.startActivityForResult(i, Constants.REQUEST_CODE_GALLERY);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (resultCode == RESULT_OK) {
        switch (requestCode) {
            case Constants.REQUEST_CODE_GALLERY:

                Uri selectedImage = data.getData();
                String filePath = null;

                String[] columns = { MediaColumns.DATA };
                Cursor cursor = this.getContentResolver().query(selectedImage, columns, null, null, null);
                if (cursor != null) {
                    cursor.moveToFirst();

                    int columnIndex = cursor.getColumnIndex(columns[0]);
                    filePath = cursor.getString(columnIndex);

                    if (!cursor.isClosed()) {
                        cursor.close();
                    }
                } else {
                    filePath = selectedImage.getPath();
                }

                if (filePath != null) {
                    this.uploadImagePath(filePath);
                } else {
                    Toast toast = Toast.makeText(this, "Unable to retrieve the selected image.", Toast.LENGTH_LONG);
                    toast.show();
                }

                break;
        }
    }
}

private void uploadImagePath(String filePath) {
    FileInputStream fileStream = null;
    try {
        fileStream = new FileInputStream(new File(filePath));
        byte[] bytes = convertStreamToBytes(fileStream);
        this.uploadImageBytes(bytes);
    } catch (Exception e) {
        Toast toast = Toast.makeText(this, "Unable to retrieve the selected image.", Toast.LENGTH_LONG);
        toast.show();
    } finally {
        closeStream(fileStream);
    }
}

private void uploadImageBytes(byte[] bytes) {
    // TODO: upload to Facebook albums
}

public static byte[] convertStreamToBytes(InputStream stream) throws IOException {
    if (stream == null) {
        return null;
    }

    ByteArrayOutputStream output = new ByteArrayOutputStream();

    copyStream(stream, output);

    return output.toByteArray();
}

public static void copyStream(InputStream from, OutputStream to) throws IOException {
    byte data[] = new byte[8192];
    int count;

    while ((count = from.read(data)) != -1) {
        to.write(data, 0, count);
    }

    from.close();
}

public static void closeStream(Closeable stream) {
    try {
        if (stream != null) {
            stream.close();
        }
    } catch (Exception e) {
        Log.e(TAG, e);
    }
}
Community
  • 1
  • 1
vortexwolf
  • 13,967
  • 2
  • 54
  • 72
  • the links you provide are correct but a bytearray is to be put into the parameters and not just a path. – Pork 'n' Bunny Apr 29 '13 at 18:17
  • @Pork the answer from the second link uses methods like `BitmapFactory.decodeFile` and `data = baos.toByteArray()`, so the path is transformed into a byte array which is used afterwards. – vortexwolf Apr 29 '13 at 18:24
  • I agree. ByteArray should be used and not String. – Pork 'n' Bunny Apr 29 '13 at 18:42
  • Thank you for good explanation. I got the point but iam getting some error @ REQUEST_CODE_GALLERY and image this.uploadImage(filePath) do you know what it Can be? – Tirolel Apr 29 '13 at 19:58
  • @Tiroler Just use any number instead of this constant (3, for example), it should be the same in both `selectImage` and `onActivityResult` methods. And the correct method is `uploadImagePath`, I mistyped. – vortexwolf Apr 30 '13 at 02:56
  • @vorrtex thank you for answering back but I cant still post the chosen picture, I have added the logcat and the method i used. – Tirolel Apr 30 '13 at 10:42
  • @vorrtex I think I have found the error, thank you very much for your help. It really helped me with understand the way to reach a solution – Tirolel Apr 30 '13 at 12:22
  • @Tirolel Good news then. By the way you can update the question and explain what error was. For me your code is correct and shouldn't throw exceptions. – vortexwolf Apr 30 '13 at 12:40
  • @vorrtex yea I did new method for postImage but I saw u had already did that for me and I got the byte into params and sendt it with the listner. it working now, so I will update the question soon as possible for other people. – Tirolel Apr 30 '13 at 19:16