Playing system click sound in iOS keyboard extension - ios

I have followed the instructions on both these links:
How to play keyboard click sound in custom keyboard?
https://developer.apple.com/library/ios/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/InputViews/InputViews.html
and done the following:
header:
#interface Key : UIView <UIInputViewAudioFeedback>
implementation:
- (BOOL) enableInputClicksWhenVisible {
return YES;
}
- (void)tapped:(UITapGestureRecognizer *)sender
{
[[UIDevice currentDevice] playInputClick];
[self.delegate keyHit:_title];
}
Yet it is still not working. What have I missed?

Try this code any time you want to play system click sound in a keyboard extension:
+ (void)keyboardClickSound {
// Check system preference for current setting of Keyboard Click Sound.
CFStringRef applicationID = CFSTR("/var/mobile/Library/Preferences/com.apple.preferences.sounds");
Boolean keyExistsAndHasValidFormat;
BOOL enableInputClicks
= CFPreferencesGetAppBooleanValue(CFSTR("keyboard"), applicationID, &keyExistsAndHasValidFormat);
// Note: If the key does not exist because it has never been changed by a user,
// set it to the default, YES.
if (!keyExistsAndHasValidFormat)
enableInputClicks = YES;
// Play Keyboard Click Sound, if enabled.
// Note: If Open Access=Off, no click sound.
if (enableInputClicks)
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
^{ AudioServicesPlaySystemSound(1104); });
}

If your keyboard extension app contains "RequestsOpenAccess" field to YES,
Then keyboard click sound must need "Allow full Access" switch to On from
General > Keyboard > Keyboards > Your_keyboard setting.
If It is Off then you can not play keyboard key sound.

Related

UIDocumentInteractionController menu does not dismiss (React Native 0.61.5) iOS 13+

I have an issue with UIDocumentInteractionController which is used to open a PDF document.
The problem at this point is when user interacts with the menu my clicking on the Open in {app_name} action, the menu itself fails to close after user interaction leaving the menu open when user comes back to the app.
Dismissing the menu at this point requires user to tap twice on the X in order for menu to be dismissed.
I also tried to close the menu dynamically when app returns to active state by running dismissMenuAnimated on UIDocumentInteractionController instance but it does not work in this case, it does however dismiss the dialog if no interaction was made on it and the method is called.
One note, this issue is only present on never iOS version 13+. On older OS the menu is closed after interaction as expected.
We tried using this code other than all react-native stuff we tried:
#property (nonatomic, strong) UIDocumentInteractionController *documentInteractionController;
#property (atomic) CGRect rect;
RCT_EXPORT_METHOD(openDocumentInteractionControllerWithFileURL:(NSURL *)fileURL){
if (!fileURL) {
// Return NO because there was no valid fileURL.
return;
}
UIViewController *rootCtrl = [[[[UIApplication sharedApplication] delegate] window] rootViewController];
// Open "Open in"-menu
self.documentInteractionController = [UIDocumentInteractionController interactionControllerWithURL:fileURL];
self.documentInteractionController.delegate = self;
BOOL sucess; // Sucess is true if it was possible to open the controller and there are apps available
sucess = [self.documentInteractionController presentOpenInMenuFromRect:self.rect inView:rootCtrl.view animated:YES];
if(!sucess){
// Inform app that the activity has finished
// Return NO because the service was canceled and did not finish because of an error.
// http://developer.apple.com/library/ios/#documentation/uikit/reference/UIActivity_Class/Reference/Reference.html
}
}
RCT_EXPORT_METHOD(dismissDocumentInteractionController){
// Hide menu
[self.documentInteractionController dismissMenuAnimated:YES];
}
But without success.
You need to close the interaction controller menu after user performs his selection in this menu.
You can do it in UIDocumentInteractionControllerDelegate like this:
- (void)documentInteractionController:(UIDocumentInteractionController *)controller willBeginSendingToApplication:(NSString *)application {
[self.documentInteractionController dismissMenuAnimated:YES];
}

How to enable/disable device wise closed caption settings on iOS?

When the accessibility option is turned on the device, we're not able to turn off the closed caption by setting the closedCaptionEnabled option for the AVPlayer instance as we normally would. Is there a way to bypass such option or even to test if it's enabled to lock the CC button if necessary?
You can iterate through each AVPlayerItemTrack and enable/disable it as you wish.
This is how I do in one of my project. I show table of available CC tracks and when the user selects one I iterate through each track, enable the on that user selected and disable rest.
//_selectedTrackIndex = userSelectedIndex;
-(void) setSelectedTrackEnabled {
for (AVPlayerItemTrack * t in [_playerItem tracks]) {
if (counter == _selectedTrackIndex) {
[t setEnabled:YES];
} else {
[t setEnabled:NO];
}
}
}

How to detect which custom keyboard (ios 8) is currently in use for text entering

I am using this solution (https://stackoverflow.com/a/25786928) to detect all custom keyboards activated in Settins app (iOS 8):
- (void)printoutAllActiveKeyboards {
// Array of all active keyboards
NSArray *keyboards = [[[NSUserDefaults standardUserDefaults] dictionaryRepresentation] objectForKey:#"AppleKeyboards"];
for (NSString *keyboard in keyboards)
NSLog(#"Custom keyboard: %#", keyboard);
}
But this in not enough for my project - I need to know which custom keyboard is currently chosen by the user for text entering. I have research stackoverflow and other resources but not found any solution for this. Is there any way to detect in my app which custom keyboard in currently chosen for text entering?
Thank you!
Take a look at this UIApplication API method to disable custom keyboards:
- (BOOL)application:(UIApplication *)application shouldAllowExtensionPointIdentifier:(NSString *)extensionPointIdentifier {
if ([extensionPointIdentifier isEqualToString: UIApplicationKeyboardExtensionPointIdentifier]) {
return NO;
}
return YES;
}
Maybe you can modify the value of UIApplicationKeyboardExtensionPointIdentifier to match your needs

Forcing app to use Apple Keyboard in iOS 8

How can I get my app's UITextfields to only use the Apple keyboard in iOS 8? I do not want to allow third party keyboards, period. I understand it may be bad user experience so please don't discuss that point with me :)
I know I can set the securedEntry property to true to force the Apple keyboard (http://www.imore.com/custom-keyboards-ios-8-explained). Maybe iOS 8 will let me set this property and NOT mask the text?
Apple provides an API for exactly that. Put this in your AppDelegate
- (BOOL)application:(UIApplication *)application
shouldAllowExtensionPointIdentifier:(NSString *)extensionPointIdentifier
{
if ([extensionPointIdentifier isEqualToString:#"com.apple.keyboard-service"]) {
return NO;
}
return YES;
}
This is the cleanest and documented way to do it :)
By setting a UITextView or UITextField's property of Secure Text Entry to YES, custom keyboards will not be shown by default and can also not be toggled to.
This will also, unfortunately, hide key press information as well as over-ride and disable auto caps and auto correct and spelling suggestions. So you have to toggle is back off to NO after you're done forcibly making the user use Apple keyboard.
Toggling this property on and then off can force the Apple Keyboard to be the first key that displays by default.
NOW, the user will still be able to press the global key so you have two options:
•One, you can just let them and detect if they do using [[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(inputModeDidChange:) name:#"UITextInputCurrentInputModeDidChangeNotification"
object:nil]; and just reloop the secureTextEntry code above and force switch back to Apple default keyboard (unprofessional method, but very easy to program). (*Note! This will also prevent users from being able to use the dictation keyboard (clicking the microphone icon button next to the space bar), unless you use undocumented code to detect if it's dictation or not (which does exist and has supposedly passed Apple validation on a few accounts. Info on this can be found here)
Or
•Two: to use UIWindows to get ONTOP of the default keyboard and add a UIWindow with userInteractionEnabled set to YES covering where that key is location (this will take a few conditional statements to make sure you're covering the right "change keyboard key" for every possibility. (i.e. landscape keyboard iPhone4, portrait keyboard iPhone5, etc).
Here is some demo code though of it working for portrait keyboards (iphone5 and iphone4)
viewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController <UITextFieldDelegate> {
UITextField *theTextField;
UIWindow *statusWindow;
}
#end
viewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
theTextField = [[UITextField alloc] initWithFrame:CGRectMake(50, 50, 50, 250)];
[theTextField becomeFirstResponder];
theTextField.secureTextEntry = YES;//turn back OFF later (like in `viewDidAppear`) and reset textField properties to YES (like auto correct, auto caps, etc).
theTextField.delegate = self;
[self.view addSubview:theTextField];
//UIWindow *statusWindow; MUST be defined in .h file!
statusWindow = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
statusWindow.frame = CGRectMake(37, self.view.frame.size.height-47, 45, 45);
statusWindow.windowLevel = UIWindowLevelStatusBar;
statusWindow.hidden = NO;
statusWindow.backgroundColor = [UIColor clearColor];
UIButton *keyboardCover = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 45, 45)];
keyboardCover.backgroundColor = [UIColor redColor];
[statusWindow addSubview:keyboardCover];
//statusWindow.alpha = 1.00;
statusWindow.userInteractionEnabled = YES;
[statusWindow makeKeyAndVisible];
}
-(void)viewDidAppear:(BOOL)animated {
[theTextField resignFirstResponder];
theTextField.secureTextEntry = NO;
theTextField.autocorrectionType = 2;//ON
theTextField.autocapitalizationType = 2;//ON
theTextField.spellCheckingType = 2;//ON
[theTextField becomeFirstResponder];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Here is an example of what that code will look like... I was using a custom keyboard, when I launched the app it forced me over to the Apple keyboard, then put a red square over the "change keyboard" button, which made it impossible for me to click the button to change the keyboard. (the red square can be changed to be anything of course like a blank key or the globe icon in a faded (disabled) state.)
To the best of my knowledge, there is no way to do this. However, if you're willing to put in the effort, you could create your own custom input view that mimics the standard Apple keyboard, and use that instead. For more on input views, refer to the documentation.

iOS SDK: Disable text dictation for UITextField [duplicate]

Ours is a health care app. We have a HIPAA-compliant speech recognizer in the app through which all the dictation can take place. The hospitals don't want physicians to accidentally start speaking to the Nuance Dragon server which is not HIPAA-compliant. So, I was looking for ways I could supress the dictation key on the keyboard.
I tried putting a fake button on the Dictation button on the key pad, but on the iPad the split dock concept keeps moving the microphone all over the screen. This does not sound like a reasonable solution. Are there any experts out there who could help me?
OKAY, finally got it! The trick is to observe UITextInputMode change notifications, and then to gather the identifier of the changed mode (Code seems to avoid the direct use of Private API, though seems to require a little knowledge of private API in general), and when the mode changes to dictation, resignFirstResponder (which will cancel the voice dictation). YAY! Here is some code:
Somewhere in your app delegate (at least that's where I put it)
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(inputModeDidChange:) name:#"UITextInputCurrentInputModeDidChangeNotification"
object:nil];
And then you can
UIView *resignFirstResponder(UIView *theView)
{
if([theView isFirstResponder])
{
[theView resignFirstResponder];
return theView;
}
for(UIView *subview in theView.subviews)
{
UIView *result = resignFirstResponder(subview);
if(result) return result;
}
return nil;
}
- (void)inputModeDidChange:(NSNotification *)notification
{
// Allows us to block dictation
UITextInputMode *inputMode = [UITextInputMode currentInputMode];
NSString *modeIdentifier = [inputMode respondsToSelector:#selector(identifier)] ? (NSString *)[inputMode performSelector:#selector(identifier)] : nil;
if([modeIdentifier isEqualToString:#"dictation"])
{
[UIView setAnimationsEnabled:NO];
UIView *resigned = resignFirstResponder(window);
[resigned becomeFirstResponder];
[UIView setAnimationsEnabled:YES];
UIAlertView *denyAlert = [[[UIAlertView alloc] initWithTitle:#"Denied" message:nil delegate:nil cancelButtonTitle:#"Okay" otherButtonTitles:nil] autorelease];
[denyAlert show];
}
}
you can create your own keyboard and set the inputView for the text fields that will accept this dictation. then when they press any keys they will get your keyboard, therefore you dont have to override the keys on the standard keyboard, you will be able to customize the entire thing.
self.myButton.inputView = self.customKeyboardView;
here is an example of an extremely custom keyboard
http://blog.carbonfive.com/2012/03/12/customizing-the-ios-keyboard/
Ray also has a teriffic tutorial on custom keyboards.
http://www.raywenderlich.com/1063/ipad-for-iphone-developers-101-custom-input-view-tutorial
I hope that helps.
I had the same issue and the only way i found that hides the dictation button is changing the keyboard type.
For me changing it to email type seemed to be reasonable:
textField.keyboardType = UIKeyboardTypeEmailAddress;
You could make a subclass of UITextField/UITextView that overrides insertDictationResult: to not insert anything.
This won't prevent the information being sent, but you could then display an alert informing them of the breech.
This is a Swift 4 solution based on #BadPirate's hack. It will trigger the initial bell sound stating that dictation started, but the dictation layout will never appear on the keyboard.
This will not hide the dictation button from your keyboard: for that the only option seems to be to use an email layout with UIKeyboardType.emailAddress.
In viewDidLoad of the view controller owning the UITextField for which you want to disable dictation:
// Track if the keyboard mode changed to discard dictation
NotificationCenter.default.addObserver(self,
selector: #selector(keyboardModeChanged),
name: UITextInputMode.currentInputModeDidChangeNotification,
object: nil)
Then the custom callback:
#objc func keyboardModeChanged(notification: Notification) {
// Could use `Selector("identifier")` instead for idSelector but
// it would trigger a warning advising to use #selector instead
let idSelector = #selector(getter: UILayoutGuide.identifier)
// Check if the text input mode is dictation
guard
let textField = yourTextField as? UITextField
let mode = textField.textInputMode,
mode.responds(to: idSelector),
let id = mode.perform(idSelector)?.takeUnretainedValue() as? String,
id.contains("dictation") else {
return
}
// If the keyboard is in dictation mode, hide
// then show the keyboard without animations
// to display the initial generic keyboard
UIView.setAnimationsEnabled(false)
textField.resignFirstResponder()
textField.becomeFirstResponder()
UIView.setAnimationsEnabled(true)
// Do additional update here to inform your
// user that dictation is disabled
}

Resources