MPNowPlayingInfoCenter defaultCenter will not update or retrieve information - iphone

I'm working to update the MPNowPlayingInfoCenter and having a bit of trouble. I've tried quite a bit to the point where I'm at a loss. The following is my code:
self.audioPlayer.allowsAirPlay = NO;
Class playingInfoCenter = NSClassFromString(#"MPNowPlayingInfoCenter");
if (playingInfoCenter) {
NSMutableDictionary *songInfo = [[NSMutableDictionary alloc] init];
MPMediaItemArtwork *albumArt = [[MPMediaItemArtwork alloc] initWithImage:[UIImage imageNamed:#"series_placeholder"]];
[songInfo setObject:thePodcast.title forKey:MPMediaItemPropertyTitle];
[songInfo setObject:thePodcast.author forKey:MPMediaItemPropertyArtist];
[songInfo setObject:#"NCC" forKey:MPMediaItemPropertyAlbumTitle];
[songInfo setObject:albumArt forKey:MPMediaItemPropertyArtwork];
[[MPNowPlayingInfoCenter defaultCenter] setNowPlayingInfo:songInfo];
}
This isn't working, I've also tried:
[[MPNowPlayingInfoCenter defaultCenter] setNowPlayingInfo:nil];
In an attempt to get it to remove the existing information from the iPod app (or whatever may have info there). In addition, just to see if I could find out the problem, I've tried retrieving the current information on app launch:
NSDictionary *info = [[MPNowPlayingInfoCenter defaultCenter] nowPlayingInfo];
NSString *title = [info valueForKey:MPMediaItemPropertyTitle];
NSString *author = [info valueForKey:MPMediaItemPropertyArtist];
NSLog(#"Currently playing: %# // %#", title, author);
and I get Currently playing: (null) // (null)
I've researched this quite a bit and the following articles explain it pretty thoroughly, however, I am still unable to get this working properly. Am I missing something? Would there be anything interfering with this? Is this a service something my app needs to register to access (didn't see this in any docs)?
Apple's Docs
Change lock screen background audio controls
Now playing info ignored

I finally figured out the problem, I was not prompting my app to receive remote control events, simply adding this line fixed the problem:
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];

I use the code below and it always works. I'm also using MPMoviePlayer like you. Have you checked whether NSClassFromString(#"MPNowPlayingInfoCenter") ever actually returns YES? Have you set you app play audio in background key in your plist?
- (void) loadMPInformation
{
NSDictionary *mpInfo;
if([savedTrack.belongingAlbum.hasAlbumArt boolValue] == NO){
mpInfo = [NSDictionary dictionaryWithObjectsAndKeys:savedTrack.belongingAlbum.album, MPMediaItemPropertyAlbumTitle,
savedTrack.belongingArtist.artist, MPMediaItemPropertyArtist, savedTrack.name, MPMediaItemPropertyTitle, nil];
} else {
UIImage *artImage = [UIImage imageWithData:savedTrack.belongingAlbum.art];
MPMediaItemArtwork *artwork = [[MPMediaItemArtwork alloc] initWithImage:artImage];
mpInfo = [NSDictionary dictionaryWithObjectsAndKeys:savedTrack.belongingAlbum.album, MPMediaItemPropertyAlbumTitle,
savedTrack.belongingArtist.artist, MPMediaItemPropertyArtist, savedTrack.name, MPMediaItemPropertyTitle, artwork, MPMediaItemPropertyArtwork, nil];
}
[MPNowPlayingInfoCenter defaultCenter].nowPlayingInfo = mpInfo;
}

Related

MFMessageComposeViewController shows blank white screen in iOS7

there's a problem when I try to send a large recipients list (e.g more than 40) using MFMessageComposeViewController. In iOS7, it will show a blank white screen for 20s or more before displaying the SMS compose view. This does not occur for iOS5 and iOS6.
Below is the existing code that I'm using,
NSArray * recipients;
for (NSIndexPath * index in selectedRows)
{
NSDictionary *dictionary = [data objectAtIndex:index.row];
NSString *phoneNum = [dictionary objectForKey:#"contactNum"];
recipients = [NSArray arrayWithObjects:phoneNum, nil]];
}
MFMessageComposeViewController *controller = [[MFMessageComposeViewController alloc] init];
if([MFMessageComposeViewController canSendText])
{
controller.body = bodyOfMessage;
controller.recipients = recipients;
controller.messageComposeDelegate = self ;
controller.wantsFullScreenLayout = NO;
[(id)_delegate presentModalViewController:controller animated:YES];
[[UIApplication sharedApplication] setStatusBarHidden:YES];
}
Below are the output message that I received when I try to send to many.
timed out waiting for fence barrier from com.apple.mobilesms.compose
Received memory warning.
Received memory warning.
Received memory warning.
Received memory warning.
Received memory warning.
Received memory warning.
Received memory warning.
Received memory warning.
Received memory warning.
I had a similar problem where I got the message in the console "
timed out waiting for fence barrier from com.apple.mobilesms.compose
The problem was that I tried in my app to add the number as a string, but because of the localization request, I have put it in a form:NSArray *recipents = #[NSLocalizedString(#"numberForRegistrationViaSms", #"")];
and
[messageController setRecipients:#[recipents]];
That didn't work for some reason but, when I put just simply, [messageController setRecipients:#[#"123456789"]];, the SMS composer appears without any problem.
I to had the same problem then figured
controller.recipients = // should always be an array of strings.
Make sure the phone numbers you send to controller.recipients are NSString.
I think I maybe resolve this:
//must initiate new NSString object
NSString *phoneStr = [NSString stringWithFormat:#"%#",... ];
MFMessageComposeViewController *aCtrl = [[MFMessageComposeViewController alloc] init];
aCtrl.recipients = #[phoneStr];
...
Then OK.
I had same problem.
timed out waiting for fence barrier from com.apple.mobilesms.compose
Message Cancelled
Instead of this:
NSString *phoneNumber = #"888888888";
[picker setRecipients:#[phoneNumber]];
Try this:
NSString *phoneNumber = person.phoneNumber;
[picker setRecipients:#[[NSString stringWithFormat:#"%#", phoneNumber]]];
This worked for me.
The problem has been resolved in iOS 7.0.3.

Objective-C Tested app on iPhone, updated data, data doesnt change

I just built my first app and now I started testing it on my phone. It looks great when I first launch the app after building it, the launch images appears and then my json data is loaded via NSURL and displays properly on the app. But when I close down the app, update the data via php and mysql and re open it the launch image does not appear and my app is not updated. Is it possible to have the app launch like it did when I first launched it, always have launch image and also get the new data?
Here is my code if it helps.
- (void)viewDidLoad
{
[super viewDidLoad];
[self loadJSON];
}
- (void)loadJSON
{
Reachability *networkReachability = [Reachability reachabilityForInternetConnection];
NetworkStatus networkStatus = [networkReachability currentReachabilityStatus];
if (networkStatus == NotReachable) {
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle: #"Error" message: #"Connection Failed" delegate: self cancelButtonTitle:#"Refresh" otherButtonTitles:nil]; [alert show]; [alert release];
});
} else {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSURL *url = [NSURL URLWithString:#"http://url.com/GetData.php"];
NSData *data = [NSData dataWithContentsOfURL:url options:0 error:nil];
NSArray *array = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSArray *firstItemArray = array[0];
NSString *yesNoString = firstItemArray[0];
NSString *dateString = firstItemArray[1];
NSString *timeString = firstItemArray[2];
NSString *homeString = firstItemArray[3];
NSString *awayString = firstItemArray[4];
NSString *lastUpdatedString = firstItemArray[5];
dispatch_async(dispatch_get_main_queue(), ^{
self.YesOrNo.text = yesNoString;
self.date.text = [#"For " stringByAppendingString:dateString];
self.time.text = timeString;
self.home.text = homeString;
self.away.text = awayString;
self.lastUpdated.text = lastUpdatedString;
self.lastUpdatedText.text = #"Last Updated";
self.vs.text = #"vs";
});
});
}
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
[self loadJSON];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)dealloc {
[_YesOrNo release];
[_date release];
[_time release];
[_vs release];
[_home release];
[_away release];
[_lastUpdatedText release];
[_lastUpdated release];
[super dealloc];
}
#end
If someone can point me in the right direction, that would be great and appreciated, thanks.
When you hit the round home button when running an app, it just puts it into the background, where it continues to run in a type of catatonic state. When you tap its icon again, it just wakes up, and doesn't re-launch. If you'd like to have your app completely quit when the user hits the home button, use the info.plist option "UIApplicationExitsOnSuspend" also known as "Application does not run in background." Set this to YES in your info.plist, and you'll get a fresh start every time. You can access this by clicking on your project in Xcode in the Project Navigator mode, and select the "info" tab at the top middle.
As it is your first app, you should try reading about the various devices and os versions.
Read about various application states, also the methods that are present in the AppDelegateClass, that get called when the app enters into various states,try reading about them.
So what has happened in your case is the device that you are using is Multitasking one. So when you press the home button or the sleep button the game goes to background, and is not killed. So next time when you tap on the application icon on your device, it brings it back to the foreground and does not relaunch it hence your Viewdidload method won't be called and your changes won't get reflected.
So, now to terminate your app, you can go through this link
http://www.gottabemobile.com/2013/02/10/how-to-close-apps-on-iphone/
Hope this helps.

Programmatically tap on HTML href in order to update app

I'm planning updates for an enterprise app with ad-hoc distribution.
For updates, Apple recommends having the user visit an HTML page and tap on a link:
href="itms-services://?action=download-manifest&url=http://example.com/
manifest.plist"
See http://help.apple.com/iosdeployment-apps/#app43ad871e
I don't want to do this. I want the app to programmatically check for updates on launch and alert the user with a UIAlertView that an update is available.
Here's what I have so far in application didFinishLaunching. The complicated plist parsing comes from the structure of an example plist found here: http://help.apple.com/iosdeployment-apps/#app43ad78b3
NSLog(#"checking for update");
NSData *plistData = [NSData dataWithContentsOfURL:[NSURL URLWithString:#"http://example.com/MyApp.plist"]];
if (plistData) {
NSLog(#"finished checking for update");
NSError *error;
NSPropertyListFormat format;
NSDictionary *plist = [NSPropertyListSerialization propertyListWithData:plistData options:NSPropertyListImmutable format:&format error:&error];
if (plist) {
NSArray *items = [plist valueForKey:#"items"];
NSDictionary *dictionary;
if ([items count] > 0) {
dictionary = [items objectAtIndex:0];
}
NSDictionary *metaData = [dictionary objectForKey:#"metadata"];
float currentVersion = [[[[NSBundle mainBundle] infoDictionary] objectForKey:#"CFBundleVersion"] floatValue];
float newVersion = [[metaData objectForKey:#"bundle-version"] floatValue];
NSLog(#"newVersion: %f, currentVersion: %f", newVersion, currentVersion);
if (newVersion > currentVersion) {
NSLog(#"A new update is available");
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Update available" message:#"A new update is available." delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"UPDATE", nil];
[alert show];
}
}
}
Then I have my UIAlertView delegate method:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 1) {
NSLog(#"downloading full update");
UIWebView *webView = [[UIWebView alloc] init];
[webView loadRequest:[[NSURLRequest alloc] initWithURL:[NSURL URLWithString:#"itms-services://?action=download-manifest&url=http://example.com/MyApp.plist"] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10.0]];
}
}
A few things:
I know [alert show] shouldn't be called in application didFinish, but I'll change it later.
I don't know how quickly plistData will be downloaded and how this download affects the app.
More importantly, my alert view delegate method doesn't work, and the update doesn't download. Even when I introduce webView with #property (nonatomic, strong) UIWebView *webView, the method doesn't do anything.
I think Dropbox has the MIME configured properly because I can download the .ipa through google Chrome.
So what I really need is a way using NSURLConnection (NSURLRequest etc.) to replicate the act of a user tapping on an HTML href. After that I think the full update will occur.
You can open a URL automatically using
[[UIApplication sharedApplication] openURL:...];
I don't know if it works for itms-services: urls, but it works for other bespoke URL schemes like tel:, fb: etc. so it should do unless Apple have specifically blocked it.

UIImagePicker crashing after selection

I'm using ELCImagePickerController so I can select multiple photos and import them. It works fine when I select a few photos, but if I select over around 25, I get a crash. Here's the code that runs after I hit done selecting photos:
-(void)selectedAssets:(NSArray*)_assets {
NSMutableArray *returnArray = [[NSMutableArray alloc] init];
int count=0;
for(ALAsset *asset in _assets) {
NSMutableDictionary *workingDictionary = [[NSMutableDictionary alloc] init];
[workingDictionary setObject:[asset valueForProperty:ALAssetPropertyType] forKey:#"UIImagePickerControllerMediaType"];
UIImage *image=[UIImage imageWithCGImage:[[asset defaultRepresentation] fullScreenImage]];
[workingDictionary setObject:image forKey:#"UIImagePickerControllerOriginalImage"];
[workingDictionary setObject:[[asset valueForProperty:ALAssetPropertyURLs] valueForKey:[[[asset valueForProperty:ALAssetPropertyURLs] allKeys] objectAtIndex:0]] forKey:#"UIImagePickerControllerReferenceURL"];
NSLog(#"%i", count);
count++;
[returnArray addObject:workingDictionary];
}
[self popToRootViewControllerAnimated:NO];
[[self parentViewController] dismissModalViewControllerAnimated:YES];
if([delegate respondsToSelector:#selector(elcImagePickerController:didFinishPickingMediaWithInfo:)]) {
[delegate performSelector:#selector(elcImagePickerController:didFinishPickingMediaWithInfo:) withObject:self withObject:[NSArray arrayWithArray:returnArray]];
}
}
I selected 80 photos, and the NSLog statement displays up to 45, but then it just crashes with no message, just (gdb).
The images I'm selecting are iPhone 4 images captured with the rear camera. I've tried resizing the images too upon importing, but even then the app still crashes. Any ideas of what could be the problem?
I'm going to put that as an answer if you don't mind.
There are few solutions to this problem. First you might want to restrict user from selecting more than something like 5 photos. Second you might want to resize your images and make them really small before putting them into an array or something. Or if you need them all in the original size, you can copy them upon selection to your ~/tmp directory and instead store the links to them in your NSArray, so that you could load them dynamically from disk instead of keeping them all in memory.
Sorry if it doesn't helps since I don't really know your ultimate goal in using such amount of images at the same time.

Publish to Facebook wall from iPhone application

No Matter what i do, i cannot get a post published to an application page wall (the app being logged into) via an iPhone application. I'm able to log in using FBLoginDialog and then retrieve data to populate a tableview, however when i click a button to publish some test content it doesn't work. Here is the button action:
- (void)compose:(id)sender;
{
NSString *tid=#"115372005166292";
NSString *body = #"My Test";
NSArray *obj = [NSArray arrayWithObjects:body,[NSString stringWithFormat:#"%#", tid],nil];
NSArray *keys = [NSArray arrayWithObjects:#"message",#"target_id",nil];
NSDictionary *params = [NSDictionary dictionaryWithObjects:obj forKeys:keys];
[[FBRequest requestWithDelegate:self] call:#"facebook.stream.publish" params:params];
}
I have also used the FBStreamDialog which works, however i'm faced with two issues there. The dialog lacks customization and i'm unable to handle the callback when the item is posted (e.g. reload the tableview)
I've been searching the internet and all of the examples are similar to the code above, so i'm not sure what i could be missing.
Thanks
You need to ask for extended permissions. After login show this:
FBPermissionDialog* dialog = [[[FBPermissionDialog alloc] init] autorelease];
dialog.delegate = self;
dialog.permission = #"status_update";
[dialog show];
Doc: http://github.com/facebook/facebook-iphone-sdk/#readme