Cannot get the MPMoviePlayerViewController to play my media file - iphone

Having some issues getting this MPMoviePlayerViewController to work. I have two sample URLs pointing to the same Quicktime movie. The commented out URL doesn't work; the other one works fine.
I've monitored both via Fiddler and I can't see any issues in headers/etc.
Basically I'm trying to figure out a way to play an Azure hosted media file with some sort of security; either via pass through WCF service. Any one have this figured out? I'm pulling my hair out.
//NSString *moviePath = [[NSString alloc] initWithString:#"http://www.nov8rix.com/Services/CPipeline.svc/Media/42"];
NSString *moviePath = [[NSString alloc] initWithString:#"http://nov8rixstorage.blob.core.windows.net/searchpad/tutorial_portrait.mov"];
NSURL *url = [NSURL URLWithString:moviePath];
[url retain];
MPMoviePlayerViewController *mp = [[MPMoviePlayerViewController alloc] initWithContentURL:url];
[self presentMoviePlayerViewControllerAnimated:mp];
[mp release];
[url release];
Update: This is the error I'm receiving:
NSConcreteNotification 0x892e540 {name = MPMoviePlayerPlaybackDidFinishNotification; object = <MPMoviePlayerController: 0x8921570>; userInfo = {
MPMoviePlayerPlaybackDidFinishReasonUserInfoKey = 1;
error = "Error Domain=MediaPlayerErrorDomain Code=-12939 \"The server is not correctly configured.\" UserInfo=0x892ecb0 {NSLocalizedDescription=The server is not correctly configured.}";
A brief search on the web mentions that my problem may be that my media connection doesn't support byte Range Requests. This is probably true. Is there a way to allow Range Requests with WCF?

Yay I finally got this to work! The reason it was not working was because my WCF services didn't support Range Requests. Apparently iPhone Movie streaming requires range requests.
I changed my implementation to make direct requests to the Azure blob storage via SAS URLs. Works so far!

Thanks for posting your answer. I had the same error with my MPMoviePlayerViewController, and my problem was fixed too when I added support for Range Requests to my php mp4 file streamer. Streaming media to the iPHone requires some specific headers, else you get the "The server is not correctly configured" error.
I found some great hints for php Range Requests support here:
fread, (PHP 4, PHP 5), fread — Binary-safe file read

Related

Network push notification

I am wondering if there is a simple way to push a notification, to all your users currently using your application.
So the next time they launch the application and they are connected to Wi-Fi, they receive a alert telling them that, i.e., "An update is available".
EDIT:
To explain in greater detail what I am looking for. I am developing an application that should only be used when it is the most recent version of the software, so I would like to be able to send out a message (notification) for when an update is available in the AppStore. This is seen in some games such as AngryBirds and Cut the Rope.
Maybe even change a BOOL in the code to TRUE, leaving a red flag if{} BOOL is TRUE. (Of course first I'd like an answer to the more basic version. This would be helpful though as well)
Hope this clears things up.
With regards,
SirKaydian
Local Notification Solution
Essentially what Oscar said previously, you could make this really simple. If you wanted to check after every launch of the application you could easily call some sort of local API (or similar) call from your application to a web service you might host. So for example you have a PHP file:
<?php
$currentVersion = 1.3;
echo $currentVersion;
?>
That simple PHP script can be updated by you whenever you release an update. The iPhone can recognize this by querying that PHP file on every startup (check NSURLConnection delegate methods to get the response from any particular URL). Now from previous checks by your application it can store those in an NSUserDefaults value by the following:
NSUserDefaults *defaults = [[NSUserDefaults alloc] init];
NSString *loadedVersion = [defaults valueForKey:#"MYAPP_CURR_VERSION"];
Now we need to compare the two from your NSURLConnection delegate method that receives the string back from the PHP file on your web service.
NSMutableURLRequest *urlRequest = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:#"http://www.website.com/folder/version.php"]];
[urlRequest setHTTPMethod:#"GET"];
[urlRequest setHTTPBody:[postParams dataUsingEncoding:NSUTF8StringEncoding]];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:urlRequest delegate:self startImmediately:YES];
[connection start];
The above code will send the request to your server URL that you tell it to. Now when we get the response we'll do it like this:
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
NSString *responseVersionFromServer = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
if(![loadedVersion isEqualToString:responseVersionFromServer]) {
//execute code here to show a local notification or UIAlertView
}
}
That will do all the comparison for you.
NOTE: You must add NSURLConnectionDelegate in your .h Header file!
Push Notifications Solution
There are services out there for allowing your application to have push notifications such as Urban Airship that you can log into and send a push notification to all of your users when an update becomes available. It's really simple to use, check out their website. (www.urbanairship.com)
You could consume a webservice and compare versions of your app (maybe save the version to NSUserDefaults), I'm sure there are other solutions but this one comes to mind. You could show an alert that links to the app store if the versions are different.

Inconsistency with MGTwitterEngine for iOS?

Before, MGTwitterEngine was working perfectly for me, but now everytime I login, i get an invalid url exception from OAuth. I thought it was because i changed something but when I tried logging in from the iphone simulator, it worked (i was trying from my iphone). I then tried an old copy of my project from 3 days ago when i had absolutely no problem, and now i'm getting the same url error. Has anybody encountered this?
To temporarily fix this, I went into SA_OauthTwitterEngine.m and did
- (SA_OAuthTwitterEngine *) initOAuthWithDelegate: (NSObject *) delegate {
if (self = (id) [super initWithDelegate: delegate]) {
self.requestTokenURL = [NSURL URLWithString: #"http://twitter.com/oauth/request_token"];
//self.accessTokenURL = [NSURL URLWithString: #"http://twitter.com/oauth/access_token"];
self.accessTokenURL = [NSURL URLWithString: #"https://api.twitter.com/oauth/access_token"];
self.authorizeURL = [NSURL URLWithString: #"http://twitter.com/oauth/authorize"];
}
return self;
}
There was a problem with the http://twitter.com/oauth/access_token url so I changed it to https://api.twitter.com/oauth/access_token which was in the documentation for the twitter API. It just feels uncomfortable having to alter this since it seems to be working fine for everybody else.
Any help is appreciated
As you can see on https://dev.twitter.com/docs/api/1/post/oauth/access_token,
Twitter recommends using HTTPS instead of HTTP, so even if it worked many times before you changed to HTTPS, don't feel uncomfortable! Sometimes, a line of code works well, but another one works better. There's nothing uncomfortable in it !
Please use HTTPS for this method, and all other OAuth token
negotiation steps.
Resource URL https://api.twitter.com/oauth/access_token
Hope it answers your question.

ASIHTTPRequest problem with parameters using 3G conneciton (Fine with Wifi)

I have one user of my iPhone application who is complaining it does not work when using his mobile data connection (but works fine via Wifi). My application make a request to a third party REST API and I use the ASIHTTPRequest library for this.
One parameter of my HTTP request is a username (which is an email address), so I encode the username using the following code:
-(NSString *) encodeString:(NSString *) string
{
NSString * returnString = (NSString *)CFURLCreateStringByAddingPercentEscapes(
NULL,
(CFStringRef) string,
NULL,
(CFStringRef)#"!*'();:#&=+$,/?%#[]",
kCFStringEncodingUTF8 );
return [returnString autorelease];
}
This then gets built into a URL as follows:
// Setup the url we need to make the request to the sharkscope API
NSString * urlString = [NSString stringWithFormat: #"%SERVICEADDRESSHERE?Username=%#&Password=%#",
encodedUserName, m_md5Key];
NSURL * url = [NSURL URLWithString:urlString];
request = [[ASIHTTPRequest requestWithURL:url] retain];
What get's sent out of my application is a request with the following Username:
Username=Fred.Bloggs%40wanadoo.fr
For this one user, what is received at the server when using his mobile data connection is:
Username=Fred.Bloogs%2540wanadoo.fr
So clearly the % character is being encoded somewhere between me making the call to requestWithURL and it arriving at the server. I can't understand the reason because I have hundreds of other users who can run the requests fine via their data connection.
Do I even need to encode the values passed into requestWithURL?
Does anyone have any idea at what stage the % character is being re-encoded. I'm guessing it must be in ASIHTTP library, but can't work out what circumstances would trigger it in this case.
The corruption is probably happening because of a proxy or transparent proxy on the 3G connection, put in place by the carrier.
Possibly workounds:
Use POST instead of GET
Use https instead of http
Use http on a non-standard port
To prove this theory, you could try asking him to enter the same / similar request in Safari on iOS when he's using the 3g connection.

How to get search results in XML format

I am planning to make an iPhone search app. the user types in the search string. the string will be searched by some search engines like Google, Live, Yahoo ...
I need to get the search result in the XML format. Is there any way to do this. Help needed. Please.
Thanks and regards,
Shibin
A RESTful search request to Google AJAX returns a response in JSON format. JSON is a like a very highly stripped-down version of XML.
Google doesn't make its SOAP interface available any longer, so I don't know if you'll be able to get XML from them, at least through a public interface. Luckily for you, JSON responses are trivial to request and to parse on the iPhone.
You can issue the request with ASIHTTPRequest and parse the JSON-formatted response on an iPhone with json-framework.
For example, to create and submit a search request that is based on the example on the Google AJAX page, you could use ASIHTTPRequest's -requestWithURL and -startSynchronous methods:
NSURL *searchURL = [NSURL URLWithString:#"http://ajax.googleapis.com/ajax/services/search/web?v=1.0&q=Paris%20Hilton"];
ASIHTTPRequest *googleRequest = [ASIHTTPRequest requestWithURL:searchURL];
[googleRequest addRequestHeader:#"Referer" value:[self deviceIPAddress]];
[googleRequest startSynchronous];
You would build the NSURL instance based on your search terms, escaping the request parameters.
If I followed Google's example to the letter, I would also add an API key to this URL. Google asks that you use an API key for REST searches. You should sign up for an API key over here and add it to your requests.
You should also specify the referer IP address in the request header, which in this case would be the local IP address of the iPhone, e.g.:
- (NSString *) deviceIPAddress {
char iphoneIP[255];
strcpy(iphoneIP,"127.0.0.1"); // if everything fails
NSHost *myHost = [NSHost currentHost];
if (myHost) {
NSString *address = [myHost address];
if (address)
strcpy(iphoneIP, [address cStringUsingEncoding:NSUTF8StringEncoding]);
}
return [NSString stringWithFormat:#"%s",iphoneIP];
}
There are also asynchronous request methods which are detailed in the ASIHTTPRequest documentation. You would use those to keep the iPhone UI from getting tied up while the search request is made.
In any case, once you have Google's JSON-formatted response in hand, you can use the json-framework SBJSON parser object to parse the response into an NSDictionary object:
NSError *requestError = [googleRequest error];
if (!requestError) {
SBJSON *jsonParser = [[SBJSON alloc] init];
NSString *googleResponse = [googleRequest responseString];
NSDictionary *searchResults = [jsonParser objectWithString:googleResponse error:nil];
[jsonParser release];
// do stuff with searchResults...
}
There are different web service API's available. I would recommend that you use those.
Google Search API: http://code.google.com/intl/sv-SE/apis/ajaxsearch/web.html
Google JS API's often return JSON. But that's easy to work with too. You should easily be able to transform the JSON to XML if needed.

Tracking iPhone on Yahoo Web Analytics using ASIHTTPRequest

I'm trying to track an event in my app using Yahoo Web Analytics. The code I am using looks like
ASIHTTPRequest *yahooTrack = [ASIHTTPRequest requestWithURL:
[NSURL URLWithString:#"http://s.analytics.yahoo.com/p.pl?a=xxxxxxxxxxxxx&js=no&b=yyyyyyyyyyyy&cf6=zzzzzzzzzzz"]];
yahooTrack.didFinishSelector = #selector(statisticsFinished:);
yahooTrack.delegate = self;
[yahooTrack startAsynchronous];
Then the statisticsFinished looks like:
NSLog(#"Cookies: %#", request.requestCookies);
NSLog(#"Redircount: %d", [request redirectCount]);
NSLog(#"Responsecode %d %#\nMsg: %#", request.responseStatusCode,
request.responseStatusMessage, [request responseString]);
And all the information I get back looks correct. Cookies are set, redirectcount is 1 the first time (as it redirects to s.analytics.yahoo.com/itr.pl?.... a normal browser does). Then the redirectcount is 0 for subsequent request until the app is restarted and session cleared. The responseString returns GIF89a.
Even if the data looks correct, Yahoo still won't track. As soon as I call the tracking url directly in my browser it works as expected.
I realize Flurry is a better option, but I'm forced to use Yahoo in this case. Also, using a UIWebView probably would work, but I'm against putting in a webview just for tracking purposes.
Is there any difference in how ASIHTTPRequest and Safari would handle a call to a simple URL as this? Or do you see anything else that could explain why the tracking isn't working?
I finally found the problem. ASIHTTPRequest creates a user-agent based on your applications name, and requests from this user agent is ignored by Yahoo somehow (bug?). As stated in the documentation, you can override the user-agent as follows:
[request addRequestHeader:#"User-Agent" value:#"My-User-Agent-1.0"];
I used the user-agent string of Safari on iPhone, and it worked immediately! BTW; the same problem applies for Android, and the same fix works.