首页 文章

Android Facebook视频上传错误使用Android API 4

提问于
浏览
17

我有这段代码,登录Facebook后,我想通过 Facebook Android SDK v4.13.1 将选定的视频上传到Facebook,

问题:

响应看起来不错,但视频未在测试用户的时间轴中显示 .

代码:

public void shareVideoFB(String videoPath, final ProgressDialog pd) {
    AccessToken accessToken = AccessToken.getCurrentAccessToken();
    GraphRequest request = GraphRequest.newPostRequest(accessToken, "https://graph-video.facebook.com/me/videos", null, new GraphRequest.Callback() {
        @Override
        public void onCompleted(GraphResponse response) {
            try {
                if (pd.isShowing())
                    pd.dismiss();
            } catch (Exception e) {
                e.printStackTrace();
            }
            onFBShareVideoCompleted(response);
        }
    });
    Bundle params = request.getParameters();
    try {
        byte[] data = readBytes(videoPath);
        params.putByteArray("video.mp4", data);
        String albumName = "testFBUpload";
        params.putString("title", albumName);
        params.putString("description", " #SomeTag");
        request.setParameters(params);
        request.executeAsync();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

回复1:

{Response: responseCode:200, graphObject:{"id":"10150481253673034", "url":"https:\/\/graph-video.facebook.com\/me\/videos"}, error:null}

回复2:

{Response: responseCode:200, graphObject:null, error:{HTTPStatus:-1,errorCode:-1,errorType:null, errorMessage:"could not construct request body"}}

编辑1

我创建了一个具有多个权限的新测试用户

  • public_profile

  • user_friends,

  • 电子邮件,

  • user_about_me,

  • user_actions.video,

  • user_likes,

  • user_videos,

  • publish_pages,

  • publish_actions

并上传视频,但仍然得到与 Response 1 相同的响应 .

编辑2

我刚刚注意到,对于测试用户,响应与 Response 1 相同,并且具有完全相同的ID 10150481253673034

3 回答

  • 2

    注意:

    我的解决方案仅适用于测试用户 . 要发布实际用户的视频 refer this 以进行提交 .

    虽然 @Morales Batovski Answer帮助了我,但我想回答我自己的问题,因为没有答案完成,我发布了一个完整的工作解决方案:

    创建测试用户:

    创建具有权限的新测试用户(您可以排除一些不必要的权限):

    • public_profile

    • user_friends

    • email

    • user_about_me

    • user_actions.video

    • user_likes

    • user_videos

    • publish_pages

    • publish_actions

    You will add these permissions here (Screenshot)


    build.gradle:

    compile 'com.facebook.android:facebook-android-sdk:[4,5)'
    

    MyAbstractFacebookActivity:

    import android.annotation.TargetApi;
    import android.app.ProgressDialog;
    import android.content.Context;
    import android.content.Intent;
    import android.content.pm.PackageInfo;
    import android.content.pm.PackageManager;
    import android.net.Uri;
    import android.os.AsyncTask;
    import android.os.Build;
    import android.os.Bundle;
    import android.util.Base64;
    import android.util.Log;
    import android.webkit.MimeTypeMap;
    import android.widget.Toast;
    
    import com.facebook.AccessToken;
    import com.facebook.AccessTokenTracker;
    import com.facebook.CallbackManager;
    import com.facebook.FacebookCallback;
    import com.facebook.FacebookException;
    import com.facebook.FacebookSdk;
    import com.facebook.GraphRequest;
    import com.facebook.GraphResponse;
    import com.facebook.Profile;
    import com.facebook.ProfileTracker;
    import com.facebook.login.LoginManager;
    import com.facebook.login.LoginResult;
    import com.facebook.share.Sharer;
    
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.json.JSONException;
    import org.json.JSONObject;
    
    import java.io.ByteArrayOutputStream;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    import java.util.Arrays;
    
    /**
     * Created by Nadeem Iqbal on 6/20/2016.
     */
    public abstract class MyAbstractFacebookActivity extends MyAbstractActivity {
    
        private static String[] FB_BASIC_PERMISSIONS = new String[]{"public_profile", "email"};
    
        private CallbackManager callbackManager;
        private FacebookCallback<Sharer.Result> fbCallback;
        private AccessTokenTracker accessTokenTracker;
        private AccessToken accessToken;
        private ProfileTracker profileTracker;
        private Profile profile;
        private String fbId = "";
    
        byte[] data;
    
        private boolean LOG_FB_HASH = true;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
    
            Log.e("FB HASH", getFBHashKey());
            fbInit();
        }
    
    
        public String getFBHashKey() {
            String key = "";
            try {
                PackageInfo info = getPackageManager().getPackageInfo(
                        getApplicationContext().getPackageName(),
                        PackageManager.GET_SIGNATURES);
                for (android.content.pm.Signature signature : info.signatures) {
                    MessageDigest md = MessageDigest.getInstance("SHA");
                    md.update(signature.toByteArray());
                    key = Base64.encodeToString(md.digest(), Base64.DEFAULT);
                    if (LOG_FB_HASH) {
                        copyToClipBoard(key);
                    }
                    log("KeyHash FB:", key);
                }
            } catch (PackageManager.NameNotFoundException | NoSuchAlgorithmException e) {
            }
            return key;
        }
    
        @TargetApi(Build.VERSION_CODES.HONEYCOMB)
        public void copyToClipBoard(String textToCopy) {
            int sdk_Version = Build.VERSION.SDK_INT;
            if (sdk_Version < Build.VERSION_CODES.HONEYCOMB) {
                android.text.ClipboardManager clipboard = (android.text.ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
                clipboard.setText(textToCopy);
                Toast.makeText(getApplicationContext(), "Copied to Clipboard!", Toast.LENGTH_SHORT).show();
            } else {
                android.content.ClipboardManager clipboard = (android.content.ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
                android.content.ClipData clip = android.content.ClipData.newPlainText("Text Label", textToCopy);
                clipboard.setPrimaryClip(clip);
                Toast.makeText(getApplicationContext(), "Copied to Clipboard!", Toast.LENGTH_SHORT).show();
            }
        }
    
        ///////// FB Work Start //////////
    
        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
    
            ///// FB Work Start //////
            callbackManager.onActivityResult(requestCode, resultCode, data);
            ///// FB Work End //////
    
        }
    
    
        void fbInit() {
            FacebookSdk.sdkInitialize(getApplicationContext());
            callbackManager = CallbackManager.Factory.create();
    
            fbCallback = new FacebookCallback<Sharer.Result>() {
                @Override
                public void onSuccess(Sharer.Result result) {
                    log("Post Shared on FB");
    
                    onPostSharedSuccessfully(result);
                }
    
                @Override
                public void onCancel() {
                    toast("Cancelled");
    
                    onPostSharedCancelled();
                }
    
                @Override
                public void onError(FacebookException e) {
                    toast("Error:" + e.getMessage());
                    e.printStackTrace();
    
                    onPostSharedError(e);
                }
            };
    
            profileTracker = new ProfileTracker() {
                @Override
                protected void onCurrentProfileChanged(Profile oldProfile, Profile currentProfile) {
                    Profile.setCurrentProfile(currentProfile);
                    profile = currentProfile;
                }
            };
    
            accessTokenTracker = new AccessTokenTracker() {
                @Override
                protected void onCurrentAccessTokenChanged(
                        AccessToken oldAccessToken,
                        AccessToken currentAccessToken) {
                    // On AccessToken changes fetch the new profile which fires the event on
                    // the ProfileTracker if the profile is different
                    Profile.fetchProfileForCurrentAccessToken();
                }
            };
    
            // Ensure that our profile is up to date
            Profile.fetchProfileForCurrentAccessToken();
    
            LoginManager.getInstance().registerCallback(callbackManager,
                    new FacebookCallback<LoginResult>() {
    
                        @Override
                        public void onSuccess(LoginResult loginResult) {
                            accessToken = AccessToken.getCurrentAccessToken();
    
                            onFBLoginSuccessfully(loginResult, accessToken);
                            getNewFBId();
                        }
    
                        @Override
                        public void onCancel() {
                            warning("Cancel", "User cancelled the process");
    
                            onFBLoginCancelled();
                        }
    
                        @Override
                        public void onError(FacebookException exception) {
                            warning("Error", "" + exception.getMessage());
                            onFBLoginError(exception);
                        }
                    });
        }
    
        protected void getNewFBId() {
            GraphRequest request = GraphRequest.newMeRequest(
                    AccessToken.getCurrentAccessToken(),
                    new GraphRequest.GraphJSONObjectCallback() {
                        @Override
                        public void onCompleted(
                                JSONObject object,
                                GraphResponse response) {
                            try {
                                fbId = object.getString("id");
                                onFbId(fbId);
    
                            } catch (JSONException e) {
                                e.printStackTrace();
                            }
                        }
                    });
    
            Bundle parameters = new Bundle();
            parameters.putString("fields", "id");
            request.setParameters(parameters);
            request.executeAsync();
        }
    
        public abstract void onFbId(String fbId);
    
        public void doLogin() {
            doLogin(FB_BASIC_PERMISSIONS);
        }
    
        public void doLogin(String[] permissions) {
            try {
                LoginManager.getInstance().logOut();
            } catch (Exception e) {
                e.printStackTrace();
            }
            LoginManager.getInstance().logInWithPublishPermissions(this, Arrays.asList(permissions));
        }
    
        ///////// FB Work End //////////
    
        public AccessToken getAccessToken() {
            return accessToken;
        }
    
        public ProfileTracker getProfileTracker() {
            return profileTracker;
        }
    
        public Profile getProfile() {
            return profile;
        }
    
        public String getFBId() {
            return fbId;
        }
    
    
        public static String getMimeType(String url) {
            String type = null;
            String extension = MimeTypeMap.getFileExtensionFromUrl(url);
            if (extension != null) {
                type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
            }
            return type;
        }
    
        private static String getPrivacy(String privacy) {
            String str;
            if (privacy.equalsIgnoreCase("Everyone"))
                str = "EVERYONE";
            if (privacy.equalsIgnoreCase("Friends and Networks"))
                str = "NETWORKS_FRIENDS";
            else if (privacy.equalsIgnoreCase("Friends of Friends"))
                str = "FRIENDS_OF_FRIENDS";
            else if (privacy.equalsIgnoreCase("Friends Only"))
                str = "ALL_FRIENDS";
            else if (privacy.equalsIgnoreCase("Custom"))
                str = "CUSTOM";
            else if (privacy.equalsIgnoreCase("Specific People..."))
                str = "SOME_FRIENDS";
            else
                str = "SELF";
    
            return str;
        }
    
        public void shareVideoFB(String videoPath, final ProgressDialog pd) {
            AccessToken accessToken = AccessToken.getCurrentAccessToken();
    
            Uri fileUri = Uri.parse(videoPath);
            String fileName = videoPath.substring(videoPath.lastIndexOf('/') + 1, videoPath.length());
            String mimeType = getMimeType(videoPath);
    
            try {
                data = readBytes(videoPath);
            } catch (IOException e) {
                e.printStackTrace();
            }
    
            int videoSize = data.length;
    
            String privacy = getPrivacy("Friends Only");
    
            GraphRequest request = GraphRequest.newPostRequest(accessToken, "/me/videos", null, new GraphRequest.Callback() {
                @Override
                public void onCompleted(GraphResponse response) {
                    try {
                        if (pd.isShowing())
                            pd.dismiss();
                    } catch (Exception e) {
                    }
    
                    onFBShareVideoCompleted(response);
                }
            });
    
            Bundle params = request.getParameters();
    
            params = request.getParameters();
            params.putByteArray(fileName, data);
    
            params.putString("title", fileName);
            params.putString("description", "Some Description...");
    
    //        params.putString("upload_phase", "start");
            params.putInt("file_size", data.length);
    
            request.setParameters(params);
            request.executeAsync();
    
        }
    
    
        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();
        }
    
        protected abstract void onFBShareVideoCompleted(GraphResponse response);    
    
        protected abstract void onFBLoginError(FacebookException exception);
    
        protected abstract void onFBLoginCancelled();
    
        protected abstract void onFBLoginSuccessfully(LoginResult loginResult, AccessToken accessToken);
    
        protected abstract void onPostSharedError(FacebookException e);
    
        protected abstract void onPostSharedCancelled();
    
        protected abstract void onPostSharedSuccessfully(Sharer.Result result);
    
    }
    

    分享:

    (此活动实现 MyAbstractFacebookActivity 并且需要来自intent的字符串 path 值,我的FB共享按钮侦听器是 onFacebookShareButtonClick()

    import android.app.ProgressDialog;
    import android.os.Bundle;
    import android.support.v7.app.ActionBar;
    import android.text.TextUtils;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.widget.TextView;
    
    import com.facebook.AccessToken;
    import com.facebook.FacebookException;
    import com.facebook.GraphResponse;
    import com.facebook.login.LoginResult;
    import com.facebook.share.Sharer;
    
    public class Share extends MyAbstractFacebookActivity {
    
        String path = "";
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_share);
            setHeader("Share");
    
            path = getIntent().getStringExtra("path");
            if (TextUtils.isEmpty(path)) {
                toast("Path is null, Exiting Activity");
                finish();
            }
        }
    
        public void setHeader(String header_title) {
             // ... My Implementation
        }
    
        public void back(View v) {
            finish();
        }
    
        public void onFacebookShareButtonClick(View view) {
            // Facebook Share button Click Listener...
            String[] FB_BASIC_PERMISSIONS = new String[]{"publish_actions"};
    
            doLogin(FB_BASIC_PERMISSIONS);
        }
    
        @Override
        protected void onFBLoginError(FacebookException exception) {
    
        }
    
        @Override
        protected void onFBLoginCancelled() {
    
        }
    
        @Override
        protected void onFBLoginSuccessfully(LoginResult loginResult, AccessToken accessToken) {
    //        getNewFBId();
    
            ProgressDialog pd = new ProgressDialog(this);
    
            pd.setMessage("Uploading Video, Please wait...");
            pd.setCancelable(false);
            pd.setCanceledOnTouchOutside(false);
            pd.show();
    
            shareVideoFB(path, pd);
    
        }
    
        @Override
        protected void onPostSharedError(FacebookException e) {
    
        }
    
        @Override
        protected void onPostSharedCancelled() {
    
        }
    
        @Override
        protected void onPostSharedSuccessfully(Sharer.Result result) {
    
        }
    
        boolean isCalledEarlier = false;
    
        @Override
        public void onFbId(String fbId) {
            if (!isCalledEarlier) {
                ProgressDialog pd = new ProgressDialog(this);
    
                pd.setMessage("Uploading Video, Please wait...");
                pd.setCancelable(false);
                pd.setCanceledOnTouchOutside(false);
                pd.show();
    
                shareVideoFB(path, pd);
    
                isCalledEarlier = true;
            }
        }
    
        @Override
        protected void onFBShareVideoCompleted(GraphResponse response) {
            // Here the  video share response will come...
            toast(response.toString());
            log(response.toString());
        }
    
    }
    

    结果:

    Test User Timeline

  • 1

    你有2个回复 .

    响应1来自测试用户.i.e . 视频已成功共享 . - >所以你需要使用 Facebook developer console 提供的测试用户凭据登录facebook并检查时间表 . 如果您没有在时间轴中找到它,请在配置文件中查看它 . 你肯定会在那里找到它 .

    由于该帐户中设置了一些隐私设置,有时它不会在时间轴上显示共享帖子 .

    响应2来自另一个帐户 . - >失败是因为除非Facebook批准您的应用,否则它将不允许您使用除测试帐户之外的其他帐户共享视频 . 因此,当您的申请将从Facebook提交流程获得 publish_actions 的批准时,您可以使用不同的帐户进行测试 . 所以这个案子没问题 .

    请参阅https://developers.facebook.com/docs/opengraph/submission-process以了解提交过程 .

  • 3

    在GraphRequest的创建中,用 /me/videos 替换图形路径 https://graph-video.facebook.com/me/videos .

    GraphRequest request = GraphRequest.newPostRequest(accessToken, "/me/videos", null, new GraphRequest.Callback() {
            @Override
            public void onCompleted(GraphResponse response) {
                // your code
            }
        });
    

    来源:

    Video Upload with Graph API

    Graph API Reference: Video

    您可以使用以下边缘发布视频:

    • /{user-id}/videos

    • /{event-id}/videos

    • /{page-id}/videos

    • /{group-id}/videos

相关问题