標籤

2011年10月11日 星期二

非死不可圖片上傳. Facebook upload photo android example code

話說, 老闆要程式的畫面上傳. 光是 FACEBOOK SDK 就搞了二天才搞清礎, 用官網的方法行不通. 更何況是要上傳畫面... 昨天到現在趕工睡不到2小時.

但是為了"忘記", 還是先PO完成功的程式碼. 不然再改一改我又忘記了

 private Facebook facebook = new Facebook("你申請的APP ID");
上面這句是一開始就要做. 所以在副程式直接呼叫即可. 不必重覆.

-----

   // 授權後進行 POST
  // 紅字部份是取得的授權項目
   facebook.authorize(this, new String[] { "email", "publish_stream",
     "read_stream", "user_photos" }, new DialogListener() {
    @Override
    public void onComplete(Bundle values) {
     Log.d("FACEBOOKCANCEL", "AUTH: " + values.toString());
     Bitmap bmp = BitmapFactory.decodeFile(mScreenshotPath);
// 已拍照的相片是在在 SD 卡上, 所以將 SD 卡內容讀出轉作 bytes[]     ByteArrayOutputStream baos = new ByteArrayOutputStream();
     bmp.compress(Bitmap.CompressFormat.PNG, 100, baos);
     byte[] data = baos.toByteArray();
     postToWall_photos("", "圖片上傳", data);
//呼叫只有這句
    }
    @Override
    public void onFacebookError(FacebookError error) {
     Log.d("FACEBOOKCANCEL", "Error: " + error);
    }
    @Override
    public void onError(DialogError e) {
     Log.d("FACEBOOKCANCEL", "DialogError: " + e);
    }
    @Override
    public void onCancel() {
     Log.d("FACEBOOKCANCEL", "Cancelled");
    }
   });



-----

接下來將下面的程式碼放到最後面 "}" 前

 // 以下為 FACEBOOK 支援 API POST 塗鴉牆 開始
 @Override
 public void onActivityResult(int requestCode, int resultCode, Intent data) {
  super.onActivityResult(requestCode, resultCode, data);
  facebook.authorizeCallback(requestCode, resultCode, data);
 }
 public void postToWall(String messageString) {
  Bundle params = new Bundle();
  params.putString("message", messageString);
  try {
   facebook.request("/me/feed", params, "POST");
  } catch (FileNotFoundException e1) {
   // TODO Auto-generated catch block
   e1.printStackTrace();
  } catch (MalformedURLException e1) {
   // TODO Auto-generated catch block
   e1.printStackTrace();
  } catch (IOException e1) {
   // TODO Auto-generated catch block
   e1.printStackTrace();
  }

// 這功能 100% 在塗鴉牆上寫字. 最沒問題 }

 public void postToWall_photos(String AlbumID, String message, byte[] buffer) {
// 這個功能經修正很多次, 我也忘了那邊才是原始值. 但確定能用了
  Bundle params = new Bundle();
  Log.d("FACEBOOKCANCEL", "PostToWall_Photo run");
  try {
   params.putString("method", "photos.upload");
   //params.putString("message", " message 到底在那出現啦~ 找不到相片說明, 怎麼寫下去");
   //params.putString("title", "風水大師: 這是個圖片說明測試!"); 

  // 上面的參數經實驗沒效   params.putString("caption", "message 到底在那出現啦~ 找不到相片說明, 怎麼寫下去");
//PO 上去後. 只有這句能顯示出來. 在相片的下方, 類似是自動留言.   //params.putString("privacy", "{'value':'EVERYONE'}");
// 相片公開參數經實驗也沒用.
   params.putByteArray("picture", buffer);
  } catch (Exception e) {
   Log.d("FACEBOOKCANCEL", "Error: " + e);
   e.printStackTrace();
  }
   //facebook.request("me/photos", params, "POST");
   // AsyncFacebookRunner mAsyncRunner = new
   // AsyncFacebookRunner(facebook);
   // mAsyncRunner.request(null, params, "POST", new
   // SampleUploadListener(), null

// 上面的部份是經N次實驗, 都證明只能 PO 文字, 不能PO 相片. 會出現 TIMEOUT!
// 也許和各別相機的相素大小有關
            AsyncFacebookRunner mAsyncRunner = new AsyncFacebookRunner(facebook);
            mAsyncRunner.request(null, params, "POST", new SampleUploadListener(), null);

// 經實驗, 只有設成背景多執行緒的方式. 相片才會出現. 不然, 即使苦等了5小時. 仍然看不到任何相片被上傳.
  
  
 }
 public class SampleUploadListener extends BaseRequestListener {
  public void onComplete(final String response, final Object state) {
   try {
    // process the response here: (executed in background thread)
    Log.d("Facebook-Example", "Response: " + response.toString());
    JSONObject json = Util.parseJson(response);
    final String src = json.getString("src");

    // then post the processed result back to the UI thread
    // if we do not do this, an runtime exception will be generated
    // e.g. "CalledFromWrongThreadException: Only the original
    // thread that created a view hierarchy can touch its views."

   } catch (JSONException e) {
    Log.w("Facebook-Example", "JSON Error in response");
   } catch (FacebookError e) {
    Log.w("Facebook-Example", "Facebook Error: " + e.getMessage());
   }
  }

  public void onFacebookError(FacebookError e, Object state) {
   // TODO Auto-generated method stub

  }
 }


// 這是傳說當中消失的 CLASS. 在原SDK EXAMPLE 中找到.

 public abstract class BaseRequestListener implements RequestListener {
  public void onFacebookError(FacebookError e, final Object state) {
   Log.e("Facebook", e.getMessage());
   e.printStackTrace();
  }

  public void onFileNotFoundException(FileNotFoundException e,
    final Object state) {
   Log.e("Facebook", e.getMessage());
   e.printStackTrace();
  }

  public void onIOException(IOException e, final Object state) {
   Log.e("Facebook", e.getMessage());
   e.printStackTrace();
  }

  public void onMalformedURLException(MalformedURLException e,
    final Object state) {
   Log.e("Facebook", e.getMessage());
   e.printStackTrace();
  }
 }


// 這也是傳說當中, 消失的程式碼, 最後在 FACEBOOK SDK EXAMPLE 找出來.
 // 以下為 FACEBOOK 支援 API POST 塗鴉牆 結束

8 則留言:

  1. 我測試了一下><
    一直無法成功~不知道大大有沒有簡單的實例
    我的路徑是uri

    回覆刪除
  2. 呵呵, 那也要說一下您的失敗在那邊. 不然連幫的機會都沒有. 您該不會叫我將 SOURCE CODE 全給吧

    回覆刪除
  3. 先問一下~~為什麼模擬器發佈文字訊息都是成功的~
    但是在手機裡發部不出去> < .....


    helper1 = new SQLiteDB(this);
    findViews();
    showViews(savedInstanceState);
    Cursor cursor = helper1.get3(mRowId);
    startManagingCursor(cursor);

    msgText = (TextView)findViewById(R.id.diary_share);
    String Diarydate = cursor.getString(1);
    String Diarytitle = cursor.getString(2);
    String Diarymain = cursor.getString(3);
    msgText.setText(Diarydate + '\n' + Diarytitle + '\n' + Diarymain);
    message = msgText.getText().toString();

    //publish_stream 登入
    facebook.authorize(this, new String[] { "email","publish_stream", "read_stream","user_photos" }, new DialogListener() {
    @Override
    public void onComplete(Bundle values) {
    postToWall(message);//開啟貼到塗鴉牆
    }
    @Override
    public void onFacebookError(FacebookError error) {}

    @Override
    public void onError(DialogError e) {}

    @Override
    public void onCancel() {}

    }
    );
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    facebook.authorizeCallback(requestCode, resultCode, data);
    }

    public void postToWall(String messageString) {
    Bundle params = new Bundle();
    params.putString("message", messageString );
    try {
    facebook.request("/me/feed", params, "POST");
    } catch (FileNotFoundException e1) {
    // TODO Auto-generated catch block
    e1.printStackTrace();
    } catch (MalformedURLException e1) {
    // TODO Auto-generated catch block
    e1.printStackTrace();
    } catch (IOException e1) {
    // TODO Auto-generated catch block
    e1.printStackTrace();
    }

    Toast.makeText(this, "分享成功!", Toast.LENGTH_SHORT).show();

    Intent intent = new Intent();
    intent.setClass(Diary_Share.this, Diary.class);
    startActivity(intent);
    Diary_Share.this.finish();
    }

    private void showViews(Bundle savedInstanceState) {
    if (mRowId == null) {
    Bundle extras = getIntent().getExtras();
    mRowId = extras != null ? extras.getLong(UserSchema3.ID) : null;
    }
    }

    private void findViews() {
    msgText = (TextView)findViewById(R.id.diary_share);
    populateFields();
    }

    private void populateFields() {
    if (mRowId != null) {
    helper1 = new SQLiteDB(this);;
    cursor = helper1.get3(mRowId);
    startManagingCursor(cursor);
    String Diarydate = cursor.getString(1);
    String Diarytitle = cursor.getString(2);
    String Diarymain = cursor.getString(3);
    msgText.setText(Diarydate+'\n'+Diarytitle+'\n'+Diarymain);
    message = msgText.getText().toString();
    }
    }

    回覆刪除
  4. 模擬器是用內建的 key 正式發行時要改key 您要確認facebook 上的與程式的key相同 才能用 否則肯定失敗的

    回覆刪除
  5. 請問一下,我和樓上那位大大是一樣的問題。
    就是用模擬器執行的時候,都可以正常運作,但是插上傳輸線之後,要在實機上測試
    按eclipse上的綠色箭頭按鈕,就是發不出去,這是為什麼呢?

    這個時候應該還不算是正式發行,是嗎?只是移到實機上測試而以,但是就是發不出
    去呢~在模擬器上都可以的呀!

    麻煩大大,指點一下,感激不盡。

    回覆刪除
  6. eclipse上的綠色箭頭按鈕 您必須要先行設定才能使用.

    我也是很懶的設. 所以我的做法是. 在專案上按右鍵

    Run As -> Android Application

    系統會出現目前可執行的列表. 指定在手機上執行即可.

    手機上執行時, 您的 KEY 仍然必須是註冊在 FACEBOOK API 所使用的 KEY. 否則是連不上去的.

    回覆刪除
  7. 你好,想請問一下,我這邊可以放訊息到塗鴉牆,卻一直沒有辦法上傳圖片,DDMS似乎出現這樣的錯誤訊息:
    Failed to find provider info for com.facebook.katana.provider.AttributionIdProvider
    不知道這是不是就是我無法上傳的主因,想問問看你有沒有什麼建議?

    回覆刪除