Tôi đang làm việc trên ứng dụng Android ghi video và cho phép người dùng tải video trực tiếp lên YouTube bằng API dữ liệu YouTube v3.Video tải lên YouTube API 3 - Quyền truy cập không được định cấu hình - Android
Tôi đã thiết lập ứng dụng của mình trong bảng điều khiển API của Google. Theo dịch vụ, tôi đã bật API dữ liệu YouTube v3. Trong quyền truy cập API, tôi có cả phần "ID ứng dụng cho ứng dụng đã cài đặt" (bao gồm ID ứng dụng khách và Bí mật ứng dụng khách) và phần "Truy cập API đơn giản" -> "Khóa cho ứng dụng Android (có chứng chỉ)" (bao gồm khóa API và một phần "Ứng dụng Android", để trống bây giờ, tức là cho phép tất cả các ứng dụng Android, nhưng tôi đã thử bằng cách đặt khóa android của mình).
Tôi đã dựa mã của tôi từ một số nơi, chủ yếu là:
https://developers.google.com/youtube/v3/code_samples/java#upload_a_video
và
Việc tải initialises OK, bắt đầu AsyncTask, nhưng sau đó tôi nhận được một IOException ném câu nói:
{
"code": 403,
"errors": [
{
"domain": "usageLimits",
"message": "Access Not Configured",
"reason": "accessNotConfigured"
}
],
"message": "Access Not Configured"
}
SO bài viết tương tự cho thấy nó là để làm với các thiết lập giao diện điều khiển API Google của tôi, nhưng tôi không thể tìm thấy bất cứ điều gì sai trái. Bất kỳ đề xuất? Tôi tự hỏi nếu đó là vì tôi không cung cấp ID khách hàng hoặc bí mật ở bất cứ đâu ...
Cảm ơn.
Mã của tôi chạy từ một đoạn có chứa danh sách video. Các phần liên quan là:
- Init
public class UploadFragment extends Fragment {
private static GoogleAccountCredential credential;
private static final HttpTransport transport = AndroidHttp.newCompatibleTransport();
private static final JsonFactory jsonFactory = new GsonFactory();
public YouTube youtube;
List<String> scopes = Lists.newArrayList(YouTubeScopes.YOUTUBE_UPLOAD);
private static String VIDEO_FILE_FORMAT = "video/*";
static final int REQUEST_GOOGLE_PLAY_SERVICES = 0;
static final int REQUEST_AUTHORIZATION = 1;
static final int REQUEST_ACCOUNT_PICKER = 2;
- Cài đặt chứng chỉ và youtube
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
...
credential = googleAccountCredential(scopes);
youtube = new YouTube.Builder(transport, jsonFactory, credential)
.setApplicationName("MyAppName")
.build();
...
}
- Mở nút nhấp chuột, bắt đầu upload
@Override void onClick(View v) {
...
if (hasGooglePlayServices()) {
uploadYouTubeVideos();
...
}
- Xây dựng thông tin xác thực
/**
* Get the credential to authorize the installed application to access user's protected data.
*
* @param scopes list of scopes needed to run YouTube upload.
*/
private static GoogleAccountCredential googleAccountCredential(List<String> scopes) throws Exception {
credential = GoogleAccountCredential.usingOAuth2(context, scopes)
.setSelectedAccountName(PreferenceManager.getAccountName());
return credential;
}
- Yêu cầu một tài khoản từ người sử dụng
/**
* Fire intent to get user to choose account
* Return to onActivityResult
*/
private void chooseAccount() {
startActivityForResult(credential.newChooseAccountIntent(), REQUEST_ACCOUNT_PICKER);
}
- Khi trở về từ người dùng lựa chọn và chiếm -/đề nghị cấp phép
/**
* Returns from chooseAccount and from request authorization
*/
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case REQUEST_AUTHORIZATION:
if (resultCode == Activity.RESULT_OK) {
uploadYouTubeVideos();
} else {
chooseAccount();
}
break;
case REQUEST_ACCOUNT_PICKER:
if (resultCode == Activity.RESULT_OK && data != null && data.getExtras() != null) {
String accountName = data.getExtras().getString(AccountManager.KEY_ACCOUNT_NAME);
if (accountName != null) {
credential.setSelectedAccountName(accountName);
PreferenceManager.setAccountName(accountName);
uploadYouTubeVideos();
}
}
break;
}
}
- Được gọi là nhiều lần tùy thuộc vào những gì thông tin chúng tôi có - tài khoản, ủy quyền, v.v.
/**
* Uploads user selected video to the user's YouTube account using OAuth2
* for authentication.
*
* @param videoFile file to be uploaded
*/
public void uploadYouTubeVideos() {
if (credential.getSelectedAccountName() == null) {
chooseAccount();
} else {
File videoFile = getVideoFile();
Insert videoInsert = prepareUpload(videoFile);
new VideoUploadAsyncTask().execute(videoInsert);
}
}
- Chuẩn bị tải lên - Đặt tất cả mọi thứ cùng nhau
/**
* Prepare upload. Just leaves execute to be run in AsyncTask.
*
* @param videoFile file to be uploaded
* @return
*/
public Insert prepareUpload(File videoFile) {
try {
// Add extra information to the video before uploading.
Video videoObjectDefiningMetadata = new Video();
// Set the video to public (default).
VideoStatus status = new VideoStatus();
status.setPrivacyStatus("public");
videoObjectDefiningMetadata.setStatus(status);
// We set a majority of the metadata with the VideoSnippet object.
VideoSnippet snippet = new VideoSnippet();
// Video file name.
snippet.setTitle(videoFile.getName());
snippet.setDescription("Test description");
// Set keywords.
List<String> tags = new ArrayList<String>();
tags.add("test");
snippet.setTags(tags);
// Set completed snippet to the video object.
videoObjectDefiningMetadata.setSnippet(snippet);
InputStreamContent mediaContent = new InputStreamContent(
VIDEO_FILE_FORMAT, new BufferedInputStream(new FileInputStream(videoFile)));
mediaContent.setLength(videoFile.length());
/*
* The upload command includes: 1. Information we want returned after file is successfully
* uploaded. 2. Metadata we want associated with the uploaded video. 3. Video file itself.
*/
YouTube.Videos.Insert videoInsert = youtube.videos()
.insert("snippet,statistics,status", videoObjectDefiningMetadata, mediaContent);
// Set the upload type and add event listener.
MediaHttpUploader uploader = videoInsert.getMediaHttpUploader();
/*
* Sets whether direct media upload is enabled or disabled. True = whole media content is
* uploaded in a single request. False (default) = resumable media upload protocol to upload
* in data chunks.
*/
uploader.setDirectUploadEnabled(false);
MediaHttpUploaderProgressListener progressListener = new MediaHttpUploaderProgressListener() {
public void progressChanged(MediaHttpUploader uploader) throws IOException {
switch (uploader.getUploadState()) {
case INITIATION_STARTED:
Log.d(TAG, "Upload file: Initiation Started");
break;
case INITIATION_COMPLETE:
Log.d(TAG, "Upload file: Initiation Completed");
break;
case MEDIA_IN_PROGRESS:
Log.d(TAG, "Upload file: Upload in progress");
Log.d(TAG, "Upload file: Upload percentage: " + uploader.getProgress());
break;
case MEDIA_COMPLETE:
Log.d(TAG, "Upload file: Upload Completed!");
break;
case NOT_STARTED:
Log.d(TAG, "Upload file: Upload Not Started!");
break;
}
}
};
uploader.setProgressListener(progressListener);
return videoInsert;
} catch (FileNotFoundException e) {
Log.e(TAG, "File not found: " + e.getMessage());
return null;
} catch (IOException e) {
Log.e(TAG, "IOException: " + e.getMessage());
return null;
}
}
- Yêu cầu Dịch vụ Google Play
/**
* Pop up dialog requesting user to download Google Play Services.
* Returns to onActivityResult
*/
void showGooglePlayServicesAvailabilityErrorDialog(final int connectionStatusCode) {
getActivity().runOnUiThread(new Runnable() {
public void run() {
Dialog dialog =
GooglePlayServicesUtil.getErrorDialog(connectionStatusCode, getActivity(),
REQUEST_GOOGLE_PLAY_SERVICES);
dialog.show();
}
});
}
- AsyncTask chạy thực thi trên tải lên
public class VideoUploadAsyncTask extends AsyncTask<Insert, Void, Void> {
@Override
protected Void doInBackground(Insert... inserts) {
Insert videoInsert = inserts[0];
try {
Video returnVideo = videoInsert.execute();
} catch (final GooglePlayServicesAvailabilityIOException availabilityException) {
showGooglePlayServicesAvailabilityErrorDialog(
availabilityException.getConnectionStatusCode());
} catch (UserRecoverableAuthIOException userRecoverableException) {
startActivityForResult(
userRecoverableException.getIntent(), UploadFragment.REQUEST_AUTHORIZATION);
} catch (IOException e) {
Log.e(TAG, "IOException: " + e.getMessage());
}
return null;
}
}
}
Các câu hỏi liên quan được đưa ra bởi SO đã chỉ cho tôi https://github.com/youtube/ytd-android, tôi sẽ xem chi tiết hơn, nhưng thoạt nhìn, có vẻ như chúng tôi đang sử dụng một phương pháp rất giống nhau . –
Xin chào, bạn có thể đăng toàn bộ mã để tham khảo không? –
Tôi nhầm lẫn với "Khóa API Android" được viết trong trang chủ của dự án. Điều đó có nghĩa là "Client ID cho ứng dụng Android"? –