Android: How to create system preferences screen for InputMethodService - sharedpreferences

I'm building a soft keyboard, and I can't figure out how to properly build a preferences screen that shows up in the system settings.
I've built the elements screen in xml (preferences.xml), I've populated the options (just a simple ListPreference to select the desired language). That's all fine.
When launching the keyboard (View onCreate InputView()...) I've set things up to write the default preferences to shared preferences:
PreferenceManager.setDefaultValues(getBaseContext(), R.xml.preferences, true);
SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
I've also set up a shared preferences listener to determine whether any changes are made to the preferences so I can update the dictionary:
SharedPreferences.OnSharedPreferenceChangeListener listener = new SharedPreferences.OnSharedPreferenceChangeListener() {
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
// do stuff
}
};
SP.registerOnSharedPreferenceChangeListener(listener);
All of this seems to be fine. But I can't for the life of me figure out how to get the preferences screen to show up in the system settings (Settings -> Language and Input -> Keyboard and Input Preferences) so I can actually CHANGE anything. All the other keyboards have a slot here that open up into preference screens where settings can be adjusted. My keyboard name has its own slot, but nothing happens if I touch it. How do I get my preferences screen to be accessible through here?

Related

Changing language in UWP doesn't change system features language - only on app restart

I have a UWP application.
And i have a need to change locale on the fly, so i have this for language changing:
Windows.Globalization.ApplicationLanguages.PrimaryLanguageOverride = language.FourDigitCode;
ResourceContext.GetForViewIndependentUse().Reset();
ResourceContext.GetForCurrentView();
But there is a problem that system features language doesn't switch ( only after application relaunch ) how can i fix it?
Here is an example:
Now i run this code:
Windows.Globalization.ApplicationLanguages.PrimaryLanguageOverride = "lv-LV";
ResourceContext.GetForViewIndependentUse().Reset();
ResourceContext.GetForCurrentView();
The UI gets localized, but system features still remain unlocalized:
But when i restart the app, all is OK:
Any ideas how can i fix it?
I'm afraid there is no fix for this and what you've seen is by design. Ref Remarks of PrimaryLanguageOverride property:
When you set the PrimaryLanguageOverride, this is immediately reflected in the Languages property. However, this change may not take effect immediately on resources loaded in the app UI. To make sure the app responds to such changes, you can listen to the QualifierValues property on a default resource context and take whatever actions may be needed to reload resources. Those requirements may vary depending on the UI framework used by the app, and it may be necessary to restart the app.
For your scenario, a restart is needed. I'd suggest that you can add a tip to tell users to restart the app and also a button to close the app like what used in News App.
And to close the app, we can call Application.Exit method like the following.
Application.Current.Exit();
Maybe page reloading can fix it? Try to re-navigate to the same page.
Found the example below here.
//like this
private bool Reload(object param = null)
{
var type = Frame.CurrentSourcePageType;
Frame.Navigate(type, param);
Frame.BackStack.Remove(Frame.BackStack.Last());
}
// or like this
private bool Reload(object param = null)
{
var frame = Window.Current.Content as Frame;
frame.Navigate(frame.CurrentSourcePageType, param);
frame.BackStack.Remove(frame .BackStack.Last());
}

OS X FinderSync 'fails' for /Volumes

I'm creating a simple OS X FinderSync that adds a menu item to the control/right-click menu for all files:
[FIFinderSyncController defaultController].directoryURLs = [NSSet setWithObject:[NSURL fileURLWithPath:#"/"]];
It's working great (the menu item appears, etc.) for all files, except those in /Volumes Oddly, if I manually create a directory in /Volumes and add some files there, the FinderSync's menu item appears when I right-click. However for any files in any mounted Volumes (i.e. from a mounted .dmg), it fails: no menu item appears.
Directly specifying a mounted volume in the directoryURLs similarly fails:
[FIFinderSyncController defaultController].directoryURLs = [NSSet setWithObject:[NSURL fileURLWithPath:#"/Volumes/SomeMountedDMG"]];
It seems others have had similar issues, so maybe this is a known bug/limitation?
The set of subfolders of a folder monitored by a Finder Sync extension does not cross file system boundaries. Although this is not explicitly mentioned in Apple’s documentation, it can be verified empirically (and is still true as of macOS 10.13.3).
As the intended use case for these extensions is to monitor when the Finder displays specific folders being maintained by synchronization utilities like Dropbox, presumably Apple does not see this behavior as a limitation. However, many developers implement Finder Sync extensions as a way of adding arbitrary items to the top-level contextual menu in the Finder (without being constrained to appear in the Services submenu), even though this usage is explicitly discouraged by Apple:
Make sure the Finder Sync extension point is appropriate for the
functionality you plan to provide. The best Finder Sync extensions
support apps that sync the contents of a local folder with a remote
data source. Finder Sync is not intended as a general tool for
modifying the Finder’s user interface.
To work around this limitation and make the extension’s menu item available for any item visible in the Finder, it is necessary to do the following:
Scan for all visible mounted volumes, and initialize the
directoryURLs property of the FIFinderSyncController object to
the result:
import FinderSync
let finderSync = FIFinderSyncController.default()
if let mountedVolumes = FileManager.default.mountedVolumeURLs(includingResourceValuesForKeys: nil,
options: .skipHiddenVolumes) {
finderSync.directoryURLs = Set<URL>(mountedVolumes)
}
Since Finder Sync extensions are long-lived processes, register
for notifications of volumes being mounted, unmounted, and renamed,
and update directoryURLs accordingly:
let notificationCenter = NSWorkspace.shared.notificationCenter
notificationCenter.addObserver(forName: NSWorkspace.didMountNotification, object: nil, queue: .main) {
(notification) in
if let volumeURL = notification.userInfo?[NSWorkspace.volumeURLUserInfoKey] as? URL {
finderSync.directoryURLs.insert(volumeURL)
}
}
(Handling unmount and rename notifications are left as an exercise
for the reader.)

Values not always persisted in App group between companion app & app extension

From time to time, but not always (I have had this working for a bit), the app/extension gets in a state where I can't read a flag set in my App Group between my companion app and my app extension. Don't know how it gets in this state or why the values differ, but it's critical to my application these always be in sync.
Companion app viewDidLoad:
NSUserDefaults *myAppSettings = [[NSUserDefaults alloc] initWithSuiteName:#"group.myapp"];
.....
[myAppSettings setBool:true forKey:#"myBool"];
[myAppSettings synchronize];
NSLog([myAppSettings boolForKey:#"myBool"] ? #"Companion app - bool TRUE" : #"Companion app - bool FALSE");
App extension viewDidLoad
NSUserDefaults *myAppSettings = [[NSUserDefaults alloc] initWithSuiteName:#"group.myapp"];
[myAppSettings synchronize];
NSLog([myAppSettings boolForKey:#"myBool"] ? #"App extension app - bool TRUE" : #"App extension - bool FALSE");
Console output
Companion app - bool TRUE
App extension - bool FALSE
I also synchronize before my companion app will enter background. I have my app group set up in the portal etc.
What am I doing wrong?
EDIT
Apparently others having this problem too:
https://devforums.apple.com/message/977151#977151
"I think that this is currently very glitchy.
Sometimes the data sharing works, then a change and all of a sudden the widget can't see the shared data anymore (both on Simulator and device).
Annoying and hope it's a bit more reliable in next beta!"
EDIT 2
Looks like another person has reported this exact issue as well:
"I also noticed the same thing too.This not only happen to the
NSUserDefaults, but also all the files in the container folder. The
keyboard extension suddenly will lose read/write pemission to the
container folder after using the keyboard for a while."
EDIT 3
More evidence: https://devforums.apple.com/message/1028078#1028078
After I upgrade to beta 3, I noticed that sometimes the keyboard
failed to open the database because it failed to access to the DB
file. The keyboard has been able to access to the file before.
EDIT 4
Seems like this could be because the keyboard loses the RequestsOpenAccess flag. But I can't reproduce it, and there's no way for me to tell for sure.
EDIT 5
Seems like others are reporting this in the iOS8 GM build:
This issue still persists for me in the GM. It seems related to a
keyboard crash.. but also there seems to be some contention between
keyboard and containing app in terms of who creates the suite in what
order. I think this problem is on Apple's end. Trust me, I WANT it to
be my fault but I've spent countless hours with trial and error. No
matter what I do in code and verify with NSLog, it will end up in this
state eventually. Hoping someone finds a magic pill. :S
Has anyone solved this yet?
You must request open access in order to access shared NSUserDefaults. It's stated directly in the App Extension Programming guide:
By default, a keyboard has no network access and cannot share a container with its containing app. To enable these things, set the value of the RequestsOpenAccess Boolean key in the Info.plist file to YES.
Be sure you change the RequestsOpenAccess field to YES. You'll find it in keyboard's Info.plist > NSExtension > NSExtensionAttributes > RequestOpenAccess. Then remove the keyboard in Settings, delete the app, run it again, and add the keyboard again. After you add it, tap on the keyboard name and then flip the switch to enable Allow Full Access. You'll need to instruct the users to follow those same steps to grant access (and reassure them you're not evil), otherwise it simply will not work and you'll never get the data that's stored in your shared container. Note that in iOS 8.3+, if the user hasn't enabled full access the keyboard will be able to access the shared container, but writing to it will not save the data, for security and privacy purposes. In 8.2- you can't access that data without open access granted.
I can confirm that the problem is related to RequestsOpenAccess flag.
Assuming that everything done right (NSUserDefaults use initWithSuiteName, all Capabilities for main application and custom keyboard were set, etc.) I have the next steps:
1) Install the main application and a custom keyboard on device
2) Set 'Allow full access' for the custom keyboard to YES
3) Add some items (in my case this is a simple text templates) in the main app
4) Go to keyboard and check that all items, that were added from the main app,
appeared in custom keyboard
5) Go to main app and add a few more items
6) Go to keyboard and now you will see that nothing changed
7) Go to settings and switch 'Allow full access' to NO and then to YES
8) Go to custom keyboard again and check that item which were added in step 5 appeared.

How do I add my privacy policy link to the Windows Settings charm with Unity?

Windows Store rule 4.1.1 mandate that:
You must provide access to your privacy policy in the Description page
of your app, as well as in the app’s settings as displayed in the
Windows Settings charm.
The Description page is easy, since when you setup your app in the store there's a field where you can enter the URL.
However I'm a bit clueless about how to add this entry in the Windows Setting charm in a Unity project. I've found this answer but that assumes you are in full control and knowledge of your Windows Store app, while I'm just exporting from Unity, so I've no clue on where I would put that code.
So, how do I do that?
Unity is exporting the game as JS or C#.
So have a look to these samples http://code.msdn.microsoft.com/windowsapps/Windows-8-Modern-Style-App-Samples. In these samples, there are a few Setting Charm screnios that you can use in your application.
But remember that, you should add setting charm after export the game.
The plugin prime31/MetroEssentials has the function registerSettingsCommand, which allows you to do just that.
// Registers a settings item with an associated message that will be displaed in a popup when clicked
public static void registerSettingsCommand( string title, string message )
// Registers a settings item with an action. When the settings item is clicked the action will be called.
public static void registerSettingsCommand( string title, Action onActivated )

Add dropdown to settings charm in Windows 8 Metro (C#)

I found how can I add command (looks like link) to settings charm:
SettingsPane.GetForCurrentView().CommandsRequested += MainPage_CommandsRequested;
void MainPage_CommandsRequested(SettingsPane sender, SettingsPaneCommandsRequestedEventArgs args)
{
var cmd = new SettingsCommand("feedback", "Send feedback", new Windows.UI.Popups.UICommandInvokedHandler(x =>
{
App.ShowSendFeedback();
}));
args.Request.ApplicationCommands.Clear();
args.Request.ApplicationCommands.Add(cmd);
}
Now I need adding dropdown list for language selection to settings charm. How can I achieve it?
See also this blog post, which explains how you can display a custom user control whenever one of your settings are selected.
Basically, he moves an off-screen user control on-screen and then hides it again when user interaction is done. To me this feels kind of hack-ish... But I guess that's where WinRT is right now.
You can't add it directly to the Win8 UI. The idea is to publish 'command' links into the Win8 UI and then, when they are clicked, your app gets notified. At that point, you show your own UI with whatever widgets you want in it. See any of the Settings samples in the SDK for an example.