iPhone: programmatically check if vibration is enabled - iphone

Is it possible to programmatically check if the system option of iPhone
Settings -> Sounds -> Vibrate on Ring
is enabled?
In my app, I would like to display an alert to the user if that option is disabled.

You cannot. Because apple is not providing the API to access the iPhone settings app.

may be you could give it a try and make sure you're running the app in iDevice because simulator don't have silent or ring mode :)
New Edits
-(BOOL)silenced
{
#if TARGET_IPHONE_SIMULATOR
// return NO in simulator. Code causes crashes for some reason.
return NO;
#endif
CFStringRef state;
UInt32 propertySize = sizeof(CFStringRef);
AudioSessionInitialize(NULL, NULL, NULL, NULL);
AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &propertySize, &state);
if(CFStringGetLength(state) > 0)
return NO;
else
return YES;
}
and you can call this method like this way
if ([self silenced])
{
NSLog(#"silenced");
} else {
NSLog(#"not silenced");
}
hope it will help you!

Related

How to check if sound off on iphone [duplicate]

I am developing an application. In that i want to detect through coding that "is iPhone on silent mode or not?". I am developing it by using cocoa with Objective-C.
If anyone knows it kindly reply.
The reason Pirripli's code does not work is that the simulator does not support the test and the code does not check for errors. Corrected code would look like:
CFStringRef state = nil;
UInt32 propertySize = sizeof(CFStringRef);
AudioSessionInitialize(NULL, NULL, NULL, NULL);
OSStatus status = AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &propertySize, &state);
if (status == kAudioSessionNoError)
{
return (CFStringGetLength(state) == 0); // YES = silent
}
return NO;
It's possible by testing for a NULL audio route using AudioToolBox:
UInt32 routeSize = sizeof (CFStringRef);
CFStringRef route;
AudioSessionGetProperty (
kAudioSessionProperty_AudioRoute,
&routeSize,
&route
);
if (route == NULL) {
NSLog(#"Silent switch is on");
}
If route is NULL then there's no available audio outputs. If it's "Headset" or "Headphones" then the silent ringer switch could still be on. However, it will never be on when it's set to "Speaker".
You're probably best testing for this in your audio route change property listener, which is set below:
AudioSessionAddPropertyListener (
kAudioSessionProperty_AudioRouteChange,
audioRouteChangeListenerCallback,
self
);
Note: If you're doing anything funky like overriding audio routes, then this answer may not apply.
Setting up and tearing down an audio session in its entirety is probably beyond the scope of this answer.
For completeness, building off this link from Dan Bon, I implement the following method to solve this problem in my apps. One thing to note is that the code checks for the iPhone simulator first - executing the below code will crash the simulator. Anyone know why?
-(BOOL)silenced {
#if TARGET_IPHONE_SIMULATOR
// return NO in simulator. Code causes crashes for some reason.
return NO;
#endif
CFStringRef state;
UInt32 propertySize = sizeof(CFStringRef);
AudioSessionInitialize(NULL, NULL, NULL, NULL);
AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &propertySize, &state);
if(CFStringGetLength(state) > 0)
return NO;
else
return YES;
}
Declaring this right in the view controller, you'd simply check
if ([self silenced]) {
NSLog(#"silenced");
else {
NSLog(#"not silenced");
}
Or, obviously, you could declare it in some kind of helper class. A more elegant solution might be a category addition on UIApplication or some such other class...
You can use Audio Route property as suggested by the previous answers, but keep in mind that:
- It works only if the Audio Category is AmbientSound
- You should not initialize Audio Session more than once in your app (see Audio Session Programming Guide)
- You should release those CFStringRef to avoid mem leaks
In case the current audio category is not AmbientSound though, you can think of changing it temporarily, perform the check on Audio Route property, and then restoring the original Audio Category.
Note that changing Audio Category will restore the default Audio Route for that category, given the current hardware configuration (i.e. whether there are headphones plugged in or not, etc).

How can I mute incoming iPhone text messages programmatically?

I'm currently trying to use the AVSystemController private framework to mute system noises based on the user's selection. I'm currently muting phone calls by calling: [(AVSystemController object) setVolumeTo:0.0 forCategory:#"Ringtone"];
Is there a command to do that for incoming text messages? I imagine it would be based on a change in the category identified in that call. However, I can't find a list of categories to reference. Of the 10 I've been able to find (Alert, Audio/Video, Ringtone, Voicemail, VoicemailGreeting, PhoneCall, TTYCall, RingtonePreview, Alarm, Record), none of them govern text message sounds. Is there a category to do this? If not, is there any other way to mute the sound from incoming texts?
I realize this goes against Apple's no-private-frameworks policy, but this app won't go up on the app store so that's no problem. I'm developing it using the latest version of Xcode for the latest version of IOS, so any method to accomplish this would be doable.
#Jessica, You can't do that, bcos it's restricted. if you want to try it in your application, then your app might be Rejected in App store.
So, Using public APIs, it is not possible.
The link you found is using private APIs, which aren't documented or guaranteed to work the way you'd expect. If you tried to release an App Store app that called a private API, it would be automatically rejected.
if you want to Check , whether is silent or not, then use below code,
-(BOOL)silenced {
#if TARGET_IPHONE_SIMULATOR
// return NO in simulator. Code causes crashes for some reason.
return NO;
#endif
CFStringRef state;
UInt32 propertySize = sizeof(CFStringRef);
AudioSessionInitialize(NULL, NULL, NULL, NULL);
AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &propertySize, &state);
if(CFStringGetLength(state) > 0)
return NO;
else
return YES;
}
For completeness, building off this link from Dan Bon, I implement the following method to solve this problem in my apps. One thing to note is that the code checks for the iPhone simulator first - executing the below code will crash the simulator. Anyone know why?
-(BOOL)silenced {
#if TARGET_IPHONE_SIMULATOR
// return NO in simulator. Code causes crashes for some reason.
return NO;
#endif
CFStringRef state;
UInt32 propertySize = sizeof(CFStringRef);
AudioSessionInitialize(NULL, NULL, NULL, NULL);
AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &propertySize, &state);
if(CFStringGetLength(state) > 0)
return NO;
else
return YES;
}
Declaring this right in the view controller, you'd simply check
if ([self silenced]) {
NSLog(#"silenced");
else {
NSLog(#"not silenced");
}

Can I determine / how, if a device has vibration or not?

I have some settings that enable/disable vibration for certain actions, but I find it pointless to display them if the device doesn't have the ability to vibrate. Is there a way to check if the person is using an iPod touch and if it has vibration?
I'm not sure there is a way to do this other than doing model checks which is probably not a great approach. I do know that apple provides:
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
If the device can vibrate, it will. On devices without vibration, it will do nothing. There is another call:
AudioServicesPlayAlertSound(kSystemSoundID_Vibrate);
This one will vibrate the device if it hash the capability or the device will beep.
It might be better to just have the settings and have some explanation around the setting because a user may want the beep when they do not have a vibrating device. Maybe call the setting something other than "Vibration Alert On/Off".
This code should do it - be aware it 'assumes' the iPhone is the only device with Vibration capability. Which it is for the moment...
- (NSString *)machine
{
static NSString *machine = nil;
// we keep name around (its like 10 bytes....) forever to stop lots of little mallocs;
if(machine == nil)
{
char * name = nil;
size_t size;
// Set 'oldp' parameter to NULL to get the size of the data
// returned so we can allocate appropriate amount of space
sysctlbyname("hw.machine", NULL, &size, NULL, 0);
// Allocate the space to store name
name = malloc(size);
// Get the platform name
sysctlbyname("hw.machine", name, &size, NULL, 0);
// Place name into a string
machine = [[NSString stringWithUTF8String:name] retain];
// Done with this
free(name);
}
return machine;
}
-(BOOL)hasVibration
{
NSString * machine = [self machine];
if([[machine uppercaseString] rangeOfString:#"IPHONE"].location != NSNotFound)
{
return YES;
}
return NO;
}
Just edited to stop the machine call from doing lots of small mallocs each time its called.

Is there a way to determine the setting of the Ring/Silent switch on the iPhone

I am trying to figure out from my code whether the Ring/Silent switch is on ring or silent. Is there a way to determine this from my program.
Thanks
I did some more searching and found the same question here How to detect iphone is on silent mode.
For completeness, here is the answer from Neil that worked for me?
CFStringRef state = nil;
UInt32 propertySize = sizeof(CFStringRef);
AudioSessionInitialize(NULL, NULL, NULL, NULL);
OSStatus status = AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &propertySize, &state);
if (status == kAudioSessionNoError) {
return (CFStringGetLength(state) == 0); // YES = silent
}
return NO;
It should be noted that this will not work if headphones are connected. You will always get "HeadPhone". This was also reported by coob.
The answer is no.
You can configure how your audio session is affected by the switch, but you cannot tell whether it's on or off.

How do you force audio to come out of the iPhone speaker when a headset is attached?

I'm trying to add a loudspeaker feature to one of my iPhone apps. I already created the recording functionality, but when I play the recorded audio it only plays to the phone headset.
What I need is the recorded file to be played on the loudspeaker, even if there is a headset attached. How could I reroute the audio to do this?
You need to override the default audio properties using AudioSessionSetProperty. Look at something like this to force all audio to go to the speaker (note that this will even happen if headphones are plugged in).
OSStatus err = 0;
UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;
err = AudioSessionSetProperty(kAudioSessionProperty_OverrideAudioRoute,sizeof(audioRouteOverride),&audioRouteOverride);
To detect the headphones, try this (this is literally copy/paste code off of another SO post, so caveat emptor, but it works for me):
/**
* Tells us if the headset is plugged in
*/
- (BOOL) headsetIsPluggedIn
{
BOOL returnVal = NO;
UInt32 routeSize = sizeof(CFStringRef);
CFStringRef route = NULL;
OSStatus error = AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &routeSize, &route);
if (!error && (route != NULL) && ([(NSString*)route rangeOfString:#"Head"].location != NSNotFound))
{
CFRelease(route);
returnVal = YES;
}
return returnVal;
}
EDIT: There is a bit of a discussion in the comments about whether the CFRelease is appropriate or not. Any hardcore Core Foundation experts care to weigh in?