網頁

2011年9月22日 星期四

Android學習_使用facebook sdk_Part3上傳照片

1. 完成開發facebook相關APP的準備工作
2. 將"文字訊息"貼上塗鴉牆

大部分開發者下一步就是希望可以上傳圖片。

可以先看一下之前傳文字到塗鴉牆的語法:

facebook.request("/me/feed", params, "POST");

第一個參數是要傳到的位置(/me/feed代表塗鴉牆)
第二個參數是傳遞的內容(使用putString方法放入)
第三個參數是傳遞的方法

好,由這邊可以知道要上傳圖片勢必要先找到放置的位置與傳遞的內容;而圖片的放置位置對於facebook來說就是"相簿",而在網路上傳遞圖片的內容當然就是Stream一類。

所以我們要找到上傳的位置,與將圖片塞入params(Bundle)的方法:
1. 上傳位置:如果你去開啟facebook的相簿,可以發現每一本相簿都有一個唯一的ID,而在facebook sdk裡面也當然就是以這個ID作為辨識的方式,所以位置是"/相簿ID/photos"。(相簿ID為15碼)
2. 傳遞內容:在Bundle裡面可以利用putByteArray將類似圖片的內容傳遞出去,所以不管我們要上傳的圖片來自於哪裡,都必須先將該圖片轉為byte[]的格式,再利用params.putByteArray("picture", buffer);的語法加入。

有了以上的各項資訊以後,我們還是不能把圖片正確的上傳,這是因為若是要上傳資訊到facebook就必須要有足夠的權限(當時貼上塗鴉牆的權限為publish_stream),而上傳圖片的權限為user_photos。

程式碼:
1. 加入適當的權限

private void facebookSetting(){
facebook.authorize(this, new String[] { "email","publish_stream", "read_stream","user_photos" },

new DialogListener() {
@Override
public void onComplete(Bundle values) {}

@Override
public void onFacebookError(FacebookError error) {}

@Override
public void onError(DialogError e) {}

@Override
public void onCancel() {}
}
);
}

2. 上傳圖片

public void postToWall_photos(String AlbumID ,String message , byte[] buffer) {
Bundle params = new Bundle();
params.putString("message", message);
try {
params.putByteArray("picture", buffer);
} catch (Exception e) {
e.printStackTrace();
}

try {
facebook.request("/" + AlbumID + "/photos", params, "POST");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

*注意:文字訊息規定於putString時,第一個參數帶"message";而圖片使用putByteArray的時候第一個參數帶"picture"。

*提醒:圖片不管是手機內的資源(uri),即時畫出來的圖片(Bitmap)或是一個Stream類的東西,都必須先轉換成byte[],才符合上傳的的格式。

*將uri轉byte[]請參考

如果因為本篇完成上傳圖片,請留:WOW!有圖有真相。

46 則留言:

  1. 你的教材很好。但我要怎樣才能將圖片轉為byte?

    回覆刪除
  2. WOW!有圖有真相。

    版大真的太棒了!!!!

    回覆刪除
  3. 板大讚哦~~對於一個初心者也是略懂了~

    回覆刪除
  4. 如何把圖片轉成byte的格式,要看你的來源從哪裡來,如果先利用照相機取得,那你就是要去查資源目標(uri)轉byte的語法;但也有可能你的圖是從手機上擷取的(比如說擷取google map),那你有可能取得的是Bitmap;或是你可能是網路環境取得的一個stream。

    所以應該是要視你手上的格式,來查要怎麼轉byte,而沒有一個通用的轉法。

    回覆刪除
  5. 你好。若果我想用機內Folder的圖片,應怎樣轉?

    回覆刪除
  6. 還有我可不可直接post 在wall 上?

    回覆刪除
  7. 從手機照片轉換,也就是以uri轉byte[]請參考http://wangshifuola.blogspot.com/2011/09/androiduribyte.html

    利用上述方法上傳照片,將會在塗鴉牆上顯示。

    回覆刪除
  8. WOW!有圖有真相。
    無限感激

    回覆刪除
  9. 我發現只有第一次會出現在塗鴉牆
    第二次開始都不會出現在塗鴉牆
    不過在相簿裡面還是看得到自己剛剛上傳的照片
    是否真的有這bug@@?

    回覆刪除
  10. 我記得測試時也發生過相同的狀況,這"好像"與相簿的隱私權設定有關,fb可能認為該相簿為不公開分享的相簿,所以當相簿新增照片後並不會顯示在塗鴉牆上,而在其他論壇的討論似乎也有碰到類似的問題,你可能可以重建一個新的相簿來進行測試。

    目前回憶起來,唯一的差別"好像是"改為利用sdk建立相簿後,就沒有碰到這個的問題;所以我不確定利用既有相簿或利用sdk建立相簿是否會對於android sdk上傳照片有影響。

    回覆刪除
  11. 你好。我想問fb.logut(context) context 那處應該輸入什麼?

    回覆刪除
  12. 那要如何利用sdk建立相簿呢@@?

    回覆刪除
  13. 你好。mAsyncRunner.logout(getContext(), new LogoutRequestListener()); 的RequestListener是什麼?

    謝謝

    回覆刪除
  14. 建立相簿的程式碼:
    params參數帶message與name

    利用facebook.request("/me/albums", params, "POST")建立。

    回覆刪除
  15. fb.logut的相關用法我沒有進行測試,你可能要查官方說明文件。

    回覆刪除
  16. 請問如果我要貼一個網址 (String)

    但是我想讓他有預覽縮圖效果
    (直接用電腦去貼網址的話 他會先載入網址 會跑出縮圖)

    有辦法能做到嗎?

    回覆刪除
  17. 那就要查facebook所提供的sdk中,於貼網址的部分能不能附加圖片了,這部分我就沒有進行測試了。

    回覆刪除
  18. WOW!有圖有真相。
    版大好厲害

    回覆刪除
  19. 想請問一下 相簿的ID要怎麼取得

    回覆刪除
  20. 取得相簿ID:facebook.request("me/albums"),返回是相簿列表,就可以進行比對了。

    回覆刪除
  21. 您好 感謝您的分享 我成功分享相簿了~
    但是我要怎麼控制相片下面的相片敘述呢?
    因為我用edittext去抓取裡面的string然後再用putstring
    但是一直抓不到
    所以我想我是不寫錯地方了~

    可以告訴我正確的地方嗎 謝謝你!!:D

    回覆刪除
  22. 請問這篇code

    除了上傳照片外

    message的文字也會被貼在照片下嗎

    因為我做出來只有照片上傳並發布 message內容沒有在照片下面

    還是要用其他的格式 不能用message? 感謝

    回覆刪除
  23. 程式碼裡面的params.putString("message", message);就是指相片下的說明文字。

    第一個"message"為fb指定的參數。
    第二個message為要傳上去的文字內容(String型態)。

    →params.putString("message", "要傳的內容");

    回覆刪除
  24. 您好 感謝你的教學文 不過關於取得相簿ID我有點不懂

    我已經可以貼照片跟建立相簿了

    但是不知道該怎麼把照片貼到指定相簿

    假設我發出

    String AlbumID = 1129;
    // 這行是建立相簿
    facebook.request("/me/albums/"+AlbumID, params, "POST");

    // 發布相片的前面該怎麼取得ID呢?
    facebook.request("/" + AlbumID + "/photos", params, "POST");

    回覆刪除
  25. 比如說你要上傳的相簿名稱叫做'匿名的fb程式'

    利用facebook.request("me/albums")取得相簿的列表(json格式),接下來去比對相簿名稱=匿名的fb程式,

    如果有比對到就取得相簿ID,
    如果比對不到就建立相簿,再取得ID。

    先看一下facebook.request("me/albums")取得的列表應該就可以很清楚。

    GOOD LUCK

    回覆刪除
  26. 上述說的"取ID"是表示拆解JSON。

    回覆刪除
  27. 又打攪了。我發現安裝了Facebook 專用app 後,用上面的code就post不到相到wall 裡。如何解決這問題?

    回覆刪除
  28. ola 您好
    我有一個問題想要問您
    我想抓取上傳圖片後的url
    而非相簿的ID
    請問該用哪個方法

    回覆刪除
  29. Facebook 專用app指的是facebook自己出的嗎?我一值都有使用這個App耶,並沒有發生不能post照片的問題。

    你可以測試一下改傳到別的相簿,或是建立一個新的相簿試試看,之前曾經有查到有時候會因為相簿的權限因為'某些狀況'被改變,導致沒辦法在塗鴉牆上顯示。

    回覆刪除
  30. 抓取照片的url這個我沒有測試過,要比較有空的時候才能測,金拍謝。

    回覆刪除
  31. ola沒關係
    謝謝你:D

    回覆刪除
  32. 你好!!
    要怎樣按按鈕之後上傳?
    一樣也是用
    //按鈕
    vh3.setOnClickListener(new Button.OnClickListener(){

    @Override
    public void onClick(View v) {
    postToWall(message);
    }
    });

    回覆刪除
  33. 要按下按鈕才進行上傳,只要將上傳的程式碼放在ClickListener內的OnClick就可以了。

    回覆刪除
  34. 想請叫大大~~可否有簡單實例可以參考><
    弄了很久都無法上傳照片

    回覆刪除
  35. 這篇就是完整的程式碼了,剩下都是轉byte[]的內容,如何轉請參考:http://wangshifuola.blogspot.com/2011/09/androiduribyte.html

    回覆刪除
  36. 建立相簿的部分我還是不太懂...
    到底要如何建立呢 ?
    感謝 :)

    回覆刪除
  37. 程式碼:
    Bundle params = new Bundle();
    params.putString("message", "OlaAndroid相簿");
    params.putString("name", "OlaAndroid相簿");

    JSONObject json = new JSONObject(facebook.request("/me/albums", params, "POST"));

    String AlbumID = json.getString("id");

    -------------------------------------
    利用facebook.request("/me/albums", params, "POST"),你就可以可以建立一個名叫"OlaAndroid相簿"的fb相簿,並且返回一個json,然後拆解後取得的相簿id(變數AlbumID )。

    所以通常的方式是:
    1. 先去抓相簿列表。
    2. 比對相簿名稱。
    3. 有該相簿就取得id,沒有就建立並取得id。

    其實上面的留言內容就有了,good luck。

    回覆刪除
  38. 我這邊都沒辦法把圖丟上去,FB他不理我就是不理我,可以幫我看一下嗎?
    package com.FB;

    import java.io.*;
    import java.net.MalformedURLException;

    import android.app.Activity;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.os.Bundle;
    import android.util.Log;
    import android.os.Debug;
    import com.facebook.android.*;
    import com.facebook.android.AsyncFacebookRunner.RequestListener;
    import com.facebook.android.Facebook.DialogListener;

    public class FBActivity extends Activity {
    private Facebook facebook = new Facebook("ID");
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    facebook.authorize( this, new String[] { "email", "read_stream", "publish_stream", "create_event", "user_photos" }, new DialogListener(){
    @Override
    public void onComplete(Bundle values) {
    // TODO Auto-generated method stub
    }
    @Override
    public void onFacebookError(FacebookError e) {
    // TODO Auto-generated method stub
    }
    @Override
    public void onError(DialogError e) {
    // TODO Auto-generated method stub
    }
    @Override
    public void onCancel() {
    // TODO Auto-generated method stub
    }
    });
    byte[] data = null;
    Debug.startMethodTracing("report");
    try {
    FileInputStream fis = new FileInputStream("/sdcard/test.jpg");
    Bitmap bi = BitmapFactory.decodeStream(fis);
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    bi.compress(Bitmap.CompressFormat.JPEG, 100, baos);
    data = baos.toByteArray();
    } catch (FileNotFoundException e) {
    e.printStackTrace();
    Log.d("onCreate", "debug error e = " + e.toString());
    }
    Debug.stopMethodTracing();

    Bundle params = new Bundle();
    params.putString("message", "Upload");
    try {
    params.putByteArray("picture", data);
    } catch (Exception e) {
    e.printStackTrace();
    }

    try {
    facebook.request("/me/feed", params, "POST");
    } catch (FileNotFoundException e) {
    e.printStackTrace();
    } catch (MalformedURLException e) {
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }

    回覆刪除
  39. 我不確定你錯在哪裡,但你可以試試看把照片丟進相簿裡面。

    facebook.request("/" + AlbumID + "/photos", params, "POST");

    回覆刪除
  40. 版大:
    請問是否有能
    上傳圖片又能打文字的程式碼呢
    現在只能 PO文字
    圖片怎弄都弄不上去
    希望有完整的程式碼

    回覆刪除
  41. 一併將圖片跟文字送出就可以達成了。

    程式碼裡面的params.putString("message", message);就是指相片下的說明文字。

    第一個"message"為fb指定的參數。
    第二個message為要傳上去的文字內容(String型態)。

    →params.putString("message", "要傳的內容");

    回覆刪除
  42. 請問版大有信箱
    我想寄我的程式碼
    給你解答

    回覆刪除
  43. 版大請問一下,因為上傳圖片需要等待
    如何以執行緒顯示等待的畫面呢?
    例如:dialog =ProgressDialog.show(WAITActivity.this,
    "", "上傳中...",true);

    回覆刪除
  44. 將上傳圖片的程式碼放在一個thread執行,然後開啟ProgressDialog之類的等待畫面(或是不開啟,仍然讓使用者作其他操作),等到上傳完成後再於該thread傳Message到Handler來通知使用者上傳完成。

    可以參考:http://wangshifuola.blogspot.tw/2010/11/androidthread.html

    http://wangshifuola.blogspot.tw/2011/06/androidthreadmessagehandler.html

    回覆刪除
  45. 您好,想請問一下我用以下的方法去取得album list,但是似乎只能取得前25本album,請問有解決方法嗎?
    response = facebook.request("me/albums");
    json = Util.parseJson(response);
    albums = json.getJSONArray("data");
    for (int i =0; i < albums.length(); i++) {
    JSONObject album = albums.getJSONObject(i);
    String album_name = album.getString("name");
    String album_id = album.getString("id");
    Log.i("Tracy","album id: "+album_name+" = "+album_id);
    }

    回覆刪除
  46. 不好意思,這個問題我就不清楚了,沒有測試過超過25本以上的FB帳號。

    回覆刪除