How to reduce audio file size in IOS - ios

I am doing an application which get songs from mediapicker and saving it to my application.i want to reduce the size of file,but i got a sample named "AACConverter",i test the application but it is not reducing the file size.could any one help me in solving this problem.
- (IBAction)convert:(id)sender {
if ( ![TPAACAudioConverter AACConverterAvailable] ) {
[[[[UIAlertView alloc] initWithTitle:NSLocalizedString(#"Converting audio", #"")
message:NSLocalizedString(#"Couldn't convert audio: Not supported on this device", #"")
delegate:nil
cancelButtonTitle:nil
otherButtonTitles:NSLocalizedString(#"OK", #""), nil] autorelease] show];
return;
}
// Initialise audio session, and register an interruption listener, important for AAC conversion
if ( !checkResult(AudioSessionInitialize(NULL, NULL, interruptionListener, self), "initialise audio session") ) {
[[[[UIAlertView alloc] initWithTitle:NSLocalizedString(#"Converting audio", #"")
message:NSLocalizedString(#"Couldn't initialise audio session!", #"")
delegate:nil
cancelButtonTitle:nil
otherButtonTitles:NSLocalizedString(#"OK", #""), nil] autorelease] show];
return;
}
// Set up an audio session compatible with AAC conversion. Note that AAC conversion is incompatible with any session that provides mixing with other device audio.
UInt32 audioCategory = kAudioSessionCategory_MediaPlayback;
if ( !checkResult(AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(audioCategory), &audioCategory), "setup session category") ) {
[[[[UIAlertView alloc] initWithTitle:NSLocalizedString(#"Converting audio", #"")
message:NSLocalizedString(#"Couldn't setup audio category!", #"")
delegate:nil
cancelButtonTitle:nil
otherButtonTitles:NSLocalizedString(#"OK", #""), nil] autorelease] show];
return;
}
NSArray *documentsFolders = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
audioConverter = [[[TPAACAudioConverter alloc] initWithDelegate:self
source:[[NSBundle mainBundle] pathForResource:#"audio" ofType:#"mp3"]
destination:[[documentsFolders objectAtIndex:0] stringByAppendingPathComponent:#"audio.m4a"]] autorelease];
NSLog(#"destinatiion path is %#",[[documentsFolders objectAtIndex:0]stringByAppendingFormat:#"audio.m4a"]);
((UIButton*)sender).enabled = NO;
[self.spinner startAnimating];
self.progressView.progress = 0.0;
self.progressView.hidden = NO;
[audioConverter start];
}
- (IBAction)playConverted:(id)sender {
if ( audioPlayer ) {
[audioPlayer stop];
[audioPlayer release];
audioPlayer = nil;
[(UIButton*)sender setTitle:#"Play converted" forState:UIControlStateNormal];
} else {
NSArray *documentsFolders = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *path = [[documentsFolders objectAtIndex:0] stringByAppendingPathComponent:#"audio.m4a"];
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
[audioPlayer play];
[(UIButton*)sender setTitle:#"Stop" forState:UIControlStateNormal];
}
}
- (IBAction)emailConverted:(id)sender {
NSArray *documentsFolders = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *path = [[documentsFolders objectAtIndex:0] stringByAppendingPathComponent:#"audio.m4a"];
MFMailComposeViewController *mailController = [[MFMailComposeViewController alloc] init];
mailController.mailComposeDelegate = self;
[mailController setSubject:NSLocalizedString(#"Recording", #"")];
[mailController addAttachmentData:[NSData dataWithContentsOfMappedFile:path]
mimeType:#"audio/mp4a-latm"
fileName:[path lastPathComponent]];
[self presentModalViewController:mailController animated:YES];
}
#pragma mark - Audio converter delegate
-(void)AACAudioConverter:(TPAACAudioConverter *)converter didMakeProgress:(CGFloat)progress {
self.progressView.progress = progress;
}
-(void)AACAudioConverterDidFinishConversion:(TPAACAudioConverter *)converter {
self.progressView.hidden = YES;
[self.spinner stopAnimating];
self.convertButton.enabled = YES;
self.playConvertedButton.enabled = YES;
self.emailConvertedButton.enabled = YES;
audioConverter = nil;
}
-(void)AACAudioConverter:(TPAACAudioConverter *)converter didFailWithError:(NSError *)error {
[[[[UIAlertView alloc] initWithTitle:NSLocalizedString(#"Converting audio", #"")
message:[NSString stringWithFormat:NSLocalizedString(#"Couldn't convert audio: %#", #""), [error localizedDescription]]
delegate:nil
cancelButtonTitle:nil
otherButtonTitles:NSLocalizedString(#"OK", #""), nil] autorelease] show];
self.convertButton.enabled = YES;
audioConverter = nil;
}

There are various ways in which you can solve this problem.
In case you want the audio to play in background, you can use
[[SimpleAudioEngine sharedEngine] playBackgroundMusic:#"BGM.mp3" loop:YES];
By using this, you can use a small audio clip which will be small in size, and play it in a loop. Same thing can be applied to Effect Audio as well.
Apart from that, decreasing the Bitrate of audio clip also helps in decreasing the size of file.
For all these editing operations, which includes editing/clipping/trimming sound clip, decreasing bitrate, saving in different formats, I'd suggest you use
Audacity (Open-source, free)

If you care about the size over the quality, maybe you want to conver the song to amr format.

Related

When i post image to instagram from my app it directly opens to filter section of Instagram but i want it to open cropping section of Instagram?

- (IBAction)postToInstagram:(id)sender {
NSURL *instagramURL = [NSURL URLWithString:#"instagram://app"];
if ([[UIApplication sharedApplication] canOpenURL:instagramURL])
{
CGRect rect = CGRectMake(0,0,0,0);
NSString *jpgPath=[NSHomeDirectory() stringByAppendingPathComponent:#"Documents/Home_1_instgram.igo"];
UIImage *imageN = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:#"%#", jpgPath]];
// [UIImagePNGRepresentation(_imageDetail.image) writeToFile:jpgPath atomically:YES];
NSURL *igImageHookFile = [[NSURL alloc] initWithString:[[NSString alloc] initWithFormat:#"file://%#",jpgPath]];
self.documentController.UTI = #"com.instagram.exclusivegram";
self.documentController = [self setupControllerWithURL:igImageHookFile usingDelegate:self];
NSString *caption = self.catalogueImage.caption; //settext as Default Caption
//Removing pre-filled captions from mobile sharing
//http://developers.instagram.com/post/125972775561/removing-pre-filled-captions-from-mobile-sharing
self.documentController.annotation = [NSDictionary dictionaryWithObject:#"Here Give what you want to share" forKey:#"InstagramCaption"];
NSLog(#"caption: %#",caption);
[self.documentController presentOpenInMenuFromRect: rect inView: self.view animated: YES ];
}
else
{
UIAlertView *alert=[[UIAlertView alloc] initWithTitle:#"INSTAGRAM NOT FOUND" message:#"Please install instagram to post to instagram." delegate:nil cancelButtonTitle:nil otherButtonTitles:#"ok", nil];
[alert show];
}
}
I found the solution to it. In iOS Instagram directly sends user to the filter section whereas in android the user is directed to the crop section. It was mentioned in Instagram iPhone Hook.
Thank You
i have changed something in your code :
you should use com.instagram.photo
- (IBAction)postToInstagram:(id)sender {
if ([self schemeAvailable:#"instagram://app"])
{
CGRect rect = CGRectMake(0,0,0,0);
NSString *jpgPath=[NSHomeDirectory() stringByAppendingPathComponent:#"Documents/Home_1_instgram.igo"];
UIImage *imageN = [UIImage imageNamed:#"IMG_1304.PNG"];
[UIImagePNGRepresentation(imageN) writeToFile:jpgPath atomically:YES];
NSURL *igImageHookFile = [[NSURL alloc] initWithString:[[NSString alloc] initWithFormat:#"file://%#",jpgPath]];
self.documentController.UTI = #"com.instagram.photo";
self.documentController = [UIDocumentInteractionController interactionControllerWithURL:igImageHookFile];
NSString *caption = #"YourCaption"; //settext as Default Caption
//Removing pre-filled captions from mobile sharing
//http://developers.instagram.com/post/125972775561/removing-pre-filled-captions-from-mobile-sharing
self.documentController.annotation = [NSDictionary dictionaryWithObject:#"Here Give what you want to share" forKey:#"InstagramCaption"];
NSLog(#"caption: %#",caption);
[self.documentController presentOpenInMenuFromRect: rect inView: self.view animated: YES ];
}
else
{
UIAlertView *alert=[[UIAlertView alloc] initWithTitle:#"INSTAGRAM NOT FOUND" message:#"Please install instagram to post to instagram." delegate:nil cancelButtonTitle:nil otherButtonTitles:#"ok", nil];
[alert show];
}
}

Issue with AVAudioPlayer gives error when click at Play button

I am programing an audio player using "AVFoundation.h". I've issues with Updating Progress bar, Hence when I click at play button my app gives error. I am attaching both code samples & error report. can anyone sort this out?
-(void)updateProgress {
NSInteger durationMinutes = [self.audioPlayer duration] / 60;
NSInteger durationSeconds = [self.audioPlayer duration] - durationMinutes * 60;
NSInteger currentTimeMinutes = [self.audioPlayer currentTime] / 60;
NSInteger currentTimeSeconds = [self.audioPlayer currentTime] - currentTimeMinutes * 60;
NSString *progressString = [NSString stringWithFormat:#"%d:%02d / %d:%02d", currentTimeMinutes, currentTimeSeconds, durationMinutes, durationSeconds];
self.timeLabel.text = progressString;
self.progressBar.progress = [self.audioPlayer currentTime] / [self.audioPlayer duration];
NSNumber *numCurrentTimeSeconds = [NSNumber numberWithInt:currentTimeSeconds];
NSNumber *numDurationSeconds = [NSNumber numberWithInt:durationSeconds];
NSString *songTitle = [self.selectedFilePath lastPathComponent];
NSString *artistName = #"MyPlayer";
MPMediaItemArtwork *albumArt = [[MPMediaItemArtwork alloc] initWithImage:[UIImage imageNamed:#"placeholder"]];
MPNowPlayingInfoCenter *infoCenter = [MPNowPlayingInfoCenter defaultCenter];
NSDictionary *infoDict = [NSDictionary dictionaryWithObjects:#[songTitle, artistName, albumArt, numDurationSeconds, numCurrentTimeSeconds] forKeys:#[MPMediaItemPropertyTitle, MPMediaItemPropertyAlbumArtist, MPMediaItemPropertyArtwork, MPMediaItemPropertyPlaybackDuration, MPNowPlayingInfoPropertyElapsedPlaybackTime]];
[infoCenter setNowPlayingInfo:infoDict]; }
When pressed Build & Run app goes successfully started in simulator, I've taken 2 images of active Console
1. before clicking at play button.
After clicking play button. when app goes crash.
enter image description here
now please suggest me what I should do at this point? so that my app start working smoothly...
Thanks
Faiz.
After following instructions by Losiowaty answer last day. those yellow issues are removed but still my programing gives same error when I click at play button.
enter image description here
This time I am uploading complete code and highlighting few things due to which I think error is occurring.
Please take a look at my mainwviewcontroller.m class code.
#interface MainViewController ()
#end
#implementation MainViewController
#synthesize audioPlayer;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib
NSError *error = nil;
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&error];
if (error == nil) {
NSLog(#"audio session initialized successfully");
} else {
NSLog(#"error initializing audio session: %#", [error description]);
}
[audioPlayer setDelegate:self];
MPVolumeView *volumeView = [ [MPVolumeView alloc] init] ;
[volumeView setFrame:self.airPlayView.bounds];
[self.airPlayView addSubview:volumeView];
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[self becomeFirstResponder];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(caughtInterruption:) name:AVAudioSessionInterruptionNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(routeChanged:) name:AVAudioSessionRouteChangeNotification object:nil];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(BOOL)canBecomeFirstResponder
{
return YES;
}
-(void)dealloc
{
[self resignFirstResponder];
[[NSNotificationCenter defaultCenter] removeObserver:self name:AVAudioSessionInterruptionNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:AVAudioSessionRouteChangeNotification object:nil];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"showFilePicker"]) {
UINavigationController *navigationController = (UINavigationController *)segue.destinationViewController;
FileViewController *fileViewController = (FileViewController *)navigationController.topViewController;
fileViewController.delegate = self;
}
}
#pragma mark - file picker delegate methods
-(void)cancel
{
[self dismissViewControllerAnimated:YES completion:nil];
}
-(void)didFinishWithFile:(NSString *)filePath
{
NSError *error = nil;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
self.selectedFilePath = filePath;
NSString *relativeFilePath = [documentsDirectory stringByAppendingPathComponent:filePath];
NSURL *fileURL = [NSURL fileURLWithPath:relativeFilePath];
self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error:&error];
self.audioPlayer.delegate = self;
if (error == nil) {
NSLog(#"audio player initialized successfully");
self.titleLabel.text = self.selectedFilePath;
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:#selector(updateProgress) userInfo:nil repeats:YES];
NSString *songTitle = [filePath lastPathComponent];
NSString *artistName = #"MyPlayer";
MPMediaItemArtwork *albumArt = [[MPMediaItemArtwork alloc] initWithImage:[UIImage imageNamed:#"placeholder"]];
MPNowPlayingInfoCenter *infoCenter = [MPNowPlayingInfoCenter defaultCenter];
NSDictionary *infoDict = [NSDictionary dictionaryWithObjects:#[songTitle, artistName, albumArt] forKeys:#[MPMediaItemPropertyTitle, MPMediaItemPropertyAlbumArtist, MPMediaItemPropertyArtwork]];
[infoCenter setNowPlayingInfo:infoDict];
[self play:nil];
} else {
NSLog(#"error initializing audio player: %#", [error description]);
}
//dismiss the file picker
[self dismissViewControllerAnimated:YES completion:nil];
}
-(IBAction)play:(id)sender
{
if ([self.audioPlayer isPlaying]) {
[self.audioPlayer pause];
[self.playButton setImage:[UIImage imageNamed:#"play"] forState:UIControlStateNormal];
[self.timer invalidate];
[animation stopAnimating];
} else {
[self.audioPlayer play];
[self.playButton setImage:[UIImage imageNamed:#"pause"] forState:UIControlStateNormal];
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:#selector(updateProgress) userInfo:nil repeats:YES];
animation.animationImages = [NSArray arrayWithObjects:
[UIImage imageNamed:#"animation1.png"],
[UIImage imageNamed:#"animation2.png"],
[UIImage imageNamed:#"animation3.png"],nil];
[animation setAnimationRepeatCount:2000];
animation.animationDuration = 0.5;
[animation startAnimating];
}
self.playbackInterrupted = NO;
}
-(IBAction)skipForward:(id)sender
{
if ([self.audioPlayer isPlaying]) {
NSTimeInterval desiredTime = self.audioPlayer.currentTime + 15.0f;
if (desiredTime < self.audioPlayer.duration) {
self.audioPlayer.currentTime = desiredTime;
}
}
}
-(IBAction)skipBackward:(id)sender
{
if ([self.audioPlayer isPlaying]) {
NSTimeInterval desiredTime = self.audioPlayer.currentTime - 15.0f;
if (desiredTime < 0) {
self.audioPlayer.currentTime = 0.0f;
} else {
self.audioPlayer.currentTime = desiredTime;
}
}
}
#pragma mark - Timer delegate
-(void)updateProgress
{
NSInteger durationMinutes = [self.audioPlayer duration] / 60;
NSInteger durationSeconds = [self.audioPlayer duration] - durationMinutes * 60;
NSInteger currentTimeMinutes = [self.audioPlayer currentTime] / 60;
NSInteger currentTimeSeconds = [self.audioPlayer currentTime] - currentTimeMinutes * 60;
NSString *progressString = [NSString stringWithFormat:#"%ld:%02ld / %ld:%02ld", currentTimeMinutes,currentTimeSeconds, durationMinutes, durationSeconds];
self.timeLabel.text = progressString;
self.progressBar.progress = [self.audioPlayer currentTime] / [self.audioPlayer duration];
NSNumber *numCurrentTimeSeconds = [NSNumber numberWithInteger:currentTimeSeconds];
NSNumber *numDurationSeconds = [NSNumber numberWithInteger:durationSeconds];
NSString *songTitle = [self.selectedFilePath lastPathComponent];
NSString *artistName = #"MyPlayer";
MPMediaItemArtwork *albumArt = [[MPMediaItemArtwork alloc] initWithImage:[UIImage imageNamed:#"placeholder"]];
MPNowPlayingInfoCenter *infoCenter = [MPNowPlayingInfoCenter defaultCenter];
NSDictionary *infoDict = [NSDictionary dictionaryWithObjects:#[songTitle, artistName, albumArt, numDurationSeconds, numCurrentTimeSeconds] forKeys:#[MPMediaItemPropertyTitle, MPMediaItemPropertyAlbumArtist, MPMediaItemPropertyArtwork, MPMediaItemPropertyPlaybackDuration, MPNowPlayingInfoPropertyElapsedPlaybackTime]];
[infoCenter setNowPlayingInfo:infoDict];
}
#pragma mark - AVAudioPlayer delegate methods
-(void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{
if (flag) {
[self.playButton setImage:[UIImage imageNamed:#"play"] forState:UIControlStateNormal];
[self.timer invalidate];
[animation stopAnimating];
}
}
#pragma mark - Remote control
-(void)remoteControlReceivedWithEvent:(UIEvent *)event
{
switch (event.subtype) {
case UIEventSubtypeRemoteControlPlay:
case UIEventSubtypeRemoteControlPause:
case UIEventSubtypeRemoteControlTogglePlayPause:
[self play:nil];
break;
case UIEventSubtypeRemoteControlNextTrack:
[self skipForward:nil];
break;
case UIEventSubtypeRemoteControlPreviousTrack:
[self skipBackward:nil];
break;
default:
break;
}
}
#pragma mark - audio interruption
-(void)caughtInterruption:(NSNotification *)notification
{
NSDictionary *userInfo = notification.userInfo;
NSNumber *type =[userInfo objectForKey:AVAudioSessionInterruptionTypeKey];
if ([type integerValue] == AVAudioSessionInterruptionTypeBegan) {
if (self.audioPlayer.playing) {
[self.audioPlayer pause];
[animation stopAnimating];
self.playbackInterrupted = YES;
}
} else {
if (self.audioPlayer.playing == NO && self.playbackInterrupted == YES) {
[self.audioPlayer play];
[animation startAnimating];
self.playbackInterrupted = NO;
}
}
}
#pragma mark - route changed
-(void)routeChanged:(NSNotification *)notification
{
NSDictionary *userInfo = notification.userInfo;
NSNumber *reason =[userInfo objectForKey:AVAudioSessionRouteChangeReasonKey];
switch ([reason integerValue]) {
case AVAudioSessionRouteChangeReasonNoSuitableRouteForCategory:
[self.audioPlayer stop];
[animation stopAnimating];
break;
case AVAudioSessionRouteChangeReasonNewDeviceAvailable:
case AVAudioSessionRouteChangeReasonOldDeviceUnavailable:
case AVAudioSessionRouteChangeReasonWakeFromSleep:
[self.audioPlayer pause];
[animation stopAnimating];
break;
default:
break;
}
}
#end
above code is error free & pretty clean, everything is clearly mentioned, I am using 4 buttons,
for Play & Pause
for seeking forward
for seeking backward
for entering into document directory for audio file picking
when I am pressing this fourth button it prepares for entering into another view for picking audio file.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"showFilePicker"]) {
UINavigationController *navigationController = (UINavigationController *)segue.destinationViewController;
FileViewController *fileViewController = (FileViewController *)navigationController.topViewController;
fileViewController.delegate = self;
}
}
I needs two things to accomplish
the first things which I needs to accomplish is that,
I don't wants to enter into next view, because I am testing my app into simulator where there is no physical audio file I can place or locate in simulator, hence I needs to avoid this thing just for my owns testing purpose.
Hence I am willing to add an audio mp3 file into NSBundle and wants to play this file when I press play button file starts playing & then Pause when pressing again. code for paying & pause is pretty clean working well. but for initializing file path is I think I've to initialize file path in viewDidload method by replacing above view did load by following code.
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSString *audioFilePath = [[NSBundle mainBundle] pathForResource:#"Nameofflie" ofType:#"mp3"];
NSURL *pathAsURL = [[NSURL alloc] initFileURLWithPath:audioFilePath];
NSError *error = nil;
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:pathAsURL error:&error];
if (error == nil) {
NSLog(#"audio session initialized successfully");
} else {
NSLog(#"error initializing audio session: %#", [error description]);
}
[audioPlayer setDelegate:self];
MPVolumeView *volumeView = [ [MPVolumeView alloc] init] ;
[volumeView setFrame:self.airPlayView.bounds];
[self.airPlayView addSubview:volumeView];
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[self becomeFirstResponder];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(caughtInterruption:) name:AVAudioSessionInterruptionNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(routeChanged:) name:AVAudioSessionRouteChangeNotification object:nil];
}
this code also Runs & compiles pretty well but when pressing play button same error occurring. so please suggest me where to place following lines to play MP3 Music file placed from NSBudle .
NSString *audioFilePath = [[NSBundle mainBundle] pathForResource:#"rabne" ofType:#"mp3"];
NSURL *pathAsURL = [[NSURL alloc] initFileURLWithPath:audioFilePath];
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:pathAsURL error:&error];
this point is totally different from just above point number 1 which I am willing to accomplish. when after testing successfully, playing that NSBundle audio MP3 file.
I wants to work with my earlier code again, as the end user is not using my simulator, hence for end users I wants to have same option which already I accomplished in above Mainviewcontroller.m class,i.e. user have to press 4th number button for accessing their device's document directory file path. that works pretty well in my code. but the thing here I wants to point to or needs to sort out is that, if someone directly pressing very 1st play button without pressing 4th button for going & selecting an audio file, an alert view should appear with a message that first select a file by pressing fourth button and then click play button. That's it I am willing to have in my code.
Based on the exception in screenshot #2, it looks that you are trying to insert a nil object into an array. The only place where you insert some objects into array is this line :
NSDictionary *infoDict = [NSDictionary dictionaryWithObjects:#[songTitle, artistName, albumArt, numDurationSeconds, numCurrentTimeSeconds] forKeys:#[MPMediaItemPropertyTitle, MPMediaItemPropertyAlbumArtist, MPMediaItemPropertyArtwork, MPMediaItemPropertyPlaybackDuration, MPNowPlayingInfoPropertyElapsedPlaybackTime]];
The second array, the one with the keys, looks ok, as it consisits of only system provided consts. The first one on the other hand has two objects than could be nil : songTitle and albumArt.
The reasons for these to be nil are :
songTitle may be nil if self.selectedFilePath is nil
albumArt - I'm not entirely sure, but it could end up being nil if your image was not found.
Please make sure that these two are not nil and everything should be working fine.
As to your warnings, these two :
NSNumber *numCurrentTimeSeconds = [NSNumber numberWithInt:currentTimeSeconds];
NSNumber *numDurationSeconds = [NSNumber numberWithInt:durationSeconds];
can be fixed by changing to [NSNumber numberWithInteger:] and are caused by the fact that NSInteger is a typedef for long and not int.
The warning on
NSString *progressString = [NSString stringWithFormat:#"%d:%02d / %d:%02d", currentTimeMinutes, currentTimeSeconds, durationMinutes, durationSeconds];
is caused by virtually the same thing. %d expects an int, and NSInteger is a long. Changing %d to %ld will fix it.
It is still my firm belief that these didn't cause the crash, especially based on the thrown exception which is pretty straightforward in stating what has happend.
The provided code confirms my assumptions - the crash happens because self.selectedFilePath is nil in updateProgress method resulting in songTitle also being nil. Why this happens? The only place in provided code where you set self.selectedFilePath is in didFinishWithFile: method, which I assume is a delegate method of FileViewController. If you don't present it and selected something there, that method is not called.
Now, if you want to setup this for testing, the easiest way would be to add this in your viewDidLoad :
NSError *error;
NSString *audioFilePath = [[NSBundle mainBundle] pathForResource:#"rabne" ofType:#"mp3"];
NSURL *pathAsURL = [[NSURL alloc] initFileURLWithPath:audioFilePath];
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:pathAsURL error:&error];
if (error == nil) {
self.selectedFilePath = #"test file"; // <<-- IMPORTANT
self.titleLabel.text = self.selectedFilePath;
} else {
NSLog(#"error initializing audio player: %#", [error description]);
}
just above [audioPlayer setDelegate:self];. This should get everything going.
On a side note : I'd also remove this line self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:#selector(updateProgress) userInfo:nil repeats:YES]; from didFinishWithFile: method - you also setup a timer in play: method, and it seems safer to do it once.
As to point #2 - I can give you a hint, that you know if a file is selected when self.selectedFilePath != nil and to take a look at UIAlertViewController class. The rest of work is left for you, as it was not a part of the original problem and has nothing to do with solving the crash. Also, you wouldn't learn anything that way :)

ZBar SDK slowing down in IOS7

I am trying to implement some qr code reader using ZBar.
After a while I did manage to do reading, but after several readings the app tends to get slower and slower (until practically unresponsive).
This SDK is compatible with iOS7 ?
Frameworks : libiconv.dylib,libinfo.dylib, QuartzCore, CoreVideo,CoreMedia,AVFoundation,CoreGraphics,UIKit,XCTest
- (IBAction)scan:(id)sender {
//initialize the reader and provide some config instructions
ZBarReaderViewController *reader = [ZBarReaderViewController new];
reader.readerDelegate = self;
[reader.scanner setSymbology: ZBAR_I25
config: ZBAR_CFG_ENABLE
to: 1];
reader.cameraFlashMode=UIImagePickerControllerCameraFlashModeOff;
reader.readerView.zoom = 1.0; // define camera zoom property
//show the scanning/camera mode
[self presentModalViewController:reader animated:YES];
// Do any additional setup after loading the view from its nib.
}
- (void) imagePickerController: (UIImagePickerController*) reader
didFinishPickingMediaWithInfo: (NSDictionary*) info {
//this contains your result from the scan
id results = [info objectForKey: ZBarReaderControllerResults];
//create a symbol object to attach the response data to
ZBarSymbol *symbol = nil;
//add the symbol properties from the result
//so you can access it
for(symbol in results){
//symbol.data holds the value
NSString *upcString = symbol.data;
//print to the console
NSLog(#"the value of the scanned UPC is: %#",upcString);
NSMutableString *message = [[NSMutableString alloc]
initWithString: #"Scanned Barcode: "];
[message appendString:[NSString stringWithFormat:#"%# ",
upcString]];
//Create UIAlertView alert
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:#"Product Barcode" message: message delegate:self
cancelButtonTitle:#"Cancel" otherButtonTitles: nil];
self.viewResult.text = upcString;
[alert show];
//After some time
[alert dismissWithClickedButtonIndex:0 animated:TRUE];
//make the reader view go away
[reader dismissModalViewControllerAnimated: YES];
}
}
EDIT : After 4 or 5 readings, this is the memory and CPU consumption -> http://diogomend.me/images/capt.png. Christ :D
Well, after checking this issue Memory related issue of ZBarReaderViewController in iOS 7, I did manage to solve the problem.
The lines I've added are the following:
(in my viewcontroller.h)
#property (strong,nonatomic) ZBarReaderViewController *reader;
(in my viewcontroller.m)
if(self.reader)
{
[self.reader.readerView stop];
for(UIView *subViews in self.reader.view.subviews)
[subViews removeFromSuperview];
[self.reader.view removeFromSuperview];
self.reader.view = nil;
}
_reader = [ZBarReaderViewController new];

Playing youtube video using HCYoutubeParser

I am using HCYoutubeParser(https://github.com/hellozimi/HCYoutubeParser) to play some videos in my ios app. When I am trying to play some video, it doesn't seem to play it.
The code looks like this:
- (void)playVideo:(id)sender
{
if (_urlToLoad)
{
MPMoviePlayerViewController *player = [[MPMoviePlayerViewController alloc]initWithContentURL:_urlToLoad];
_mp = player;
[self presentViewController:_mp animated:YES completion:nil];
}
}
- (void)submitYouTubeURL:(id)sender {
[playButton setImage:nil forState:UIControlStateNormal];
NSURL *url = [NSURL URLWithString:_urlOfYoutube];
activityIndicator.hidden = NO;
[HCYoutubeParser thumbnailForYoutubeURL:url thumbnailSize:YouTubeThumbnailDefaultHighQuality completeBlock:^(UIImage *image, NSError *error) {
if (!error) {
[playButton setBackgroundImage:image forState:UIControlStateNormal];
playButton.hidden = NO;
NSDictionary *qualities = [HCYoutubeParser h264videosWithYoutubeURL:url];
_urlToLoad = nil;
_urlToLoad = [NSURL URLWithString:[qualities objectForKey:#"medium"]];
NSLog(#"%#",[NSURL URLWithString:[qualities objectForKey:#"medium"]]);
activityIndicator.hidden = YES;
[playButton setImage:[UIImage imageNamed:#"play_button"] forState:UIControlStateNormal];
}
else {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:[error localizedDescription] delegate:nil cancelButtonTitle:#"Dismiss" otherButtonTitles:nil];
[alert show];
}
}];
}
The line that gives the problem is _urlToLoad = [NSURL URLWithString:[qualities objectForKey:#"medium"]];
[NSURL URLWithString:[qualities objectForKey:#"medium"]] returns null..
How do I solve this?
In my case , I was getting 0 key value pair for
NSDictionary *qualities = [HCYoutubeParser h264videosWithYoutubeURL:url];
Ie , I was getting qualities having 0 key value pair.
I found that code in HCYoutubeParser.m , in method + (NSDictionary *)h264videosWithYoutubeID:(NSString *)youtubeID a variable signature variable was not getting initialized , so I replaced NSString *signature = nil; with NSString *signature = #"";

Unable to send email using MFMailComposeViewController in simulator

I am new to ios app development, Below is the code I used to send an email.
MFMailComposeViewController* controller = [[MFMailComposeViewController alloc] init];
controller.mailComposeDelegate = self;
[controller setSubject:#"My Subject"];
[controller setMessageBody:#"Hello there." isHTML:NO];
[self presentModalViewController:controller animated:YES];
[controller release];
- (void)mailComposeController:(MFMailComposeViewController*)controller
didFinishWithResult:(MFMailComposeResult)result
error:(NSError*)error {
if (result == MFMailComposeResultSent) {
NSLog(#"It's away!");
}
[self dismissModalViewControllerAnimated:YES];
}
Unfortunately delegate methods are never triggered , Can any one please suggest how can i check my email via simulator?
You CANNOT send mails through Simulator.
Instead you can install the application in device and try from there.
Simulator just displays the composer but wont allow you to send mails. Sent Successfully is just the acknowledgment that your code is fine and there is no issue that terminates it while sending.
As far as i know, you cannot send mail from Simulator.. The MFMailComposeViewController uses the mailbox configured in iPhone's Mail app to send the mail. The simulator does not have the Mail app.
You can able to send mail using the Gmail connectivity you can send mail to user for that you need to insert the some amount of code and setting in your code following code which use for sending a mail.
- (IBAction)sendMessageInBack:(id)anObject{
NSLog(#"Start Sending");
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:#"sample.pdf"];
NSData *dataObj = [NSData dataWithContentsOfFile:writableDBPath];
SKPSMTPMessage *testMsg = [[SKPSMTPMessage alloc] init];
testMsg.fromEmail = #"Your mail id";
testMsg.toEmail = #"sender mail ids";
testMsg.relayHost = #"smtp.gmail.com";
testMsg.requiresAuth = YES;
testMsg.login = #"Uour mail id";
testMsg.pass = #"your pass";
testMsg.subject = #"Test application ";
testMsg.wantsSecure = YES; // smtp.gmail.com doesn't work without TLS!
// Only do this for self-signed certs!
// testMsg.validateSSLChain = NO;
testMsg.delegate = self;
NSDictionary *plainPart = [NSDictionary dictionaryWithObjectsAndKeys:#"text/plain",kSKPSMTPPartContentTypeKey,
#"Some text to include in body",kSKPSMTPPartMessageKey,#"8bit",kSKPSMTPPartContentTransferEncodingKey,nil];
testMsg.parts = [NSArray arrayWithObjects:plainPart,nil];
[testMsg send];
}
-(void)messageSent:(SKPSMTPMessage *)message{
[message release];
NSLog(#"delegate - message sent");
}
-(void)messageFailed:(SKPSMTPMessage *)message error:(NSError *)error{
[message release];
// open an alert with just an OK button
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:#"Unable to send email" delegate:self cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alert show];
[alert release];
NSLog(#"delegate - error(%d): %#", [error code], [error localizedDescription]);
}
And following files copy into your project.
For downloading a sample code here.

Resources