動画を記録し、ユーザーがYouTube Data API v3を使用してYouTubeに直接アップロードできるAndroidアプリを開発中です。YouTube API 3アップロード動画 - アクセスが設定されていません - Android
GoogleのAPIコンソールで自分のアプリをセットアップしました。サービスの下で、私はYouTube Data API v3を有効にしています。 APIアクセスでは、「インストールされたアプリケーションのクライアントID」(クライアントIDとクライアントシークレットを含む)とセクション「シンプルAPIアクセス」 - >「Androidアプリのキー(証明書付き)」(APIキー今のところ空白になっている「Android Apps」セクション(すべてのAndroidアプリを許可していますが、Androidのキーを設定して試しました)が表示されます。
私は主に、多くの場所から自分のコードをベースとしている:
https://developers.google.com/youtube/v3/code_samples/java#upload_a_video
と
アップロードがOK初期化し、AsyncTaskを開始し、その後私が得ますIOExceptionがスローされました:
{
"code": 403,
"errors": [
{
"domain": "usageLimits",
"message": "Access Not Configured",
"reason": "accessNotConfigured"
}
],
"message": "Access Not Configured"
}
同様のSOの投稿は、私のGoogle APIコンソールの設定と関係があると示唆していますが、間違ったものは見つけられません。助言がありますか?クライアントのIDや秘密をどこにも提供していないからです。
ありがとうございました。
私のコードは、動画のリストを含むフラグメントから実行されます。関連するセクションは次のとおりです。
-
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;
のInit - セットアップ資格とユーチューブ
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
...
credential = googleAccountCredential(scopes);
youtube = new YouTube.Builder(transport, jsonFactory, credential)
.setApplicationName("MyAppName")
.build();
...
}
- ボタンクリックで、
@Override void onClick(View v) {
...
if (hasGooglePlayServices()) {
uploadYouTubeVideos();
...
}
をアップロード開始 - ビルドします資格情報
/**
* 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;
}
- /許可を要求し
/**
* 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;
}
}
- - ものに応じて複数回呼び出さ を選択し、アカウントのユーザーからの復帰で - ユーザー
/**
* Fire intent to get user to choose account
* Return to onActivityResult
*/
private void chooseAccount() {
startActivityForResult(credential.newChooseAccountIntent(), REQUEST_ACCOUNT_PICKER);
}
からアカウントをリクエストします我々が持っている情報 - アカウント、認証など
/**
* 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);
}
}
- アップロード を準備するには -
/**
* 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;
}
}
一緒
をすべてを置きます - Googleがサービス
/**
* 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を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;
}
}
}
SOさんから与えられた関連の質問は、https://github.com/youtube/ytd-androidに私に指摘していますが、もっと詳しく見ていきますが、一見すると非常に似た方法を使っているようです。 –
こんにちは、参考のためにコード全体を投稿できますか? –
私は、プロジェクトのホームページに書かれている "Android API Key"と混同しています。それは "AndroidアプリケーションのクライアントID"を意味しますか? –