I have this code to get the audio inside my project and supposed to play audio:
#import "ViewController.h"
#import <AudioToolbox/AudioServices.h>
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self playAudio];
}
- (void)playAudio {
[self playSound:#"Splash" :#"wav"];
}
- (void)playSound :(NSString *)fName :(NSString *) ext{
SystemSoundID audioEffect;
NSString *path = [[NSBundle mainBundle] pathForResource : fName ofType :ext];
if ([[NSFileManager defaultManager] fileExistsAtPath : path]) {
NSURL *pathURL = [NSURL fileURLWithPath: path];
AudioServicesCreateSystemSoundID((__bridge CFURLRef) pathURL, &audioEffect);
AudioServicesPlaySystemSound(audioEffect);
}
else {
NSLog(#"error, file not found: %#", path);
}
}
#end
I'm using iOS 8 with iPhone 4s simulator, and this code doesn't work and I not hear the audio, why?
Related
I want to know whether my users are downloading my application for the first time or upgrading the old version.
How can I get that information when application is launched?
Option 1.
Save the bundle version somewhere and check if it differs from
[[NSBundle mainBundle] objectForInfoDictionaryKey:#"CFBundleVersion"]]
on each app startup.
Option 2.
Use a category on UIApplication that let's you see if the app was updated.
UIApplication+Versioning.h
#protocol UIApplicationDelegate<UIApplicationDelegate>
#optional
- (void)application:(UIApplication *)application
willUpdateToVersion: (NSString*) newVersion
fromVersion: (NSString*) previousVersion;
- (void)application:(UIApplication *)application
didUpdateToVersion: (NSString*) newVersion
fromVersion: (NSString*) previousVersion;
#end
#interface UIApplication (Versioning)
#end
UIApplication+Versioning.m
#import "UIApplication+Versioning.h"
#import <objc/message.h>
#import <objc/runtime.h>
static NSString* UIApplicationVersionFileName = #"app.version";
#implementation UIApplication (Versioning)
+ (void)load
{
original = class_getInstanceMethod(self, #selector(setDelegate:));
swizzled = class_getInstanceMethod(self, #selector(swizzled_setDelegate:));
method_exchangeImplementations(original, swizzled);
}
- (void)swizzled_setDelegate:(id<UIApplicationDelegate>)delegate
{
IMP implementation = class_getMethodImplementation([self class], #selector(swizzled_application:didFinishLaunchingWithOptions:));
class_addMethod([delegate class], #selector(swizzled_application:didFinishLaunchingWithOptions:), implementation, "B#:##");
original = class_getInstanceMethod([delegate class], #selector(application:didFinishLaunchingWithOptions:));
swizzled = class_getInstanceMethod([delegate class], #selector(swizzled_application:didFinishLaunchingWithOptions:));
method_exchangeImplementations(original, swizzled);
[self swizzled_setDelegate: delegate];
}
- (BOOL)swizzled_application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Check for a version change
NSError* error;
NSArray* directories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString* versionFilePath = [[directories objectAtIndex: 0] stringByAppendingPathComponent:UIApplicationVersionFileName];
NSString* oldVersion = [NSString stringWithContentsOfFile:versionFilePath
encoding:NSUTF8StringEncoding
error:&error];
NSString* currentVersion = [[[NSBundle mainBundle] infoDictionary] objectForKey: #"CFBundleVersion"];
switch (error.code)
{
case NSFileReadNoSuchFileError:
{
// Delegate methods will not be called first time
oldVersion = [currentVersion copy];
[currentVersion writeToFile: versionFilePath
atomically: YES
encoding: NSUTF8StringEncoding
error: &error];
break;
}
default:
{
NSLog(#"Warning: An error occured will loading the application version file -> Recreating file");
[[NSFileManager defaultManager] removeItemAtPath: versionFilePath
error: nil];
oldVersion = [currentVersion copy];
[currentVersion writeToFile: versionFilePath
atomically: YES
encoding: NSUTF8StringEncoding
error: &error];
break;
}
}
if( ![oldVersion isEqualToString: currentVersion] )
{
if ([[application delegate] respondsToSelector: #selector(application:willUpdateToVersion:fromVersion:)])
{
objc_msgSend([application delegate], #selector(application:willUpdateToVersion:fromVersion:), currentVersion, oldVersion);
}
[currentVersion writeToFile:versionFilePath
atomically:YES
encoding:NSUTF8StringEncoding
error:&error];
if ([[application delegate] respondsToSelector: #selector(application:didUpdateToVersion:fromVersion:)])
{
objc_msgSend([application delegate], #selector(application:willUpdateToVersion:fromVersion:), currentVersion, oldVersion);
}
}
SEL realSelector = #selector(swizzled_application:didFinishLaunchingWithOptions:);
return (BOOL) objc_msgSend([application delegate], realSelector, application, launchOptions);
}
#end
I was trying to play a song in iOS, but it gives me an error message.
HEADER FILE .h
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
#interface PRPViewController : UIViewController{
AVAudioPlayer *audioPlayer;
IBOutlet UIButton *start;
}
-(IBAction)play;
#end
IMPLEMENTATION FILE .m
NSURL *url = [NSURL fileURLWithPath:
[NSString stringWithFormat:#"%#/bobmarley.mp3",
[[NSBundle mainBundle] resourcePath]]];
NSError *error;
audioPlayer = [[AVAudioPlayer alloc] initWithContentsofURL:url error:&error];
audioPlayer.numberOfLoops = 0;
[audioPlayer play];
but it says
No visible #interface for AVAudioPlayer declares the selector 'initWithContentsofUrl:error:'
What should I do?
You should capitalize the "O" in Of. In Objective-C, spelling counts, including capitalization. initWithContentsofURL and initWithContentsOfURL are two different things.
(By the way, this is a very good reason for using autocompletion as much as possible. The autocompletion mechanism knows much better than you do how to spell the names of the declared methods!)
You should check if the file is available on your system with the method initWithContentsOfURL, yours is written wrong. Otherwise the app can crash. I created a class which handles everything for me:
#implementation AudioPlayer{
AVAudioPlayer *_sound;
NSURL *_soundURL;
NSString *_receivedValue;
float _volumeSpecific;
}
- (id)initWithAudioFile:(NSString *)fileName andExtension:(NSString *)extension{
self = [super init];
if( self ){
_receivedValue = fileName;
_soundURL = [NSURL fileURLWithPath:
[[NSBundle mainBundle] pathForResource:fileName
ofType:extension]];
if([[NSFileManager defaultManager] fileExistsAtPath:[_soundURL path]]){
_sound = [[AVAudioPlayer alloc] initWithContentsOfURL:_soundURL
error:nil];
}
}
return self;
}
- (void)playEndless{
if( [[NSUserDefaults standardUserDefaults] boolForKey:kSound] ){
_sound.numberOfLoops = -1;
[_sound play];
}
}
- (void)setVolume:(float)myVolume{
_volumeSpecific = myVolume;
[_sound setVolume:myVolume];
}
- (void)play{
if( _sound == nil ){
NSLog(#"No AudioPlayer available %#", self);
}
if( [[NSUserDefaults standardUserDefaults] boolForKey:kSound] ){
if( _volumeSpecific ){
[_sound setVolume:_volumeSpecific];
}
[_sound play];
}
}
- (NSString *)description{
return [NSString stringWithFormat:#"Received: %#, Player: %#, URL: %#",
_receivedValue, _sound, _soundURL];
}
I can get both iPhone and iPad to load the same HTML file, however I would like to load a more optimized page based on which device the program is loading on.
ViewController.h:
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#property (strong, nonatomic) IBOutlet UIWebView *webView;
#end
ViewController.m:
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
NSURL *url = [[NSBundle mainBundle] URLForResource:#"index" withExtension:#"html"];
NSString *html = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];
NSString *path = [[NSBundle mainBundle] bundlePath];
NSURL *baseURL = [NSURL fileURLWithPath:path];
[_webView loadHTMLString:html baseURL:baseURL];
// disable scrolling
_webView.scrollView.scrollEnabled = NO;
_webView.scrollView.bounces = NO;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
I have tried to create a new outlet, but I seem to be running into overlapping code.
How can I load different HTML files for iPad and iPhone with a universal build?
Just use one web view. All you need is two different HTML files.
Then you code can be something like:
NSURL *url;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
url = [[NSBundle mainBundle] URLForResource:#"index-iphone" withExtension:#"html"];
} else {
url = [[NSBundle mainBundle] URLForResource:#"index-ipad" withExtension:#"html"];
}
This assumes you have both an index-iphone.html and a index-ipad.html file in your app bundle.
Here is my MainViewController.m
#import "MainViewController.h"
#interface MainViewController ()
#end
#implementation MainViewController
#synthesize audioPlayer;
#synthesize soundsArray;
-(void)prepareSounds
{
NSString *filepath= [[NSBundle mainBundle] pathForResource:#"Sounds" ofType:#"plist"];
self.soundsArray = [[NSArray alloc] initWithContentsOfFile:filepath];
}
- (IBAction)playSound:(id)sender {
UIButton *buttonPressed = (UIButton *)sender;
NSString *soundName = [soundsArray objectAtIndex:(buttonPressed.tag -1)];
NSString *path = [[NSBundle mainBundle] pathForResource:soundName ofType:#"mp3"];
NSURL *file = [[NSURL alloc] initFileURLWithPath:path];
AVAudioPlayer *p = [[AVAudioPlayer alloc]
initWithContentsOfURL:file error:nil];
self.audioPlayer = p;
[self.audioPlayer play];
}
- (IBAction)playSound2:(id)sender {
UIButton *buttonPressed = (UIButton *)sender;
NSString *soundName = [soundsArray objectAtIndex:(buttonPressed.tag -2)];
NSString *path = [[NSBundle mainBundle] pathForResource:soundName ofType:#"mp3"];
NSURL *file = [[NSURL alloc] initFileURLWithPath:path];
AVAudioPlayer *p = [[AVAudioPlayer alloc]
initWithContentsOfURL:file error:nil];
self.audioPlayer = p;
[self.audioPlayer play];
}
- (IBAction)playSound3:(id)sender {
UIButton *buttonPressed = (UIButton *)sender;
NSString *soundName = [soundsArray objectAtIndex:(buttonPressed.tag -3)];
NSString *path = [[NSBundle mainBundle] pathForResource:soundName ofType:#"mp3"];
NSURL *file = [[NSURL alloc] initFileURLWithPath:path];
AVAudioPlayer *p = [[AVAudioPlayer alloc]
initWithContentsOfURL:file error:nil];
self.audioPlayer = p;
[self.audioPlayer play];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Flipside View
- (void)flipsideViewControllerDidFinish:(FlipsideViewController *)controller
{
[self dismissViewControllerAnimated:YES completion:nil];
}
- (IBAction)showInfo:(id)sender
{
FlipsideViewController *controller = [[FlipsideViewController alloc] initWithNibName:#"FlipsideViewController" bundle:nil];
controller.delegate = self;
controller.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:controller animated:YES completion:nil];
}
#end
My MainViewController.h
#import <UIKit/UIKit.h>
#import "FlipsideViewController.h"
#import <AudioToolbox/AudioToolbox.h>
#import <AVFoundation/AVFoundation.h>
#interface MainViewController : UIViewController <FlipsideViewControllerDelegate> {
AVAudioPlayer *audioPlayer;
NSArray *soundsArray;
}
#property(nonatomic, retain) AVAudioPlayer *audioPlayer;
#property(nonatomic, retain) NSArray *soundsArray;
-(void)prepareSounds;
- (IBAction)playSound:(id)sender;
- (IBAction)playSound2:(id)sender;
- (IBAction)playSound3:(id)sender;
#end
In the 'Supporting Files' folder I have an array of strings with the name of the sound files I want to play, and in the 'Supporting Files' folder I have a folder named 'Sounds', which contains the sound files.
All of my buttons play the same sound. Can someone please provide some insight. Thanks!
I think the problem may be in this line playSound:
NSString *soundName = [soundsArray objectAtIndex:(buttonPressed.tag -1)]
which is repeated in playSound2 and playSound3 with "buttonPressed.tag -2" and "buttonPressed.tag -3".
If your buttonPressed.tags are set to 1, 2, and 3, then each time "buttonPressed.tag -X" is likely evaluating to 0, and playing the sound of the first file in the array.
You are repeating the code to do the same task.
Add all your buttons IBAction to a single method (say it as playSound)
Implement the method like:
- (IBAction)playSound:(UIButton *)sender
{
NSString *soundName = [soundsArray objectAtIndex:(sender.tag -1)];
NSString *path = [[NSBundle mainBundle] pathForResource:soundName ofType:#"mp3"];
NSURL *file = [[NSURL alloc] initFileURLWithPath:path];
AVAudioPlayer *p = [[AVAudioPlayer alloc] initWithContentsOfURL:file error:nil];
self.audioPlayer = p;
[self.audioPlayer play];
}
There is no need of writing same code for each individual button.
SOLVED: prepareSounds() was never called. Here is the working code:
#import "MainViewController.h"
#interface MainViewController ()
#end
#implementation MainViewController
#synthesize audioPlayer;
#synthesize soundsArray;
-(void)prepareSounds
{
NSString *filepath= [[NSBundle mainBundle] pathForResource:#"Sound" ofType:#"plist"];
self.soundsArray = [[NSArray alloc] initWithContentsOfFile:filepath];
}
- (void)stopAudio
{
if (audioPlayer!= nil) {
[audioPlayer stop];
//do some task for changing the Image i.e setting the default image
}
}
- (IBAction)playSound:(UIButton *)sender
{
UIButton *btn = (UIButton*)sender;
NSString *soundName = [soundsArray objectAtIndex:(btn.tag - 1)];
NSString *path = [[NSBundle mainBundle] pathForResource:soundName ofType:#"mp3"];
NSURL *file = [[NSURL alloc] initFileURLWithPath:path];
AVAudioPlayer *p = [[AVAudioPlayer alloc] initWithContentsOfURL:file error:nil];
self.audioPlayer = p;
if([audioPlayer isPlaying])
{
[self stopAudio];
}
[self.audioPlayer play];
}
- (void)viewDidLoad
{
[self prepareSounds];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Flipside View
- (void)flipsideViewControllerDidFinish:(FlipsideViewController *)controller
{
[self dismissViewControllerAnimated:YES completion:nil];
}
- (IBAction)showInfo:(id)sender
{
FlipsideViewController *controller = [[FlipsideViewController alloc] initWithNibName:#"FlipsideViewController" bundle:nil];
controller.delegate = self;
controller.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:controller animated:YES completion:nil];
}
#end
- (void)viewDidLoad {
SystemSoundID ReelStopSound;
NSString *soundPath = [[NSBundle mainBundle] pathForResource:#"spin" ofType:#"mp3" ];
CFURLRef soundURL = (CFURLRef)[NSURL fileURLWithPath:soundPath];
AudioServicesCreateSystemSoundID(soundURL, &ReelStopSound);
AudioServicesPlaySystemSound(ReelStopSound);
[super viewDidLoad];
}
when i run this app in simulator it plays the spin.mp3 but in the my iPad its not!!