Send attachment to QuickBlox IOS sdk - ios

I have downloaded the quickblox sample chat application and sending text messages are working fine. But how to send attachment like picture, video or else?
According to Quickblox's documentation.
There is class named QBChatAttachment having properties as type, url and id but how to attach files like picture, video or else?

Please Proper read SimpleSample-chat users-ios in this link they have mention all detail regarding how to send attachment and how to receive and download attachment etc .
For sending and receiving attachment in quickbox follow this link
Send and Receive Attachment
Detail Explanation:
Send and receive a message with attachment Send attachment
It's possible to add attachments to message: for example, image, audio
file or video file. We don't have any restrictions here - you can
attach any type of file.
To send a message with attachments you should use the same way as you
send regular message with text, but add to it an attachment object.
Attachment can be:
1) A file content Module Example
2) A file in Custom Objects module Example
To send a message with attachment
you should upload a file to Content module, Custom Objects module
using sample above or use an url to any file in Internet. Then you
should incorporate an ID to file to message.
For example, we use Content module to store attachments. Next snippets
show
how to upload a file to Content module and send it as an attach:
// Upload a file to the Content module
NSData *imageData = UIImagePNGRepresentation([UIImage imageNamed:#"arrow.png"]);
[QBRequest TUploadFile:imageData fileName:#"arrow.png" contentType:#"image/png" isPublic:NO successBlock:^(QBResponse
*response, QBCBlob *uploadedBlob) {
NSUInteger uploadedFileID = uploadedBlob.ID;
// Create chat message with attach
//
QBChatMessage *message = [QBChatMessage message];
...
QBChatAttachment *attachment = QBChatAttachment.new;
attachment.type = #"image";
attachment.ID = [NSString stringWithFormat:#"%d", uploadedFileID]; //use 'ID' property to store an ID of a file in Content or CustomObjects modules
[message setAttachments:#[attachment]];
} statusBlock:^(QBRequest *request, QBRequestStatus *status) {
// handle progress
} errorBlock:^(QBResponse *response) {
NSLog(#"error: %#", response.error);
}];
Receive attachment
For example we use Content module to store attachments. Next snippets
allow to receive a message with an attachment and download it:
#pragma mark QBChatDelegate
- (void)chatDidReceiveMessage:(QBChatMessage *)message{
for(QBChatAttachment *attachment in message.attachments){
// download file by ID
[QBRequest TDownloadFileWithBlobID:[attachment.ID integerValue] successBlock:^(QBResponse *response, NSData *fileData) {
UIImage *image = [UIImage imageWithData:fileData];
} statusBlock:^(QBRequest *request, QBRequestStatus *status) {
// handle progress
} errorBlock:^(QBResponse *response) {
NSLog(#"error: %#", response.error);
}];
}
}
to obtain a link to attachment and use to show an image:
- (void)chatDidReceiveMessage:(QBChatMessage *)message{
for(QBChatAttachment *attachment in message.attachments){
// or if you have only file ID
NSString *privateUrl = [QBCBlob privateUrlForID:[attachment.ID integerValue]];
}
}
I hope it will be helpful for you.

Related

chat with quickblox using special characters iOS

I currently facing very strange issue with Quickblox, please anybody have any idea about this issue, help me out.
I am doing one to one chat and created private dialog for that.
I am sending message one user to other user like below:
QBChatMessage *message = [QBChatMessage message];
[message setText:#"Hello"];
message.dialogID = qb_dialog_id;
NSMutableDictionary *params = [NSMutableDictionary dictionary];
params[#"send_to_chat"] = #"1";
[message setCustomParameters:params];
[QBRequest createMessage:message successBlock:^(QBResponse *response, QBChatMessage *createdMessage) {
NSLog(#"success: %#", createdMessage);
} errorBlock:^(QBResponse *response) {
NSLog(#"ERROR: %#", response.error);
}];
This is work fine for me even any for special characters like "*,'$#!
And user will receive this messages whom i send the message from the delegate of quickblox method
- (void)chatDidReceiveMessage:(QB_NONNULL QBChatMessage *)message
Now the issue is, when i am sending message with '&' character other user will not get this message and my chat is also stop working and also not even call the delegate of receiver side.
But it is storing in the quickblox history that is in Chat module. So what is the issue with the '&' in QBRequest

How to update message status in ChatList using Quick blox sample?

I'm using Quick blox and I downloaded Sample app (https://github.com/QuickBlox/quickblox-ios-sdk/tree/master/sample-chat) which uses QMChatViewController, QMServices.
I am using MessageStatusStringBuilder class methods in ChatViewController to get the status (read/delivered/sent) of message (here this message is not a string it is an instance of QBChatMessage) in ChatViewController so that I'm showing the message status when ever QMChatServiceDelegate calls backs were called.
I have a requirement to show the status(read/delivered/sent) of last message in DialogsViewController under each dialog also.
But in DialogsViewController lastTextMessage is a string but not a QBChatMessage instance.
How to update this message status?
One plus point is I will get callbacks from this QMChatServiceDelegate in DialogsViewController also, even I can't find the status of message from that.
So how to handle this?
First you should get the message with the extended request using date_send as key and dialog's lastMessageDate as value. Then using the instance of the MessageStatusStringBuilder class you can get the status of the last message.
QBChatDialog *dialog = ... // your dialog
QBResponsePage *resPage = [QBResponsePage responsePageWithLimit:1 skip:0];
NSMutableDictionary *extendedRequest = #{#"date_sent" : [NSString stringWithFormat:#"%tu", (NSUInteger)[dialog.lastMessageDate timeIntervalSince1970]]}.mutableCopy;
[QBRequest messagesWithDialogID:dialog.ID extendedRequest:extendedRequest forPage:resPage successBlock:^(QBResponse *response, NSArray *messages, QBResponsePage *responcePage) {
NSLog(#"status = %#",[self.stringBuilder statusFromMessage:[messages firstObject]]);
} errorBlock:^(QBResponse *response) {
NSLog(#"error: %#", response.error);
}];

How to download an image using QuickBox API?

I'm trying to download an image file using Quickblox API. I can upload a file but when I try to download, NSData image doesn't show an image.
// Upload a user avatar, previously log in Quickblox API
NSData *avatar = UIImagePNGRepresentation([UIImage imageNamed:#"userWhite"]);
[QBRequest TUploadFile:avatar fileName:#"avatar.png" contentType:#"image/png" isPublic:YES successBlock:^(QBResponse *response, QBCBlob *blob) {
// Success
} statusBlock:^(QBRequest *request, QBRequestStatus *status) {
} errorBlock:^(QBResponse *response) {
}];
Image Upload: Image
Download avatar:
NSString* userProfilePictureID = [NSString stringWithFormat:#"%ld",(long)[[LocalStorageService shared] currentUser].blobID]; // user - an instance of QBUUser class
// download user profile picture
[QBRequest downloadFileWithUID:#"318547" successBlock:^(QBResponse *response, NSData *fileData) { UIImage* image = [UIImage imageWithData:fileData];
} statusBlock:^(QBRequest *request, QBRequestStatus *status) {
} errorBlock:^(QBResponse *response) {
}];
UIImage doesn't show any image. What can I do? NSData isn't corrupted.
Your download code looks right. You basically should call QBRequest method and pass blob.UID to it.
But in my case blob.UID is something like this 9357c3d66b944880a82cdbeb836f143c00. However there are steps I took to accomplish your task:
1) Sign up or login user
Either by calling +[QBRequest signUp:successBlock:errorBlock:] or +[QBRequest logInWithUserLogin:password:successBlock:errorBlock].
2) Enumerate through all available blobs for current user
[QBRequest blobsWithSuccessBlock:^(QBResponse* response,
QBGeneralResponsePage* page,
NSArray* blobs) {
[self findAndShowAvatarFromBlobs:blobs];
} errorBlock:^(QBResponse* response) { <...> }];
3) Find desired blob and download it
- (void)findAndShowAvatarFromBlobs:(NSArray*)blobs {
for (QBCBlob* blob in blobs) {
if ([blob.name hasPrefix:#"avatar"]) {
[QBRequest downloadFileWithUID:blob.UID
successBlock:^(QBResponse* response, NSData* fileData) {
UIImage* image = [UIImage imageWithData:fileData];
self.imageView.image = image;
}
statusBlock:^(QBRequest* request, QBRequestStatus* status) { <...> }
errorBlock:^(QBResponse* response) { <...> }];
}
}
}
Probably you have a problem with getting valid blob UID (I suspect that you are using blob ID which is not the same as UID). Is it possible for you to use the same kind of logic?
Full project you can find here: https://dl.dropboxusercontent.com/u/930742/so/QuickBloxSample.zip
It creates necessary user, uploads and then downloads image with showing it in UIImageView demonstrating all described steps. (Don't forget to set your service and application keys in AppDelegate)
P.S. In admin panel you can find blob UID by clicking on its ID in Content table

Google Drive iOS: Upload HTML file to overwrite an existing Docs file

I am trying to write an application that will pull down the contents of a Google Docs file as HTML to allow me to edit it inside the app. After editing the html file I then want to upload the changes back to Google Drive and update the contents of the original Google Docs file. I have been able to pull down the Google Docs file but am not able to upload my changes back to the server.
Can you please help to understand why this error is happening ? And possibly advise me on a fix for the issue ?
I am getting the following NSError:
Error Domain=com.google.GTLJSONRPCErrorDomain Code=500 "The operation couldn’t be completed. (Internal Error)" UserInfo=0x157a8610 {error=Internal Error, GTLStructuredError=GTLErrorObject 0x16846f60: {message:"Internal Error" code:500 data:[1]}, NSLocalizedFailureReason=(Internal Error)}
2014-06-17 12:11:35.188 DrEdit[548:60b] Error UserInfo: {
GTLStructuredError = "GTLErrorObject 0x16846f60: {message:\"Internal Error\" code:500 data:[1]}";
NSLocalizedFailureReason = "(Internal Error)";
error = "Internal Error";
}
Please code being executed when uploading below:
- (void)saveFile {
GTLUploadParameters *uploadParameters = nil;
// Only update the file content if different.
if (![self.originalContent isEqualToString:self.textView.text]) {
// NSData *fileContent =
// [self.textView.text dataUsingEncoding:NSUTF8StringEncoding];
NSAttributedString *s = self.textView.attributedText;
NSDictionary *documentAttributes = [NSDictionary dictionaryWithObjectsAndKeys:NSHTMLTextDocumentType, NSDocumentTypeDocumentAttribute, nil];
NSData *htmlData = [s dataFromRange:NSMakeRange(0, s.length) documentAttributes:documentAttributes error:NULL];
// NSString *htmlString = [[NSString alloc] initWithData:htmlData encoding:NSUTF8StringEncoding];
// NSData *fileContent = [self.textView.attributedText convertToData];
uploadParameters = [GTLUploadParameters uploadParametersWithData:htmlData MIMEType:#"text/html"];
// [GTLUploadParameters uploadParametersWithData:fileContent MIMEType:#"text/plain"];
// [GTLUploadParameters uploadParametersWithData:fileContent MIMEType:#"application/vnd.google-apps.document"];
}
self.driveFile.title = self.updatedTitle;
GTLQueryDrive *query = nil;
if (self.driveFile.identifier == nil || self.driveFile.identifier.length == 0) {
// This is a new file, instantiate an insert query.
query = [GTLQueryDrive queryForFilesInsertWithObject:self.driveFile
uploadParameters:uploadParameters];
} else {
// This file already exists, instantiate an update query.
query = [GTLQueryDrive queryForFilesUpdateWithObject:self.driveFile
fileId:self.driveFile.identifier
uploadParameters:uploadParameters];
}
UIAlertView *alert = [DrEditUtilities showLoadingMessageWithTitle:#"Saving file"
delegate:self];
[self.driveService executeQuery:query completionHandler:^(GTLServiceTicket *ticket,
GTLDriveFile *updatedFile,
NSError *error) {
[alert dismissWithClickedButtonIndex:0 animated:YES];
if (error == nil) {
self.driveFile = updatedFile;
self.originalContent = [self.textView.text copy];
self.updatedTitle = [updatedFile.title copy];
[self toggleSaveButton];
[self.delegate didUpdateFileWithIndex:self.fileIndex
driveFile:self.driveFile];
[self doneEditing:nil];
} else {
NSLog(#"An error occurred: %#", error);
NSLog(#"Error UserInfo: %#", error.userInfo);
[DrEditUtilities showErrorMessageWithTitle:#"Unable to save file"
message:[error description]
delegate:self];
}
}];
}
Thanks,
Michael
Its not possible to write html to a gdoc programmatically.
Currently its only possible to manually paste html but not with an api unfortunately (and strangely)
I was able to solve this problem by changing the property convert to YES on the GTLQueryDrive class. The documentation states that it will attempt to convert the file being uploaded into a native Google Docs format.
Hope this helps. Please see the method I am describing from the SDK below:
// Method: drive.files.update
// Updates file metadata and/or content
// Required:
// fileId: The ID of the file to update.
// Optional:
**// convert: Whether to convert this file to the corresponding Google Docs
// format. (Default false)**
// newRevision: Whether a blob upload should create a new revision. If false,
// the blob data in the current head revision will be replaced. (Default
// true)
// ocr: Whether to attempt OCR on .jpg, .png, or .gif uploads. (Default false)
// ocrLanguage: If ocr is true, hints at the language to use. Valid values are
// ISO 639-1 codes.
// pinned: Whether to pin the new revision. (Default false)
// setModifiedDate: Whether to set the modified date with the supplied
// modified date. (Default false)
// sourceLanguage: The language of the original file to be translated.
// targetLanguage: Target language to translate the file to. If no
// sourceLanguage is provided, the API will attempt to detect the language.
// timedTextLanguage: The language of the timed text.
// timedTextTrackName: The timed text track name.
// updateViewedDate: Whether to update the view date after successfully
// updating the file. (Default true)
// Upload Parameters:
// Maximum size: 10GB
// Accepted MIME type(s): */*
// Authorization scope(s):
// kGTLAuthScopeDrive
// kGTLAuthScopeDriveFile
// Fetches a GTLDriveFile.
+ (id)queryForFilesUpdateWithObject:(GTLDriveFile *)object
fileId:(NSString *)fileId
uploadParameters:(GTLUploadParameters *)uploadParametersOrNil;
Thanks,
Michael

Twitter The operation couldn’t be completed. (com.apple.accounts error 6.)?

I want to upload image to Twitter.
I wrote code as
- (void)postImage:(UIImage *)image withStatus:(NSString *)status
{
NSLog(#"Share on Twitter");
ACAccountType *twitterType =
[self.accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
SLRequestHandler requestHandler =
^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
if (responseData) {
NSInteger statusCode = urlResponse.statusCode;
if (statusCode >= 200 && statusCode < 300) {
NSDictionary *postResponseData =
[NSJSONSerialization JSONObjectWithData:responseData
options:NSJSONReadingMutableContainers
error:NULL];
NSLog(#"[SUCCESS!] Created Tweet with ID: %#", postResponseData[#"id_str"]);
}
else {
NSLog(#"[ERROR] Server responded: status code %d %#", statusCode,
[NSHTTPURLResponse localizedStringForStatusCode:statusCode]);
}
}
else {
NSLog(#"[ERROR] An error occurred while posting: %#", [error localizedDescription]);
}
};
ACAccountStoreRequestAccessCompletionHandler accountStoreHandler =
^(BOOL granted, NSError *error) {
if (granted) {
NSArray *accounts = [self.accountStore accountsWithAccountType:twitterType];
NSURL *url = [NSURL URLWithString:#"https://api.twitter.com"
#"/1.1/statuses/update_with_media.json"];
NSDictionary *params = #{#"status" : status};
SLRequest *request = [SLRequest requestForServiceType:SLServiceTypeTwitter
requestMethod:SLRequestMethodPOST
URL:url
parameters:params];
NSData *imageData = UIImageJPEGRepresentation(image, 1.f);
[request addMultipartData:imageData
withName:#"media[]"
type:#"image/jpeg"
filename:#"image.jpg"];
[request setAccount:[accounts lastObject]];
[request performRequestWithHandler:requestHandler];
}
else {
NSLog(#"[ERROR] An error occurred while asking for user authorization: %#",
[error localizedDescription]);
}
};
[self.accountStore requestAccessToAccountsWithType:twitterType
options:NULL
completion:accountStoreHandler];
}
I am getting error as
The operation couldn’t be completed. (com.apple.accounts error 6.)
You should use the SLComposeViewController class. In order to do this, a number of steps should be performed in sequence. Firstly, the application may optionally check to verify whether a message can be sent to the specified social network service. This essentially equates to checking if a valid social network account has been configured on the device and is achieved using the isAvailableForServiceType: class method, passing through as an argument the type of service required from the following options:
SLServiceTypeFacebook
SLServiceTypeTwitter
SLServiceTypeSinaWeibo
The following code, for example, verifies that Twitter service is available to the application:
if ([SLComposeViewController isAvailableForServiceType:SLServiceTypeTwitter])
{
// Device is able to send a Twitter message
}
This method call is optional and, in the event that an account for the specified social network has yet to be set up, the composer will simply take the user to the device’s Settings application where a Twitter account may be configured.
The next step is to create an instance of the SLComposeViewController class and supply an optional completion handler to be called when the composer screen is either cancelled by the user or used to send a message. Next, a range of methods may be called on the instance to initialize the object with the content of the message, including the initial text of the message, an image attachment and a URL:
setInitialText: - Sets the initial text of the message on the SLComposeViewController instance.
addImage: - Adds image files as attachments to the message.
addURL: - Adds a URL to the message. The method automatically handles the URL shortening.
Each of the above methods returns a Boolean result indicating whether the addition of content was successful.
Finally, when the message is ready to be presented to the user, the SLComposeViewController object is presented modally by calling the presentViewController: method of the parent view controller:
SLComposeViewController *composeController = [SLComposeViewController
composeViewControllerForServiceType:SLServiceTypeTwitter];
[composeController setInitialText:#"Just found this great website"];
[composeController addImage:postImage.image];
[composeController addURL: [NSURL URLWithString:
#"http://www.website.com"]];
[self presentViewController:composeController
animated:YES completion:nil];
Once called, this method will present the composer view to the user primed with any text, image and URL contents pre-configured via the method calls. Once displayed, the user has the option to modify the text of the message, cancel the message, add location data or send the message. If a completion handler has been configured it will be called and passed a value indicating the action that was taken by the user within the composer view. Possible values are:
SLComposeViewControllerResultCancelled – The user cancelled the composition session by touching the Cancel button.
SLComposeViewControllerResultDone – The user sent the composed message by touching the Send button.

Resources