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 則留言:

Tom Tong 提到...

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

匿名 提到...

WOW!有圖有真相。

版大真的太棒了!!!!

匿名 提到...

板大讚哦~~對於一個初心者也是略懂了~

ola的家 提到...

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

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

Tom Tong 提到...

你好。若果我想用機內Folder的圖片,應怎樣轉?

Tom Tong 提到...

還有我可不可直接post 在wall 上?

ola的家 提到...

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

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

Tom Tong 提到...

WOW!有圖有真相。
無限感激

阿槌 提到...

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

ola的家 提到...

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

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

Tom Tong 提到...

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

阿槌 提到...

那要如何利用sdk建立相簿呢@@?

Tom Tong 提到...

你好。mAsyncRunner.logout(getContext(), new LogoutRequestListener()); 的RequestListener是什麼?

謝謝

ola的家 提到...

建立相簿的程式碼:
params參數帶message與name

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

ola的家 提到...

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

匿名 提到...

請問如果我要貼一個網址 (String)

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

有辦法能做到嗎?

ola的家 提到...

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

匿名 提到...

WOW!有圖有真相。
版大好厲害

匿名 提到...

想請問一下 相簿的ID要怎麼取得

ola的家 提到...

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

yazu 提到...

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

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

匿名 提到...

請問這篇code

除了上傳照片外

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

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

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

ola的家 提到...

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

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

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

匿名 提到...

您好 感謝你的教學文 不過關於取得相簿ID我有點不懂

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

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

假設我發出

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

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

ola的家 提到...

比如說你要上傳的相簿名稱叫做'匿名的fb程式'

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

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

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

GOOD LUCK

ola的家 提到...

上述說的"取ID"是表示拆解JSON。

Tom Tong 提到...

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

匿名 提到...

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

ola的家 提到...

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

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

ola的家 提到...

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

匿名 提到...

ola沒關係
謝謝你:D

匿名 提到...

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

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

ola的家 提到...

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

匿名 提到...

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

ola的家 提到...

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

匿名 提到...

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

ola的家 提到...

程式碼:
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。

匿名 提到...

我這邊都沒辦法把圖丟上去,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();
}
}
}

ola的家 提到...

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

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

匿名 提到...

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

ola的家 提到...

一併將圖片跟文字送出就可以達成了。

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

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

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

匿名 提到...

請問版大有信箱
我想寄我的程式碼
給你解答

匿名 提到...

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

ola的家 提到...

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

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

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

王切西 提到...

您好,想請問一下我用以下的方法去取得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);
}

ola的家 提到...

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

張貼留言