I'm working on using the ObjectiveFlickr library to upload photos to Flickr from my iPhone app. I am able to authorize the app and perform general requests, but I am getting an error while trying to upload a photo. The photo is meant to be uploaded is an image captured using AVFoundation. Here is the relevant code:
UIImage *image = [[UIImage alloc] initWithData:imageData];
if ([[AppDelegate sharedDelegate].apiContext.OAuthToken length]) {
NSData *uploadData = UIImageJPEGRepresentation(image, 1);
if (!flickrRequest) {
flickrRequest = [[OFFlickrAPIRequest alloc] initWithAPIContext:[AppDelegate sharedDelegate].apiContext];
flickrRequest.delegate = self;
flickrRequest.requestTimeoutInterval = 60.0;
}
[flickrRequest uploadImageStream:[NSInputStream inputStreamWithData:uploadData] suggestedFilename:#"Test" MIMEType:#"image/jpeg" arguments:[NSDictionary dictionaryWithObjectsAndKeys:#"0", #"is_public", nil]];
[UIApplication sharedApplication].idleTimerDisabled = YES;
NSLog(#"Can upload photo");
The flickrRequest object is defined and #property'd in the .h file pertaining to the code above.
The OFFlickrRequestDelegate methods are as follows:
- (void)flickrAPIRequest:(OFFlickrAPIRequest *)inRequest imageUploadSentBytes:(NSUInteger)inSentBytes totalBytes:(NSUInteger)inTotalBytes {
NSLog(#"Success");
}
- (void)flickrAPIRequest:(OFFlickrAPIRequest *)inRequest didCompleteWithResponse:(NSDictionary *)inResponseDictionary {
NSLog(#"%s %# %#", __PRETTY_FUNCTION__, inRequest.sessionInfo, inResponseDictionary);
}
- (void)flickrAPIRequest:(OFFlickrAPIRequest *)inRequest didFailWithError:(NSError *)inError {
NSLog(#"%s %# %#", __PRETTY_FUNCTION__, inRequest.sessionInfo, inError);
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:[inError description] delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert show];
}
When I run the project on the device the console shows:
Can upload photo
Success
Success
Success
Success
flickrAPIRequest:didFailWithError:(null) Error Domain=org.lukhnos.ObjectiveFlickr Code=2147418115 "The operation couldn’t be completed. (org.lukhnos.ObjectiveFlickr error 2147418115.)"
Searching through the API's documentation, "error 2147418115" is defined as "OFFlickrAPIRequestFaultyXMLResponseError". I'm not really sure what this means though. Also strange--"Success" appears four times when I'm only attempting to upload one photo.
The sample app utilizing ObjectiveFlickr, "Snap and Run" uploads photos fine on the same device that I am testing on. Comparing the code between my app and Snap and Run, I don't see any major differences that could cause the photo not to upload.
Any help would be greatly appreciated.
That is strange. OFFlickrAPIRequestFaultyXMLResponseError means the returned data cannot be parsed as XML. If the sample app SnapAndRun runs correctly and yours don't, I suggest add one line in ObjectiveFlickr.m, right after the line NSString *stat = [rsp objectForKey:#"stat"];:
NSString *dataString = [[[NSString alloc] initWithData:[request receivedData] encoding:NSUTF8StringEncoding] autorelease];
NSLog(#"received response: %#", dataString);
This may help you find out what goes wrong (e.g. if it's a server-side issue, or some response format that the library missed).
When I got this error I used Charles to see what was going on. Flickr was sending back an error saying that the signature was invalid. Looking at my request, I found that I had reversed the order of the key and values (i.e. there was whitespace in one of my keys, which probably caused a signature error).
Related
I was using the following code for checking the internet connection in my first iOS app (almost 3 years ago).
NSError *err = nil;
NSStringEncoding encoding;
NSString * connectionstring = [[NSString alloc] initWithContentsOfURL:[NSURL URLWithString:#"http://www.google.com"] usedEncoding:&encoding error:&err];
if(connectionstring.length ==0)
{
UIAlertView * alert = [[UIAlertView alloc] initWithTitle:#"Error Occured" message:#"No Internet Connection." delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
[alert release];
}
else
{
// loading another screen
}
The problem is in India and US it is going into the else condition but in Belgium it is going into the if condition and throwing the error. So are there any restrictions for Google in Belgium?
If it is tagged incorrectly please guide me. In my current versions solved this issue by using Rechability classes to check this . Just I wanted to know about it . Thanks in advance.
As a first step, look at the encoding.
You can log the encoding right after the connectionstring is created by inserting
NSLog(#"encoding: %#", [NSString localizedNameOfStringEncoding:encoding]);
into your code.
For further debugging, you could try loading the url into an NSData object first, then inspect the data and finally create a NSString from the data.
Alternative solution: To check internet connection Use Reachability class provided by apple.
Download Apple Sample Here, add Reachability class to your project.
- (BOOL)isConnected
{
Reachability *reachability = [Reachability reachabilityForInternetConnection];
NetworkStatus networkStatus = [reachability currentReachabilityStatus];
return !(networkStatus == NotReachable);
}
Instead of using google.com use any local client server test url for internet checking it will also be very fast responsive comparatively of any other way of internet validation.
Upgrading my app. Target is iOS5.1. Xcode 4.5.2 and am using FacebookSDK 3.0 along with Twitter Frameworks.
App is logging into Facebook without issue. When I attempt to publish a post, I get this returned in the log:
2012-12-18 10:39:31.934 MyApp[31754:1d603] Error Domain=com.facebook.sdk Code=5
"The operation couldn’t be completed. (com.facebook.sdk error 5.)"
UserInfo=0xab74630 {com.facebook.sdk:ParsedJSONResponseKey={
body = {
error = {
code = 100;
message = "(#100) Missing message or attachment";
type = OAuthException;
};
};
code = 400;
}, com.facebook.sdk:HTTPStatusCode=400}
2012-12-18 10:39:31.935 MyApp[31754:1d603] (null)
This last line is the result of a log expression to list the "postParams" in the "publishStory" method listed below. Note that it is (null).
The error result in simulator is "error: domain = com.facebook.sdk, code = 5"
I used the Facebook tutorial to build the FB interface. I've got the params listed in initWithNibName, just as the tutorial indicates.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// this stuff will change... just get it working
self.postParams = [[NSMutableDictionary alloc] initWithObjectsAndKeys:
#"Share...", #"message",
#"http://MyApp.com", #"link",
#"icon.png", #"picture",
#"MyApp", #"name",
#"A wonderful way to record your life events.", "caption",
#"Easy to use.", #"description",
nil];
}
return self;
}
Then, the "publish" is in a separate method, which is where it stops and I get the above error.
- (void)publishStory
{
[FBRequestConnection
startWithGraphPath:#"me/feed"
parameters:_postParams
HTTPMethod:#"POST"
completionHandler:^(FBRequestConnection *connection,
id result,
NSError *error) {
NSString *alertText;
if (error) {
NSLog(#"%#",error);
NSLog(#"%#", _postParams);
alertText = [NSString stringWithFormat:
#"error: domain = %#, code = %d",
error.domain, error.code];
} else {
alertText = [NSString stringWithFormat:
#"Posted action, id: %#",
[result objectForKey:#"id"]];
}
// Show the result in an alert
[[[UIAlertView alloc] initWithTitle:#"Result"
message:alertText
delegate:self
cancelButtonTitle:#"OK!"
otherButtonTitles:nil]
show];
}];
}
I think, that the actual params are not being uploaded. I've been searching for several days trying to find a solution.
Anyone have an idea of how to fix this and get the post to complete? Any help would be greatly appreciated!
I Had a similar problem, but my problem was that the postParams weren't retained because I didn't use a property and I was creating the postParams in the same publish method. The parameters need to me retained somewhere in the class.
Assure that your property is using retain, also make sure that the init method is being called.
I have implemented the NSStream delegate. I have implemented the same as Witap Application
In that, I have implemented handleEvent delegate
- (void) stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode{
switch(eventCode) {
case NSStreamEventOpenCompleted:
{
[tcpServer release];
tcpServer = nil;
break;
}
case NSStreamEventHasBytesAvailable:
{
//done my stuff here
}
case NSStreamEventErrorOccurred:
{
UIAlertView *wifiLostAlert = [[UIAlertView alloc] initWithTitle:#"Wifi
connection error" message:#"" delegate:nil cancelButtonTitle:#"Continue" otherButtonTitles:nil];
[wifiLostAlert show];
[wifiLostAlert release];
wifiLostAlert = nil;
}
}
In my client site, they reported an issue as
"Multiple time when we was either trying to send a message to the
learner or synching devices she got the following message: “Wifi
connection error.
Same happend at 2 different networks and it doesnot recover quickly
even if the network is pretty strong signal."
Unfortunately, I am unable to reproduce this issue in my site and it's working fine in another client site too!!.
Any clue's regarding the issue. Any help on this is appreciated.
Thank you.
I would recommend you supply the client with an updated version that displays more information about what error is actually occurring.
You can get more information about the error using:
NSError* error = [stream streamError];
You can find more information about NSError at NSError Class Reference.
Something like this might work in your case:
NSString* errorMessage = [NSString stringWithFormat:#"%# (Code = %d")",
[error localizedDescription],
[error code]];
Then change your UIAlertView to this:
UIAlertView *wifiLostAlert = [[UIAlertView alloc]
initWithTitle:#"Stream Error"
message:errorMessage
delegate:nil
cancelButtonTitle:#"Continue"
otherButtonTitles:nil];
This won't solve the problem but will give both you and your client more information about the root cause is.
For example, you may find the error is "Connection refused." which would point to a problem not with WiFi signal strength but in the server-side software.
Good luck!
I used ELCImagePickerController in my app.
but when we start our application first time and on Image gallery it will ask for accessing user location , if we don't allow to access user location to it then it will give error in UIAlertView and it wont show image gallery.
But after that if we go to setting app -> location services -> [turn on switch for access location for our app] then start app -> go to gallery page -> we can show image gallery in our app.
So my question is how can we show image gallery with ELCImagePickerController with location services turn off for our app or user don't allow to access location to our app.
ELCImagePickerController can be downloadable at this LINK
Then find ELCAlbumPickerController.m file then go to View Did Load then this causes error alert when user location access turned off,
dispatch_async(dispatch_get_main_queue(), ^
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// Group enumerator Block
void (^assetGroupEnumerator)(struct ALAssetsGroup *, BOOL *) = ^(ALAssetsGroup *group, BOOL *stop)
{
if (group == nil)
{
return;
}
[self.assetGroups addObject:group];
// Keep this line! w/o it the asset count is broken for some reason. Makes no sense
NSLog(#"count: %d", [group numberOfAssets]);
// Reload albums
[self performSelectorOnMainThread:#selector(reloadTableView) withObject:nil waitUntilDone:YES];
};
// Group Enumerator Failure Block
void (^assetGroupEnumberatorFailure)(NSError *) = ^(NSError *error) {
UIAlertView * alert = [[UIAlertView alloc] initWithTitle:#"Error" message:[NSString stringWithFormat:#"Album Error: %#", [error description]] delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[alert show];
[alert release];
NSLog(#"A problem occured %#", [error description]);
};
// Enumerate Albums
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library enumerateGroupsWithTypes:ALAssetsGroupAll
usingBlock:assetGroupEnumerator
failureBlock:assetGroupEnumberatorFailure];
[library release];
[pool release];
});
The answer is that you can't show the image gallery with ELCImagePickerController with location services turned off.
ELCImagePickerController uses the Assets Library Framework to access the device's photo album. Because this framework also gives access to the metadata of the photos - including location data - the user needs to grant permission for the app to use Location Services.
There's no way around this, except if you use the standard UIImagePickerController (but I assume that won't cover the requirements for your app)
I know - I have read the documentation - but frankly Facebook is horrible at it. I can't figure out how to send a request that illicits a response. Here's what I'm trying:
NSURL *fbID = [NSURL URLWithString:#"https://graph.facebook.com/me?fields=id"];
fbUserID = [[NSData alloc] initWithContentsOfURL: fbID];
Where should this code go? Is there a specific class it is looking for if I have set 'self' as delegate?
How are you trying to integrate FB into your app? I have been looking into Facebook connect recently and found their documentation very helpful (http://developers.facebook.com/docs/guides/mobile/#ios). I know you said you looked at the documentation, but for me after going through their steps for iOS I was able to make an app that allowed users to sign in and give me access to their basic information, including ID. After going through authorization, I had the following code in my app delegate:
- (void) fbDidLogin {
//get information about the currently logged in user
[facebook requestWithGraphPath:#"me" andDelegate:self];
}
- (void)request:(FBRequest *)request didLoad:(id)result {
NSString *name = [result objectForKey:#"name"];
NSString *msg = [[NSString alloc] initWithFormat:#"To prove this works, your name is %#",name];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Thanks for Logging In!"
message:msg
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
[alert release];
}
This gets the user's full name after logging in and displays it. You can do the same thing for getting their ID.