【问题标题】:Android direct upload video to YouTubeAndroid直接上传视频到YouTube
【发布时间】:2025-12-08 16:55:02
【问题描述】:

我需要从图库中将视频上传到 YouTube,然后返回 YouTube 视频网址。但是,我一直无法成功获得授权。错误

java.lang.IllegalArgumentException:预期的数字类型,但得到了类 com.google.api.client.extensions.java6.auth.oauth2.FilePersistedCredential [key expiration_time_millis,字段私有 java.util.Map com.google.api.client .extensions.java6.auth.oauth2.FilePersistedCredentials.credentials]

发生在下面的代码行,

// 设置授权码流程。

    GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
            Yconstants.HTTP_TRANSPORT, Yconstants.JSON_FACTORY,
            clientSecrets, scopes).setCredentialStore(credentialStore)
            .build();

任何人都可以通过提供一些关于以下内容的想法来帮助我吗?

  1. 如何获取 JSONObject 用户的凭证字符串?

        JSONObject user = new JSONObject();
        user.put("access_token", "");
        user.put("expiration_time_millis", 1350470676670L);
        user.put("refresh_token", "()");
    
  2. 如何在注册期间获取我的应用的客户端密码?

    在我的 client_secret.json 中没有客户端密码值。

【问题讨论】:

    标签: android youtube


    【解决方案1】:

    这可能会对您有所帮助:

    import com.google.api.client.googleapis.GoogleHeaders;
    import com.google.api.client.http.HttpRequest;
    import com.google.api.client.http.HttpRequestFactory;
    import com.google.api.client.http.HttpResponse;
    import com.google.api.client.http.HttpResponseException;
    import com.google.api.client.http.HttpTransport;
    import com.google.api.client.http.HttpUnsuccessfulResponseHandler;
    import com.google.api.client.http.InputStreamContent;
    import com.google.api.client.http.MultipartRelatedContent;
    import com.google.api.client.http.javanet.NetHttpTransport;
    import com.google.api.client.http.xml.atom.AtomContent;
    import com.google.api.client.util.Key;
    import com.google.api.client.xml.XmlNamespaceDictionary;
    
    ....
    
    public static final XmlNamespaceDictionary NAMESPACE_DICTIONARY = new XmlNamespaceDictionary();
        static
        {
            NAMESPACE_DICTIONARY.set("", "http://www.w3.org/2005/Atom")
                .set("atom", "http://www.w3.org/2005/Atom")
                .set("exif", "http://schemas.google.com/photos/exif/2007")
                .set("gd", "http://schemas.google.com/g/2005")
                .set("geo", "http://www.w3.org/2003/01/geo/wgs84_pos#")
                .set("georss", "http://www.georss.org/georss")
                .set("gml", "http://www.opengis.net/gml")
                .set("gphoto", "http://schemas.google.com/photos/2007")
                .set("media", "http://search.yahoo.com/mrss/")
                .set("openSearch", "http://a9.com/-/spec/opensearch/1.1/")
                .set("xml", "http://www.w3.org/XML/1998/namespace");
        }
    
        /**
         * Represents an Atom formatted upload request for YouTube
         * 
         * @see http 
         *      ://code.google.com/intl/en/apis/youtube/2.0/developers_guide_protocol_direct_uploading.html#Sending_a_Direct_Upload_API_Request
         * 
         *      <entry xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/"
         *      xmlns:yt="http://gdata.youtube.com/schemas/2007"> <media:group> <media:title type="plain">Bad Wedding Toast</media:title>
         *      <media:description type="plain"> I gave a bad toast at my friend's wedding. </media:description> <media:category
         *      scheme="http://gdata.youtube.com/schemas/2007/categories.cat">People </media:category> <media:keywords>toast,
         *      wedding</media:keywords> </media:group> </entry>
         * @author fhackenberger
         */
        public static class UploadEntry
        {
            @Key("media:group")
            MediaGroup group = new MediaGroup();
        }
    
        /**
         * @see UploadEntry
         * @author fhackenberger
         */
        public static class MediaGroup
        {
            @Key("media:title")
            MediaAttribute title = new MediaAttribute();
            @Key("media:description")
            MediaAttribute description = new MediaAttribute();
            @Key("media:category")
            MediaCategory category = new MediaCategory();
            @Key("media:keywords")
            String keywords;
        }
    
        /**
         * @see UploadEntry
         * @author fhackenberger
         */
        public static class MediaAttribute
        {
            @Key("@type")
            String type = "plain";
            @Key("text()")
            String value;
        }
    
        /**
         * @see UploadEntry
         * @author fhackenberger
         */
        public static class MediaCategory
        {
            @Key("@scheme")
            String scheme = "http://gdata.youtube.com/schemas/2007/categories.cat";
            @Key("text()")
            String category;
        }
    
        /**
         * Represents an error response from Youtube
         * 
         * @see http://code.google.com/intl/en/apis/youtube/2.0/developers_guide_protocol_error_responses.html <errors> <error>
         *      <domain>yt:validation</domain> <code>invalid_value</code> <location
         *      type='xpath'>media:group/media:category[@scheme='http://gdata.youtube.com/schemas/2007/categories.cat']/text() </location>
         *      </error> </errors>
         * @author fhackenberger
         * 
         */
        public static class YoutubeErrors
        {
            @Key("error")
            List<YoutubeError> errors;
        }
    
        /**
         * @see YoutubeErrors
         * @author fhackenberger
         */
        public static class YoutubeError
        {
            @Key
            String domain;
            @Key
            String code;
            @Key
            YoutubeErrorLocation location;
    
            @Override
            public String toString()
            {
                return "domain: " + domain + "; code: " + code + "; location: (" + location + ")";
            }
        }
    
        /**
         * @see YoutubeError
         * @author fhackenberger
         */
        public static class YoutubeErrorLocation
        {
            @Key("@type")
            String type;
            @Key("text()")
            String location;
    
            @Override
            public String toString()
            {
                return "type: " + type + "; location: " + location;
            }
        }
    
        /**
         * Represents a YouTube video feed
         * 
         * @see http://code.google.com/intl/en/apis/youtube/2.0/developers_guide_protocol_understanding_video_feeds.html
         * @author fhackenberger
         */
        public static class VideoFeed
        {
            @Key
            List<Video> items;
    
            @Override
            public String toString()
            {
                return "Items: " + items;
            }
        }
    
        /**
         * A single video entry
         * 
         * @see VideoFeed
         * @author fhackenberger
         */
        public static class Video
        {
            @Key
            String id;
            @Key
            String title;
            @Key
            String description;
            @Key
            Player player;
            @Key("link")
            List<Link> links;
    
            @Override
            public String toString()
            {
                return "Id: " + id + " Title: " + title + " Description: " + description + " Player: " + player + " Links: " + links;
            }
        }
    
        /**
         * A related link for a {@link Video}
         * 
         * @see VideoFeed
         * @author fhackenberger
         */
        public static class Link
        {
            @Key("@rel")
            String rel;
            @Key("@href")
            String href;
            @Key("@type")
            String type;
    
            @Override
            public String toString()
            {
                return href;
            }
        }
    
        /**
         * The URL for the YouTube video player for a {@link Video}
         * 
         * @see VideoFeed
         * @author fhackenberger
         */
        public static class Player
        {
            @Key("default")
            String defaultUrl;
    
            @Override
            public String toString()
            {
                return "DefaultURL: " + defaultUrl;
            }
        }
    
        public YouTubeUploader(Context context, AccountInfo accountInfo)
        {
            this.context = context;
            this.accountInfo = accountInfo;
        }
    
        @Override
        public void upload(Record r)
        {
            HttpRequest request = null;
            try
            {
                HttpTransport transport = new NetHttpTransport();
                HttpRequestFactory requestFactory = transport.createRequestFactory();
                request = requestFactory.buildPostRequest(YouTubeUrl.uploadUrl(), null);
    
                File file = new File(fileName);
                InputStreamContent videoContent = new InputStreamContent();
                videoContent.inputStream = new FileInputStream(file);
                videoContent.type = "application/octet-stream";
    
                // Describes the video
                AtomContent atomContent = new AtomContent();
                atomContent.namespaceDictionary = NAMESPACE_DICTIONARY;
                UploadEntry uploadEntry = new UploadEntry();
                uploadEntry.group.title.value = videoTitle;
                uploadEntry.group.description.value = "";
                uploadEntry.group.category.category = "People\n";
                uploadEntry.group.keywords = "";
                atomContent.entry = uploadEntry;
    
                MultipartRelatedContent multiPartContent = MultipartRelatedContent.forRequest(request);
                multiPartContent.parts.add(atomContent);
                multiPartContent.parts.add(videoContent);
    
                request.content = multiPartContent;
    
                GoogleHeaders headers = new GoogleHeaders();
                headers.setApplicationName(Consts.youtubeAppName);
                headers.acceptEncoding = "gzip";
                headers.mimeVersion = "1.0";
                headers.gdataVersion = "2";
                headers.setDeveloperId(Consts.youtubeDevKey);
                headers.setGoogleLogin(accountInfo.token);
                headers.slug = GoogleHeaders.SLUG_ESCAPER.escape(videoTitle);
    
                request.headers = headers;
                request.unsuccessfulResponseHandler = new YoutubeUnsuccessfulResponseHandler();
    
                // HttpParser parser = new AtomParser();
                // ((AtomParser)parser).namespaceDictionary = NAMESPACE_DICTIONARY;
                // request.addParser(parser);
    
                HttpResponse response = request.execute();
                String responseStr = NetworkHelper.readResponse(response.getContent());
                videoUrl = getContentLink(responseStr);
            }
            catch (HttpResponseException e)
            {
                YoutubeError error = ((YoutubeUnsuccessfulResponseHandler) request.unsuccessfulResponseHandler).errors.errors.get(0);
                errorMessage = error + "";
            }
            catch (IOException e)
            {
                errorMessage = e.getMessage();
            }
        }
    
        class YoutubeUnsuccessfulResponseHandler implements
            HttpUnsuccessfulResponseHandler
        {
            YoutubeErrors errors = null;
    
            @Override
            public boolean handleResponse(HttpRequest request, HttpResponse response, boolean retrySupported) throws IOException
            {
                errors = response.parseAs(YoutubeErrors.class);
                return false;
            }
        }
    
    
    public class YouTubeUrl extends GoogleUrl
    {
        private static final boolean PRETTY_PRINT = true;
    
        private static final String UPLOAD_URL = "https://uploads.gdata.youtube.com/feeds/api/users/default/uploads";
    
        @Key
        String author;
    
        @Key("max-results")
        Integer maxResults = 2;
    
        YouTubeUrl(String encodedUrl, boolean json)
        {
            super(encodedUrl);
            if (json)
                this.alt = "jsonc";
            this.prettyprint = PRETTY_PRINT;
        }
    
        public static GenericUrl uploadUrl()
        {
            return new YouTubeUrl(UPLOAD_URL, false);
        }
    }
    

    SRC

    【讨论】: