MPMoviePlayerController reconnecting multiple times - iphone

I have a simple HTTP server running that pretty much just serves an MP3 file in chunks of equal size. I'm writing an iOS app (for testing purposes), that basically takes a URL and streams the file through MPMovieController. Here's my sample code:
MPMoviePlayerController *mp = [[MPMoviePlayerController alloc] init];
[mp setMovieSourceType:MPMovieSourceTypeStreaming];
mp.contentURL = [NSURL URLWithString:#"http://127.0.0.1:8080"];
[mp play];
It works. BUT: on my http server I see multiple connections (first one breaks right away, second one streams to the end usually, although sometimes there is 3rd connection).
I know it's not the server issue, since when I do this:
NSData *myData = [NSData dataWithContentsOfURL:[NSURL URLWithString:#"http://127.0.0.1:8080"]];
...then there's only 1 connection that finishes reading and disconnects.
The question is: Why does MPMoviePlayerController need to establish and break those connections before finishing reading the file, why doesn't it just keep waiting for more data to be written on the socket? I haven't been able to find any relevant docs that would explain this :(
P.S. If you are curious why I need this, here's a short explanation: I'm trying to emulate real life network scenarios where bytes are received by the MPMovieController in chunks with small delays of random length in between

You need to modify your server and add support for HTTP 206 Partial Content requests/responses. iOS requests movie data over HTTP this way.

Related

iOS - 3G slow connection issue when connecting to back-end API server

Currently I am working on an App which requires several calls to a back-end server.
When on WiFi the App connects fine and downloads very fast the data, but when on 3G the connection seems a bit unstable and very slow.
So I have done some very simple test case (which you find below). And it seems that NSURLConnection is not getting data at the same response speed.
(Do note that I have removed the URL of the real server I connected to)
Test cases:
Placed on a server the following php script:
<?php echo 'hello world' ?>
Grabbed an iPhone, put WiFi off and made sure it had a proper 3G connection.
Used the following Objective-C code to connect to the server:
NSURL * url = [NSURL URLWithString:#"http://someserver.com/test.php"];
NSURLRequest * request = [NSURLRequest requestWithURL:url];
NSDate * startDate = [NSDate date];
NSLog(#"START");
NSURLConnection * connection = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSLog(#"%3.2f", -[startDate timeIntervalSinceNow]);
This returns on 3G - 1.47 seconds. So this might be normal if you connect for the first time using 3G, since it needs to initialise. But now comes the interesting part. If you repeat this call several times it returns the following:
1.47 seconds
2.33 seconds
1.1 seconds
I have tested this using two different iPhones and two different providers:T-Mobile and KPN. I also tried this using the async version of NSURLConnection, which I normally use, but this also returns the same results.
(Other things I also did: checked Apple's Reachabilty.h, removed the DNS look-up by replacing the server url by the ip-number, used an other server and used https://www.google.nl/search?q=%i, arc4random(), also tried [NSString alloc]initWithContentOfURL]. All returned a similar result, except when using the iPhone browser: Safari, which responded immediately.)
I have also tested something similar using an Android phone, but then I get a fast response 500ms (using the same providers).
Did someone encountered this before? If so, how did you solve this issue and what causes this problem with the connection?
I have a similar issue in that naturally over a 3g connection the post request would be slightly slower depending on the amount of data sent. However if I send over a synchronous request its quicker for me than the async method. What I have noticed is that over a 3g connection using async the OS has to close the connections and you may notice in the log "purgeIdleCellConnections: found one to purge conn" seems to add some time to method execution.

NSInputStream example?

I'm trying to create a simple iPhone app that can communicate with a server (which is running on my computer at the moment and works fine). I've been trying to use the NSStream class but have had a lot of issues. I really just want to mimic a telnet-type of connection using the streams. I've managed to send data to my server with an NSOutputStream, but I can't figure out how to use the NSInputStream to read the reply sent from the server. Here is the method I have so far:
-(void)sendName:(NSString *)name{
NSData*nameData = [name dataUsingEncoding:NSUTF8StringEncoding];
[outputStream write:(uint8_t *)[nameData bytes] maxLength:[nameData length]];
//The server sends a reply here.
[inputStream read:? maxLength:?]; // I don't know what do to here.
[inputStream close]; //Created and opened elsewhere.
[outputStream close]; //Created and opened elsewhere.
}
I can't figure out how to get the inputStream to read what the server sends. I've tried passing an NSData object in as the buffer but it always crashes. So how do I create the buffer? Also, is it bad to make the length huge to make sure the buffer doesn't fill up (though maybe waste space)? Some example code would be splendid! Thanks in advance!
The thing you need to understand about NSStreams, is "don't call us, we'll call you." When the stream has data available, it will notify its delegate, and then you read whatever data is available and tell it to go get some more.
Read the Streams Programming Guide

sending information from my iphone app to my computer

So I have a pretty simple problem, which I have no idea how to go about (kinda of new for everything here). I am developing an iPhone app that I intend to use only myself - so think small for now :)Let's say all my app is doing is tracking my location every hour. All I want to do, is to be able to read this information not on the iphone, say on a file on my computer. How can I send this information from my app to a personal computer? I am guessing that I will need to set up some server / database or something on my personal machine?
Can someone please help with a quick step by step on how to go about that? I literally have no clue where to start...
Thanks!
You just need a http server and then you cam create HTTP GET/POST requests to url's set up on your machine. You can use the responses to send data back to the device.
You'll need to have a listener somewhere to send your data to. For instance, you could set up a communication class in your project which would be responsible for serving as the medium between your applications. You would then set up a listener on a server, or your machine that would listen for requests.
iPhone > Communication Class > Web service
(.NET in this case)
You can use the NSURLConnection object to serve this purpose. E.g.
- (void) sendSomethingToServer:(NSString*)myData{
NSString*url = [[NSString alloc]initWithFormat: #"http://example.com/service.asmx/RecordData?myData='%#'", myData];
[self createRequest:url];
[url release];
}
http://example.com/service.asmx/RecordData being the location and method on your web service.
Here's a generic request method I created which sets the headers as a JSON packet.
- (void) createRequest: (NSString*)urlFormatted {
NSLog(#"Request Sent");
NSURL *url = [NSURL URLWithString: urlFormatted];
NSMutableURLRequest *request =[NSMutableURLRequest requestWithURL: url];
[request setHTTPMethod:#"GET"];
[request setValue:#"application/json; charset=UTF-8" forHTTPHeaderField:#"Content-Type"];
}
And on the back-end, on your web server, you would have a method that recieves the data. Obviously you could use any technology you wanted on the server. In this example, I'm using .NET on Mono e.g.
[WebMethod(Description = "Generic Client Data)]
[ScriptMethod(UseHttpGet = true, ResponseFormat = ResponseFormat.Json)]
public string RecordData(string myData)
{
// Do something with data
}
Set up a Ruby on Rails server on your Mac. It's free and quite easy.
Use ASIHTTPRequest to send data to the Ruby server.
http://allseeing-i.com/ASIHTTPRequest/
If you just need to get the data back and forth, I believe you could use file sharing. Here's a tutorial on how to set that up:
http://www.raywenderlich.com/1948/how-integrate-itunes-file-sharing-with-your-ios-app
It would allow you to view the files in itunes and copy them back and forth when the iPhone is connected via USB. If all you need to do is to get a raw data file onto your computer, that would likely be a lot less overhead than having to build/run a full server just to transfer the file over.
Apple's can you help get started. Search for "networking" in the docs and develop a client on both sides which uses your own protocol.

Is it possible to read the contents of a web page into a string so i can parse out the data?

I'd like to be able to get my iphone to load a URL( or really the file that the url points to) into a string. The reason I want to be able to do this is so that I can then parse the string looking for tags and extract some values from it.
The files are mostly webpages so html or .asp etc.
Anybody able to give me some hints on what I need to do to achieve this kinda of thing?
Many Thanks,
-Code
First get the URL
NSURL *anUrl = [NSURL URLWithString:#"http://google.com"];
Then turn it into a string
NSError *error;
NSString *htmlString = [NSString stringWithContentsOfURL:anUrl encoding:NSUTF8Encoding error:&error];
UPDATE:
There is documentation on getting the contents of an URL by using NSURLConnection from the ADC site
From there you can get the string representation of the downloaded data using
NSString *htmlString = [[NSString alloc] initWithData:urlData encoding:NSUTF8Encoding];
I appreciate that this has been asked and answered, but I would strongly suggest that you consider not using NSString's stringWithContentsOfURL:encoding:error: method for this. If there's one message Apple has tried to send to iOS developers over the past year it is this: Do not make synchronous network calls on the main thread.
If that request takes more than twenty seconds to respond, which is not at all unlikely with a 3G or EDGE connection, and certainly possible on a WiFi connection, iOS will kill your app. More importantly, if it takes more than about half a second to return you're going to anger your users as they fiddle with their unresponsive phones.
NSURLConnection is not terribly difficult to use, and will allow your device to continue responding to events while it's downloading content.

iPhone upload image speed advice

I have an app that allows you to take a picture, adjust the jpeg quality size (10-100%) and then send it to a server using ASIFormDataRequest (part of the ASIHTTPRequest implementation). This works fine over a network connection, but over the celluar network it appears to sit there for 5-10 minutes attempting to transmit the image post data, before failing (even with the quality at 10%).
On comparing this to the image uploads that the Twitter and Facebook apps provide (which take ~30 seconds to a minute) this isn't exactly ideal. I wondered if anyone could give me any advice about either how to speed up my data transfer, or monitor it so I can see exactly where the problem lies.
Once I get back to my mac laptop tonight I'll post a code snippet of exactly what it is I'm doing, in case that helps.
EDIT: Heres the code snippet:
NSURL *url = [NSURL URLWithString:#"...upload.php"];
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
NSTimeInterval time = [[NSDate date] timeIntervalSince1970];
NSString *fileName = [NSString stringWithFormat:#"%d", time];
...
float compressionRate = [userAccountView getCompressionRate];
NSLog(#"Compression rate: %.1f", compressionRate);
NSData *imageData = UIImageJPEGRepresentation(imageForView, compressionRate);
[request setData:imageData withFileName:fileName andContentType:#"image/jpeg" forKey:#"userfile"];
[request setDelegate:self];
[request startAsynchronous];
The .. code comment is where I just stick an 'uploading' image over the view. I suppose I could make the call synchronous as opposed to asynchronous, do you think that may improve performance? I have left it that way in case at a later stage I wanted to allow the user to do other bits while it is uploading.
Any advice would be great :)
Thanks,
Dan
EDIT:
Jesse, thanks for the comment - I added in [request setUploadProcessDelegate:self] and put in the required method to monitor the data that was being sent, and it all seemed to be sending okay.
JosephH - I have added in "[ASIHTTPRequest setShouldThrottleBandwidthForWWAN:YES]" as suggested, and have also added "set_time_limit(0);" into the PHP upload script (in case of timeouts) and now the data does seem to be sending and being retrieved over the cellular network, so horray! Am playing around now with file compressions etc. to find the best one for the best quality. ATM it seems like 0.3 is pretty good quality, and transfers in roughly 30 seconds or so, which is what I was looking for!
I was also incorrectly setting the compression rate, as I was using 10-100 as opposed to 0.0-1.0, so I have also corrected that.
Thanks for your quick help guys in solving my issue!!
I think the first thing to do is to check what size the data you're sending is:
NSLog(#"imageData size = %d", [imageData length]);
Does your NSLog correctly show the compressionRate is set to 0.1 for 10%?
ASIHTTPRequest also has a lot of debug logging you can enable - see ASIHTTPRequestConfig.h; just change everything from 0 to 1. It may not reveal anything of interest, but it is certainly worth looking at.
Are you calling [ASIHTTPRequest setShouldThrottleBandwidthForWWAN:YES] ?
When it fails, how does it fail, what is the error, what does any logging on the server show?
(If you find out anything extra, please do edit it into the question and post a comment and I'll take another look)