使用Facebook SDK从SD卡上传视频到Facebook是否可行?

13

我们能否通过Facebook SDK将Android设备SD卡上的视频上传到Facebook账户?

如果可以,有哪些简单的示例?

4个回答

25

是的,这是可能的!经过两天的尝试和研究,我成功了。下面是代码:

byte[] data = null;
String dataPath = "/mnt/sdcard/KaraokeVideos/myvideo.3gp";
String dataMsg = "Your video description here.";
Bundle param;
facebook = new Facebook(FB_APP_ID);
AsyncFacebookRunner mAsyncRunner = new AsyncFacebookRunner(facebook);
InputStream is = null;
try {
    is = new FileInputStream(dataPath);
    data = readBytes(is);
    param = new Bundle();
    param.putString("message", dataMsg);
    param.putString("filename", dataName);
    param.putByteArray("video", data);
    mAsyncRunner.request("me/videos", param, "POST", new fbRequestListener(), null);
}
catch (FileNotFoundException e) {
   e.printStackTrace();
}
catch (IOException e) {
   e.printStackTrace();
}

其中fbRequestListener()AsyncFacebookRunner.RequestListener()的实现,而readBytes()是将您的视频文件转换为byte[]的函数。 dataName字符串应包含有效的文件扩展名(3gp,mp4等)。 代码如下:

public byte[] readBytes(InputStream inputStream) throws IOException {
    // This dynamically extends to take the bytes you read.
    ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();

    // This is storage overwritten on each iteration with bytes.
    int bufferSize = 1024;
    byte[] buffer = new byte[bufferSize];

    // We need to know how may bytes were read to write them to the byteBuffer.
    int len = 0;
    while ((len = inputStream.read(buffer)) != -1) {
        byteBuffer.write(buffer, 0, len);
    }

    // And then we can return your byte array.
    return byteBuffer.toByteArray();
}

我从这个答案中得到了这个函数。

当然,你需要拥有最新的Facebook SDK,但我们需要应用这个补丁来修复{"error":{"type":"OAuthException","message":"(#352) Video file format is not supported"}}字符串响应错误。

就是这样了!希望能对你有所帮助!


你好,我使用了你发布的答案。它运行良好,但是我遇到了这个错误 {"error":{"type":"OAuthException","message":"(#352) Video file format is not supported"}}。你提供了最新的补丁来解决这个错误。所以请告诉我在util类中需要更改哪些代码。 - Ramakrishna
很棒的帖子,加油!Erick和Peter Mortensen - user1025050
1
这段代码可以运行,但是当你发送一个容器为mp4的视频时它就无法工作(如果是3gp格式则可以)。在ffmpeg信息中会显示一个moov原子未找到的错误。 - Yekmer Simsek
1
@Erick 感谢您提供的示例,它可以很好地上传小文件到Facebook,但是当我尝试上传一个大小为95MB的视频文件时,它会抛出java.lang.OutOfMemoryError错误,请问您能否帮助我解决这个问题。提前致谢。 - vinay kumar
我已经尝试了你的代码,但是它返回了“oauthexception code 2500,OAuthException:必须使用活动访问令牌”,你能帮我解决这个错误吗? - Ravi Bhandari
显示剩余6条评论

2
随着新版Facebook SDK 3.5的发布,视频上传变得更加简单。如果您正在使用SDK 3.5或更高版本,以下是上传视频到Facebook所需的代码:
//Path to the video, Ex: path = Environment.getExternalStorageDirectory() + File.separator + "myVideo.mp4";
        String path;
        //get the current active facebook session
        Session session = Session.getActiveSession();
        //If the session is open
        if(session.isOpened()) {
            //Get the list of permissions associated with the session
            List<String> permissions = session.getPermissions();
            //if the session does not have video_upload permission
            if(!permissions.contains("video_upload")) {
                //Get the permission from user to upload the video to facebook
                Session.NewPermissionsRequest newPermissionsRequest = new Session
                        .NewPermissionsRequest(this, Arrays.asList("video_upload"));
                session.requestNewReadPermissions(newPermissionsRequest);
            }


            //Create a new file for the video 
            File file = new File(path);
            try {
                //create a new request to upload video to the facebook
                Request videoRequest = Request.newUploadVideoRequest(session, file, new Request.Callback() {

                    @Override
                    public void onCompleted(Response response) {

                        if(response.getError()==null)
                        {
                            Toast.makeText(MainActivity.this, "video shared successfully", Toast.LENGTH_SHORT).show();
                        }
                        else
                        {
                            Toast.makeText(MainActivity.this, response.getError().getErrorMessage(), Toast.LENGTH_SHORT).show();
                        }
                    }
                });

                //Execute the request in a separate thread
                videoRequest.executeAsync();

            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }

        //Session is not open
        else {
            Toast.makeText(getApplicationContext(), "Please login to facebook first", Toast.LENGTH_SHORT).show();
        }

1
在发布新的Facebook SDK中,上传视频到Facebook页面或墙上发生了一些变化。
这是我用于在Facebook页面或Facebook墙上上传视频的代码。
你的onActivityResult()方法应该像这样。
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if(requestCode == CAMERA_VIDEO && resultCode == Activity.RESULT_OK){
        String selectedVideoFilePath = GetFilePathFromDevice.getPath(this, data.getData());   
        final byte[] datas = readBytes(selectedVideoFilePath);
        PostVideo(datas, selectedVideoFilePath);
    }
}

这里是onActivityResult()中使用的所有方法。

public byte[] readBytes(String dataPath) throws IOException {
        InputStream inputStream = new FileInputStream(dataPath);
        ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len;
        while ((len = inputStream.read(buffer)) != -1) {
            byteBuffer.write(buffer, 0, len);
        }
        return byteBuffer.toByteArray();
 }


public void PostVideo(byte[] VideoBytes, String filePath) {
        String url;
        url = "/me/videos";

        AccessToken token = AccessToken.getCurrentAccessToken();
        if (token != null) {
            Bundle param = new Bundle();
            param.putByteArray("video." + getFileExt(filePath), VideoBytes);
            param.putString("description", "sample video");
            new GraphRequest(token,url, param, HttpMethod.POST, new GraphRequest.Callback() {

                public void onCompleted(GraphResponse response) {
                    Log.e("New Post", "Res =" + response.toString());
                    dialog.dismiss();

                    if (response != null && response.getJSONObject() != null && response.getJSONObject().has("id")) {
                        Log.e("New Post", "Success");
                        Toast.makeText(NewPostActivity.this, "Video posted successfully.", Toast.LENGTH_SHORT).show();
                    } else {
                        Toast.makeText(NewPostActivity.this, "Error in posting Video.", Toast.LENGTH_SHORT).show();
                    }
                    setResult(Activity.RESULT_OK, new Intent());
                    finish();
                }
            }).executeAsync();
        }
 }

public static String getFileExt(String fileName) {
        return fileName.substring((fileName.lastIndexOf(".") + 1), fileName.length());
}

这里是GetFilePathFromDevice类,用于在onActivityResult()中从URI获取文件路径。

@SuppressLint("NewApi")
public final class GetFilePathFromDevice {

/**
 * Get file path from URI
 *
 * @param context context of Activity
 * @param uri     uri of file
 * @return path of given URI
 */
public static String getPath(final Context context, final Uri uri) {
    final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
    // DocumentProvider
    if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
        // ExternalStorageProvider
        if (isExternalStorageDocument(uri)) {
            final String docId = DocumentsContract.getDocumentId(uri);
            final String[] split = docId.split(":");
            final String type = split[0];
            if ("primary".equalsIgnoreCase(type)) {
                return Environment.getExternalStorageDirectory() + "/" + split[1];
            }
        }
        // DownloadsProvider
        else if (isDownloadsDocument(uri)) {
            final String id = DocumentsContract.getDocumentId(uri);
            final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
            return getDataColumn(context, contentUri, null, null);
        }
        // MediaProvider
        else if (isMediaDocument(uri)) {
            final String docId = DocumentsContract.getDocumentId(uri);
            final String[] split = docId.split(":");
            final String type = split[0];
            Uri contentUri = null;
            if ("image".equals(type)) {
                contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
            } else if ("video".equals(type)) {
                contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
            } else if ("audio".equals(type)) {
                contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
            }
            final String selection = "_id=?";
            final String[] selectionArgs = new String[]{split[1]};
            return getDataColumn(context, contentUri, selection, selectionArgs);
        }
    }
    // MediaStore (and general)
    else if ("content".equalsIgnoreCase(uri.getScheme())) {
        // Return the remote address
        if (isGooglePhotosUri(uri))
            return uri.getLastPathSegment();
        return getDataColumn(context, uri, null, null);
    }
    // File
    else if ("file".equalsIgnoreCase(uri.getScheme())) {
        return uri.getPath();
    }
    return null;
}

public static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
    Cursor cursor = null;
    final String column = "_data";
    final String[] projection = {column};
    try {
        cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
        if (cursor != null && cursor.moveToFirst()) {
            final int index = cursor.getColumnIndexOrThrow(column);
            return cursor.getString(index);
        }
    } finally {
        if (cursor != null)
            cursor.close();
    }
    return null;
}

public static boolean isExternalStorageDocument(Uri uri) {
    return "com.android.externalstorage.documents".equals(uri.getAuthority());
}

public static boolean isDownloadsDocument(Uri uri) {
    return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}

public static boolean isMediaDocument(Uri uri) {
    return "com.android.providers.media.documents".equals(uri.getAuthority());
}

public static boolean isGooglePhotosUri(Uri uri) {
    return "com.google.android.apps.photos.content".equals(uri.getAuthority());
}
}

1

在修补Util文件后,没有得到结果。

我遇到了软件提到的问题。

我在Android上尝试了这个...现在成功运行了..视频在一段时间后显示在我的墙上(可能是因为Facebook正在刷新数据..)

String path="\mnt\sdcard\test.mp4";

    if (new File(path).exists()) {
        try {
            byte[] data = null;
            String dataPath = new File(path).getAbsolutePath();
            Log.e("", dataPath);
            String dataMsg = "It is the short movie created";
            Bundle param;
            InputStream is = null;
            try {
                is = new FileInputStream(dataPath);
                data = readBytes(is);
                param = new Bundle();
                // param.putString("filename", "" + new
                // File(path).getName());
                // param.putString("mimeType", "video/mp4");
                param.putString("message", dataMsg);
                param.putString("title", "title");
                param.putString("contentType", "video/quicktime");
                param.putByteArray("video.mov", data);
                Utility.mAsyncRunner.request("me/videos", param, "POST",
                        new FBRequestListener(), null);

                Toast.makeText(getContext(), "Uploading...",
                        Toast.LENGTH_SHORT).show();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    } else {
        Toast.makeText(getContext(), "No videos found in these dates",
                Toast.LENGTH_SHORT).show();
    }

FBRequestListener.java

public class FBRequestListener implements RequestListener {

    @Override
    public void onComplete(String response, Object state) {
        Log.e("response", response);
        // Log.e("state", state.toString());
    }

    @Override
    public void onIOException(IOException e, Object state) {
        Log.e("", "onIOException");
        e.printStackTrace();

    }

    @Override
    public void onFileNotFoundException(FileNotFoundException e,
            Object state) {
        Log.e("", "onFileNotFoundException");
        e.printStackTrace();

    }

    @Override
    public void onMalformedURLException(MalformedURLException e,
            Object state) {
        Log.e("", "onMalformedURLException");
        e.printStackTrace();
    }

    @Override
    public void onFacebookError(FacebookError e, Object state) {
        Log.e("", "onFacebookError");
        e.printStackTrace();

    }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接