package ca.bitwit.postcard.network; import android.os.AsyncTask; import android.util.Log; import ca.bitwit.postcard.PostcardAdaptor; import org.apache.http.HttpEntity; import org.apache.http.entity.mime.HttpMultipartMode; import org.apache.http.entity.mime.MultipartEntityBuilder; import org.json.JSONException; import org.json.JSONObject; import org.scribe.model.*; import java.io.ByteArrayOutputStream; import java.io.File; import java.lang.Boolean; public class FacebookNetwork extends Network { PostcardAdaptor adaptor; JSONObject data; int networkAccountId; public FacebookNetwork(PostcardAdaptor adaptor, JSONObject data) { super(adaptor, data); this.name = "facebook"; this.initializeFacebook(); } public void initializeFacebook() { try { networkAccountId = data.getInt("id"); } catch (JSONException e) { e.printStackTrace(); } } public void willDelete(){} public void postUpdate(SocialActivity activity){ FacebookPostTask task = new FacebookPostTask(); task.prepare(activity); task.execute(); } public class FacebookPostTask extends AsyncTask<String, Long, Boolean> { private SocialActivity activity; public void prepare(SocialActivity activity) { Log.d("CordovaPostcard", "Preparing Facebook Network Activity Post Task"); this.activity = activity; } protected Boolean doInBackground(String... urls) { try { adaptor.setupService("facebook"); String postUrl = "https://graph.facebook.com/me/feed"; Token accessToken = new Token( data.getString("token"), data.getString("tokenSecret")); ProgressOAuthRequest request = null; // if activity.messageLink == null && if ( activity.messageMedia != null && activity.messageMedia.imageLocation != null) { Log.d("Postcard", "sending a picture message to Twitter"); postUrl = "https://graph.facebook.com/me/photos"; request = new ProgressOAuthRequest(Verb.POST, postUrl); MultipartEntityBuilder builder = MultipartEntityBuilder.create(); builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); builder.addTextBody("message", activity.message); //TODO: Needs type maybe? i.e. image/jpg Log.d("Postcard", "image location -> " + activity.messageMedia.imageLocation); builder.addBinaryBody("picture", new File(activity.messageMedia.imageLocation.replace("file://", ""))); HttpEntity entity = builder.build(); // Now, pull out the contents of everything you've added and set it as the payload ByteArrayOutputStream bos = new ByteArrayOutputStream((int) entity.getContentLength()); entity.writeTo(bos); request.addPayload(bos.toByteArray()); request.addHeader(entity.getContentType().getName(), entity.getContentType().getValue()); } else { request = new ProgressOAuthRequest(Verb.POST, postUrl); request.addBodyParameter("message", activity.message); } adaptor.oAuthService.signRequest(accessToken, request); request.uploadProgressCallback = new FacebookPostUploadProgress(); Response response = request.send(); System.out.println(response.getBody()); return true; } catch (Exception exception) { Log.d("CordovaPostcard", exception.getMessage()); return null; } } protected void onProgressUpdate(Long... progress) { Log.d("CordovaPostcard", "Downloaded bytes: " + progress[0]); } protected void onPostExecute(Boolean success) { if (success != null){ Log.d("CordovaPostcard", "Successful post"); adaptor.postUIMessage("networkPostComplete", "{id:" + networkAccountId + "}"); } else Log.d("CordovaPostcard", "Posting failed"); } } public class FacebookPostUploadProgress implements UploadProgressCallback { public void progress(double progress){ adaptor.postUIMessage("networkProgress", "{id:" + networkAccountId + ", progress:" + progress + "}"); } } } /* * - (void)buildActivityParameters { ACAccountType *facebookAccountType = [_accountsManager.accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook]; // Specify App ID and permissions NSDictionary *options = @{ ACFacebookAppIdKey : FACEBOOK_APP_KEY, ACFacebookPermissionsKey : @[@"publish_stream", @"publish_actions"], ACFacebookAudienceKey : ACFacebookAudienceEveryone }; [_accountsManager.accountStore requestAccessToAccountsWithType:facebookAccountType options:options completion:^(BOOL granted, NSError *e) { if (granted) { NSArray *accounts = [_accountsManager.accountStore accountsWithAccountType:facebookAccountType]; self.facebookAccount = [accounts lastObject]; self.currentParameters = [NSMutableDictionary dictionary]; NSString *accountId; BWLog(@"Credentials -- Account ID %@ Token %@", _accountId, _token); if (_accountId != nil) { //Is a FB Page accountId = _accountId; _currentParameters[@"access_token"] = _token; } else { //Is a personal FB feed accountId = [[self.facebookAccount valueForKey:@"properties"] valueForKey:@"uid"]; switch(self.privacyLevel.integerValue){ case FacebookPrivacyLevelMe: _currentParameters[@"privacy"] = @"{\"value\":\"SELF\"}"; break; case FacebookPrivacyLevelFriends: _currentParameters[@"privacy"] = @"{\"value\":\"ALL_FRIENDS\"}"; break; case FacebookPrivacyLevelExtended: _currentParameters[@"privacy"] = @"{\"value\":\"FRIENDS_OF_FRIENDS\"}"; break; case FacebookPrivacyLevelPublic: default: _currentParameters[@"privacy"] = @"{\"value\":\"EVERYONE\"}"; break; } } self.currentRequestUrl = [NSString stringWithFormat:@"https://graph.facebook.com/%@/feed", accountId]; _currentParameters[@"message"] = (_shouldRemoveLink.boolValue) ? _currentActivity.message : _currentActivity.messageWithLink; if (_currentActivity.messageLink) { _currentParameters[@"link"] = _currentActivity.messageLink.url; } else if (_currentActivity.messageMedia.videoData) { self.currentRequestUrl = [NSString stringWithFormat:@"https://graph.facebook.com/%@/videos", accountId]; [_currentParameters removeObjectForKey:@"message"]; _currentParameters[@"title"] = _currentActivity.message; _currentParameters[@"description"] = _currentActivity.message; _currentParameters[@"contentType"] = @"video/mp4"; } else if (_currentActivity.messageMedia.image) { self.currentRequestUrl = [NSString stringWithFormat:@"https://graph.facebook.com/%@/photos", accountId]; } BWLog(@"Facebook parameters -> %@", _currentParameters); [self buildActivityRequest]; } else { BWLog(@"FacebookNetwork post error-> %@", [e description]); [[NetworksManager sharedInstance] network:self didFailWithError:e]; } }]; } - (void)buildActivityRequest { NSURL *feedURL = [NSURL URLWithString:_currentRequestUrl]; self.currentActivityRequest = [SLRequest requestForServiceType:SLServiceTypeFacebook requestMethod:SLRequestMethodPOST URL:feedURL parameters:_currentParameters]; if (_currentActivity.messageLink == nil && _currentActivity.messageMedia.videoData) { [_currentActivityRequest addMultipartData:_currentActivity.messageMedia.videoData withName:@"video.mp4" type:@"video/mp4" filename:@"video.mp4"]; } else if (_currentActivity.messageLink == nil && _currentActivity.messageMedia.imageData) { [_currentActivityRequest addMultipartData:_currentActivity.messageMedia.imageData withName:@"picture" type:@"image/jpg" filename:nil]; } if (_accountId == nil) { _currentActivityRequest.account = self.facebookAccount; } [self sendActivityRequest]; } - (void)sendActivityRequest { AFJSONRequestOperation *operation = [[AFJSONRequestOperation alloc] initWithRequest:_currentActivityRequest.preparedURLRequest]; [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *op, id responseObject) { BWNetLog(@"FacebookNetwork message response %@", responseObject); [_currentActivity.postIds setValue:[responseObject valueForKey:@"id"] forKey:@"facebook"]; NSString *accountId; if (_accountId != nil) { accountId = _accountId; } else { accountId = [[self.facebookAccount valueForKey:@"properties"] valueForKey:@"uid"]; } NSString *postId = [responseObject[@"id"] stringByReplacingOccurrencesOfString:[NSString stringWithFormat:@"%@_", accountId] withString:@""]; [[NetworksManager sharedInstance] network:self didCompletePostingWithInfo:@{ @"id" : postId, @"permalink" : [NSString stringWithFormat:@"http://www.facebook.com/%@/posts/%@", accountId, postId] }]; self.currentActivity = nil; self.currentRequestUrl = nil; self.currentActivityRequest = nil; self.currentParameters = nil; } failure:^(AFHTTPRequestOperation *op, NSError *failure) { NSError *parseError; NSDictionary *errorJson = [NSJSONSerialization JSONObjectWithData:op.responseData options:NSJSONReadingMutableContainers error:&parseError]; BOOL handledError = NO; if (parseError == nil && [[errorJson valueForKeyPath:@"error.code"] isEqualToNumber:@1500]) { BWNetLog(@"Facebook URL Error, retrying with link in message"); [_currentParameters removeObjectForKey:@"link"]; _currentParameters[@"message"] = _currentActivity.messageWithLink; [self buildActivityRequest]; handledError = YES; } else { BWNetLog(@"Operation failed -- status code %d - \n %@ \n %@", op.response.statusCode, [op response].allHeaderFields, [op responseString]); [[NetworksManager sharedInstance] network:self didFailWithError:failure]; self.currentActivity = nil; self.currentRequestUrl = nil; self.currentActivityRequest = nil; self.currentParameters = nil; } [Flurry logEvent:@"Faceboook Post Error" withParameters:@{ @"response" : op.responseString, @"wasHandled" : @(handledError) }]; }]; [operation setUploadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) { BWNetLog(@"Sent %lld of %lld bytes", totalBytesWritten, totalBytesExpectedToWrite); double fraction = (double) totalBytesWritten / totalBytesExpectedToWrite; fraction *= 0.9; [[NetworksManager sharedInstance] network:self updatedProgress:fraction]; }]; [operation start]; } * */