In my project wanna have a flow like this:
Users record short videos -> they upload the videos on my channel -> end
- (void)doAuthWithoutCodeExchange:(OIDServiceConfiguration *)configuration clientID:(NSString *)clientID clientSecret:(NSString *)clientSecret { NSURL *redirectURI = [NSURL URLWithString:kRedirectURI]; // builds authentication request OIDAuthorizationRequest *request = [[OIDAuthorizationRequest alloc] initWithConfiguration:configuration clientId:clientID clientSecret:clientSecret scopes:@[ OIDScopeOpenID, OIDScopeProfile ] redirectURL:redirectURI responseType:OIDResponseTypeCode additionalParameters:nil]; // performs authentication request AppDelegate *appDelegate = (AppDelegate *) [UIApplication sharedApplication].delegate; [self logMessage:@"Initiating authorization request %@", request]; appDelegate.currentAuthorizationFlow = [OIDAuthorizationService presentAuthorizationRequest:request presentingViewController:self callback:^(OIDAuthorizationResponse *_Nullable authorizationResponse, NSError *_Nullable error) { if (authorizationResponse) { OIDAuthState *authState = [[OIDAuthState alloc] initWithAuthorizationResponse:authorizationResponse]; [self setAuthState:authState]; [self logMessage:@"Authorization response with code: %@", authorizationResponse.authorizationCode]; // could just call [self tokenExchange:nil] directly, but will let the user initiate it. OIDTokenRequest *tokenExchangeRequest = [_authState.lastAuthorizationResponse tokenExchangeRequest]; [self logMessage:@"Performing authorization code exchange with request [%@]", tokenExchangeRequest]; [OIDAuthorizationService performTokenRequest:tokenExchangeRequest callback:^(OIDTokenResponse *_Nullable tokenResponse, NSError *_Nullable error) { if (!tokenResponse) { [self logMessage:@"Token exchange error: %@", [error localizedDescription]]; } else { [self logMessage:@"Received token response with accessToken: %@", tokenResponse.accessToken]; } [_authState updateWithTokenResponse:tokenResponse error:error]; GTMAppAuthFetcherAuthorization *gtmAuthorization = [[GTMAppAuthFetcherAuthorization alloc] initWithAuthState:authState]; // Sets the authorizer on the GTLRYouTubeService object so API calls will be authenticated. self.youTubeService.authorizer = gtmAuthorization; // Serializes authorization to keychain in GTMAppAuth format. [GTMAppAuthFetcherAuthorization saveAuthorization:gtmAuthorization toKeychainForName:kGTMAppAuthKeychainItemName]; [self uploadVideoFile]; }]; } else { [self logMessage:@"Authorization error: %@", [error localizedDescription]]; } }]; }
This method cause this flow:
app send user to google login page in safari -> user log with his credentials -> after login, user is redirect back to my app -> the block success call the method UploadVideo.
This part of the flow seems to work correctly, i obtain a valid token as the log says. The second part is the video upload that consist in two main methods:
- (void)uploadVideoFile {
// Collect the metadata for the upload from the user interface.
// Status.
GTLRYouTube_VideoStatus *status = [GTLRYouTube_VideoStatus object];
status.privacyStatus = @"public";
// Snippet.
GTLRYouTube_VideoSnippet *snippet = [GTLRYouTube_VideoSnippet object];
snippet.title = @"title";
NSString *desc = @"description";
if (desc.length > 0) {
snippet.descriptionProperty = desc;
}
NSString *tagsStr = @"tags";
if (tagsStr.length > 0) {
snippet.tags = [tagsStr componentsSeparatedByString:@","];
}
GTLRYouTube_Video *video = [GTLRYouTube_Video object];
video.status = status;
video.snippet = snippet;
[self uploadVideoWithVideoObject:video
resumeUploadLocationURL:nil];
}
- (void)uploadVideoWithVideoObject:(GTLRYouTube_Video *)video
resumeUploadLocationURL:(NSURL *)locationURL {
NSURL *fileToUploadURL = [NSURL fileURLWithPath:self.VideoUrlCri.path];
NSError *fileError;
NSLog(@"step");
if (![fileToUploadURL checkPromisedItemIsReachableAndReturnError:&fileError]) {
NSLog(@"exit");
return;
}
// Get a file handle for the upload data.
NSString *filename = [fileToUploadURL lastPathComponent];
NSString *mimeType = [self MIMETypeForFilename:filename
defaultMIMEType:@"video/mp4"];
GTLRUploadParameters *uploadParameters =
[GTLRUploadParameters uploadParametersWithFileURL:fileToUploadURL
MIMEType:mimeType];
uploadParameters.uploadLocationURL = locationURL;
GTLRYouTubeQuery_VideosInsert *query =
[GTLRYouTubeQuery_VideosInsert queryWithObject:video
part:@"snippet,status"
uploadParameters:uploadParameters];
query.executionParameters.uploadProgressBlock = ^(GTLRServiceTicket *ticket,
unsigned long long numberOfBytesRead,
unsigned long long dataLength) {
NSLog(@"upload progress");
};
GTLRYouTubeService *service = self.youTubeService;
_uploadFileTicket = [service executeQuery:query
completionHandler:^(GTLRServiceTicket *callbackTicket,
GTLRYouTube_Video *uploadedVideo,
NSError *callbackError) {
if (callbackError == nil) {
NSLog(@"uploaded");
} else {
NSLog(@"error %@",callbackError);
}
}];
}
- (NSString *)MIMETypeForFilename:(NSString *)filename
defaultMIMEType:(NSString *)defaultType {
NSString *result = defaultType;
NSString *extension = [filename pathExtension];
CFStringRef uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension,
(__bridge CFStringRef)extension, NULL);
if (uti) {
CFStringRef cfMIMEType = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType);
if (cfMIMEType) {
result = CFBridgingRelease(cfMIMEType);
}
CFRelease(uti);
}
return result;
}
I obtain a 403 error in NSLog(@"error %@",callbackError); and i can't see error details because the are something like :
data=<7b226572 726f7222 3a7b2265 72726f72 73223a5b 7b22646f 6d61696e 223a2267 6c6f6261 6c222c22 72656173 6f6e223a 22696e73 75666669 ... 61676522 3a22496e 73756666 69636965 6e742050 65726d69 7373696f 6e227d7d>}
In google api console i have created a Client Oauth for my application bundle and an API key, i use those values for my connection, it seems they works correctly because i obtain a valid token. Anyway, there someone who can help me or point me in the right direction about this error? Or there someone who knows a working example about a video upload for IOS and not for MAC ? There something weird in my code?