community-cordova-plugin-native-settings 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,12 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <module type="WEB_MODULE" version="4">
3
+ <component name="NewModuleRootManager">
4
+ <content url="file://$MODULE_DIR$">
5
+ <excludeFolder url="file://$MODULE_DIR$/.tmp" />
6
+ <excludeFolder url="file://$MODULE_DIR$/temp" />
7
+ <excludeFolder url="file://$MODULE_DIR$/tmp" />
8
+ </content>
9
+ <orderEntry type="inheritedJdk" />
10
+ <orderEntry type="sourceFolder" forTests="false" />
11
+ </component>
12
+ </module>
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="ProjectModuleManager">
4
+ <modules>
5
+ <module fileurl="file://$PROJECT_DIR$/.idea/community-cordova-plugin-native-settings.iml" filepath="$PROJECT_DIR$/.idea/community-cordova-plugin-native-settings.iml" />
6
+ </modules>
7
+ </component>
8
+ </project>
package/.idea/vcs.xml ADDED
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="VcsDirectoryMappings">
4
+ <mapping directory="$PROJECT_DIR$/../.." vcs="Git" />
5
+ </component>
6
+ </project>
package/README.md ADDED
@@ -0,0 +1,191 @@
1
+ [![NPM version](https://img.shields.io/npm/v/community-cordova-plugin-native-settings)](https://www.npmjs.com/package/community-cordova-plugin-native-settings)
2
+
3
+ # community-cordova-plugin-native-settings
4
+
5
+ I dedicate a considerable amount of my free time to developing and maintaining many cordova plugins for the community ([See the list with all my maintained plugins][community_plugins]).
6
+ To help ensure this plugin is kept updated,
7
+ new features are added and bugfixes are implemented quickly,
8
+ please donate a couple of dollars (or a little more if you can stretch) as this will help me to afford to dedicate time to its maintenance.
9
+ Please consider donating if you're using this plugin in an app that makes you money,
10
+ or if you're asking for new features or priority bug fixes. Thank you!
11
+
12
+ [![](https://img.shields.io/static/v1?label=Sponsor%20Me&style=for-the-badge&message=%E2%9D%A4&logo=GitHub&color=%23fe8e86)](https://github.com/sponsors/eyalin)
13
+
14
+ ---
15
+
16
+ # Community Cordova Plugin Native Settings
17
+
18
+ ## Overview
19
+ This Cordova plugin provides a simple way to open native device settings screens on Android and iOS platforms. It allows your app to deep-link into specific system settings pages (Wi‑Fi, Bluetooth, Location, etc.) with a clean Promise-based API.
20
+
21
+ ## Installation
22
+ To install the plugin in your Cordova project, use the following command:
23
+ ```bash
24
+ cordova plugin add community-cordova-plugin-native-settings
25
+ ```
26
+
27
+ ## Usage
28
+ The plugin provides a Promise-based API (also compatible with callbacks) to open various system settings screens.
29
+
30
+ ### Basic JavaScript Usage
31
+ ```javascript
32
+ document.addEventListener('deviceready', onDeviceReady, false);
33
+
34
+ function onDeviceReady() {
35
+ // Open Wi‑Fi settings
36
+ cordova.plugins.settings.open('wifi')
37
+ .then(() => console.log('Wi‑Fi settings opened'))
38
+ .catch(err => console.error('Failed to open settings:', err));
39
+
40
+ // Open settings in a new task (Android only)
41
+ cordova.plugins.settings.open({ setting: 'wifi', newTask: true })
42
+ .then(() => console.log('Settings opened in new task'))
43
+ .catch(err => console.error('Error:', err));
44
+ }
45
+ ```
46
+
47
+ ### TypeScript/Angular Usage
48
+ ```typescript
49
+ import { INativeSettings } from 'community-cordova-plugin-native-settings';
50
+
51
+ declare const cordova: any;
52
+
53
+ @Injectable({
54
+ providedIn: 'root'
55
+ })
56
+ export class SettingsService {
57
+ private settings: INativeSettings;
58
+
59
+ constructor() {
60
+ this.settings = cordova.plugins.settings;
61
+ }
62
+
63
+ async openWifiSettings(newTask: boolean = false): Promise<void> {
64
+ try {
65
+ await this.settings.open({ setting: 'wifi', newTask });
66
+ console.log('Wi‑Fi settings opened');
67
+ } catch (err) {
68
+ console.error('Failed to open settings:', err);
69
+ throw err;
70
+ }
71
+ }
72
+
73
+ async isWifiSettingsAvailable(): Promise<boolean> {
74
+ return await this.settings.isAvailable('wifi');
75
+ }
76
+ }
77
+ ```
78
+
79
+ ## API Reference
80
+
81
+ ### Methods
82
+
83
+ #### open(options: string | INativeSettingsOptions): Promise<void>
84
+ Opens the requested settings page.
85
+
86
+ Parameters:
87
+ - `options`: Either a string (setting name) or an object with:
88
+ - `setting`: The settings page to open
89
+ - `newTask`: (Android only) Whether to open in a new task
90
+
91
+ #### isAvailable(setting: string): Promise<boolean>
92
+ Checks if a specific settings page is available on the current device.
93
+
94
+ Parameters:
95
+ - `setting`: The settings page to check
96
+
97
+ ### Supported Settings
98
+
99
+ #### Android
100
+ - 'wifi' - Wi‑Fi settings
101
+ - 'location' - Location settings
102
+ - 'bluetooth' - Bluetooth settings
103
+ - 'accessibility' - Accessibility settings
104
+ - 'add_account' - Add account settings
105
+ - 'airplane_mode' - Airplane mode settings
106
+ - 'apn' - APN settings
107
+ - 'application_details' - App details
108
+ - 'application_development' - Development settings
109
+ - 'application' - Application settings
110
+ - 'battery_optimization' - Battery optimization
111
+ - 'device_info' - Device info
112
+ - 'display' - Display settings
113
+ - 'keyboard' - Keyboard settings
114
+ - 'manage_all_applications' - All apps
115
+ - 'manage_applications' - App management
116
+ - 'memory_card' - Memory card
117
+ - 'network' - Network settings
118
+ - 'nfc' - NFC settings
119
+ - 'notification' - Notification settings
120
+ - 'security' - Security settings
121
+ - 'sound' - Sound settings
122
+ - 'sync' - Sync settings
123
+ - 'usage' - Usage settings
124
+ - 'user_dictionary' - User dictionary
125
+ - 'voice_input' - Voice input settings
126
+ - 'vpn' - VPN settings
127
+
128
+ #### iOS
129
+ - 'wifi' - Wi‑Fi settings
130
+ - 'bluetooth' - Bluetooth settings
131
+ - 'location' - Location settings
132
+ - 'settings' - App settings
133
+ - 'about' - About settings
134
+ - 'accessibility' - Accessibility settings
135
+ - 'account' - Account settings
136
+ - 'airplane_mode' - Airplane mode
137
+ - 'battery' - Battery settings
138
+ - 'browser' - Browser settings
139
+ - 'date' - Date settings
140
+ - 'facetime' - FaceTime settings
141
+ - 'keyboard' - Keyboard settings
142
+ - 'locale' - Language settings
143
+ - 'music' - Music settings
144
+ - 'notification' - Notification settings
145
+ - 'photos' - Photos settings
146
+ - 'profile' - Profile settings
147
+ - 'sounds' - Sound settings
148
+ - 'storage' - Storage settings
149
+ - 'wallpaper' - Wallpaper settings
150
+
151
+ **Note**: Some iOS URL schemes are unofficial and may not work on all iOS versions. The plugin will fall back to opening the app's settings page in such cases.
152
+
153
+ ## Platform Specifics
154
+ - **Android**: Provides comprehensive access to system settings through Android's Settings API
155
+ - **iOS**: Uses URL schemes to deep-link into settings; some settings may fall back to the app settings page due to iOS restrictions
156
+
157
+ ## Contributing
158
+ Contributions to the plugin are welcome! Please follow the standard fork and pull request workflow.
159
+
160
+ ## License
161
+ This project is licensed under the MIT License.
162
+
163
+ ---
164
+ [community_plugins]: https://github.com/EYALIN?tab=repositories&q=community&type=&language=&sort=
165
+
166
+ Android (uses android.provider.Settings actions):
167
+
168
+ - accessibility, account, airplane_mode, apn, application_details, application_development, application
169
+ - battery_optimization, bluetooth, captioning, cast, data_roaming, date, display, dream
170
+ - keyboard, keyboard_subtype, storage, locale, location, manage_all_applications, manage_applications
171
+ - memory_card, network, nfcsharing, nfc_payment, nfc_settings, print, privacy, quick_launch
172
+ - search, security, settings, show_regulatory_info, sound, sync, usage, user_dictionary
173
+ - voice_input, wifi_ip, wifi, wireless
174
+
175
+ iOS (deep-links; availability varies by iOS version):
176
+
177
+ - about, accessibility, account, airplane_mode, autolock, battery, bluetooth, cellular, date
178
+ - facetime, keyboard, language, location, music, notifications (falls back to app settings), photos
179
+ - privacy, reset, ringtone, safari, sound, software_update, storage, vpn, wallpaper, wifi
180
+
181
+ Note: iOS deep-linking uses App-Prefs / UIApplicationOpenSettingsURLString fallbacks. Apple may restrict or change these schemes in new iOS releases.
182
+
183
+ ## Contributing
184
+
185
+ Contributions are welcome. Please open issues or PRs against the repository.
186
+
187
+ ## License
188
+
189
+ MIT
190
+
191
+ [community_plugins]: https://github.com/search?q=topic%3Acordova-plugin+org%3Aeyalin&type=Repositories
@@ -0,0 +1,13 @@
1
+ # Release Notes
2
+
3
+ ### 1.0.0 (Nov 07, 2025)
4
+ * Initial release as a community plugin
5
+ * Added Promise-based API
6
+ * Added TypeScript support
7
+ * Added isAvailable method
8
+ * Improved error handling
9
+ * Added comprehensive documentation
10
+ * Added support for opening settings in new task (Android)
11
+ * Modernized codebase and API design
12
+ * Added full type definitions
13
+ * Improved iOS compatibility
package/package.json ADDED
@@ -0,0 +1,22 @@
1
+
2
+ {
3
+ "name": "community-cordova-plugin-native-settings",
4
+ "version": "1.0.0",
5
+ "description": "A Cordova plugin to open native device settings screens",
6
+ "types": "./types/index.d.ts",
7
+ "cordova": {
8
+ "id": "community-cordova-plugin-native-settings",
9
+ "platforms": ["android", "ios"]
10
+ },
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "git+https://github.com/eyalin/community-cordova-plugin-native-settings.git"
14
+ },
15
+ "keywords": ["ecosystem:cordova","cordova-android","cordova-ios","settings","native-settings","preferences"],
16
+ "author": "EYALIN",
17
+ "license": "MIT",
18
+ "bugs": { "url": "https://github.com/eyalin/community-cordova-plugin-native-settings/issues" },
19
+ "homepage": "https://github.com/eyalin/community-cordova-plugin-native-settings#readme",
20
+ "funding": { "type": "github", "url": "https://github.com/sponsors/eyalin" }
21
+ }
22
+
package/plugin.xml ADDED
@@ -0,0 +1,48 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
3
+ xmlns:android="http://schemas.android.com/apk/res/android"
4
+ id="community-cordova-plugin-native-settings"
5
+ version="1.0.0">
6
+ <name>Cordova Plugin Native Settings</name>
7
+ <description>A Cordova plugin to open native device settings screens</description>
8
+ <license>MIT</license>
9
+ <keywords>cordova,settings,native,preferences,options,android,ios</keywords>
10
+ <repo>https://github.com/eyalin/community-cordova-plugin-native-settings.git</repo>
11
+ <issue>https://github.com/eyalin/community-cordova-plugin-native-settings/issues</issue>
12
+
13
+ <engines>
14
+ <engine name="cordova" version=">=4.0.0" />
15
+ </engines>
16
+
17
+ <js-module src="www/settings.js" name="SettingsPlugin">
18
+ <clobbers target="SettingsPlugin" />
19
+ </js-module>
20
+
21
+ <!-- android -->
22
+ <platform name="android">
23
+ <config-file target="res/xml/config.xml" parent="/*">
24
+ <feature name="NativeSettings">
25
+ <param name="android-package" value="com.ionicframework.plugins.nativesettings.NativeSettings" />
26
+ </feature>
27
+ </config-file>
28
+ <source-file src="src/android/NativeSettings.java" target-dir="src/com/ionicframework/plugins/nativesettings" />
29
+ </platform>
30
+
31
+ <!-- ios -->
32
+ <platform name="ios">
33
+ <config-file target="config.xml" parent="/*">
34
+ <feature name="NativeSettings">
35
+ <param name="ios-package" value="NativeSettings" />
36
+ </feature>
37
+ </config-file>
38
+
39
+ <!-- Add App-Prefs to LSApplicationQueriesSchemes -->
40
+ <config-file target="*-Info.plist" parent="LSApplicationQueriesSchemes">
41
+ <array>
42
+ <string>App-Prefs</string>
43
+ </array>
44
+ </config-file>
45
+ <header-file src="src/ios/NativeSettings.h" />
46
+ <source-file src="src/ios/NativeSettings.m" />
47
+ </platform>
48
+ </plugin>
@@ -0,0 +1,42 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
3
+ xmlns:android="http://schemas.android.com/apk/res/android"
4
+ id="community-cordova-plugin-native-settings"
5
+ version="1.0.0">
6
+ <name>Cordova Plugin Native Settings</name>
7
+ <description>A Cordova plugin to open native device settings screens</description>
8
+ <license>MIT</license>
9
+ <keywords>cordova,settings,native,preferences,options,android,ios</keywords>
10
+ <repo>https://github.com/eyalin/community-cordova-plugin-native-settings.git</repo>
11
+ <issue>https://github.com/eyalin/community-cordova-plugin-native-settings/issues</issue>
12
+
13
+ <engines>
14
+ <engine name="cordova" version=">=4.0.0" />
15
+ </engines>
16
+
17
+ <js-module src="www/settings.js" name="SettingsPlugin">
18
+ <clobbers target="cordova.plugins.settings" />
19
+ <clobbers target="NativeSettings" />
20
+ </js-module>
21
+
22
+ <!-- android -->
23
+ <platform name="android">
24
+ <config-file target="res/xml/config.xml" parent="/*">
25
+ <feature name="NativeSettings">
26
+ <param name="android-package" value="com.ionicframework.plugins.nativesettings.NativeSettings" />
27
+ </feature>
28
+ </config-file>
29
+ <source-file src="src/android/NativeSettings.java" target-dir="src/com/ionicframework/plugins/nativesettings" />
30
+ </platform>
31
+
32
+ <!-- ios -->
33
+ <platform name="ios">
34
+ <config-file target="config.xml" parent="/*">
35
+ <feature name="NativeSettings">
36
+ <param name="ios-package" value="NativeSettings" />
37
+ </feature>
38
+ </config-file>
39
+ <header-file src="src/ios/NativeSettings.h" />
40
+ <source-file src="src/ios/NativeSettings.m" />
41
+ </platform>
42
+ </plugin>
@@ -0,0 +1,161 @@
1
+ package com.ionicframework.plugins.nativesettings;
2
+
3
+ import org.apache.cordova.CallbackContext;
4
+ import org.apache.cordova.CordovaPlugin;
5
+ import org.apache.cordova.PluginResult;
6
+ import org.json.JSONArray;
7
+ import org.json.JSONException;
8
+
9
+ import android.content.Intent;
10
+ import android.content.Context;
11
+ import android.net.Uri;
12
+ import android.os.Build;
13
+ import android.provider.Settings;
14
+ import java.util.HashMap;
15
+ import java.util.Map;
16
+
17
+ public class NativeSettings extends CordovaPlugin {
18
+ private static final Map<String, String> settingsMap = new HashMap<>();
19
+
20
+ static {
21
+ // Initialize settings map
22
+ settingsMap.put("accessibility", Settings.ACTION_ACCESSIBILITY_SETTINGS);
23
+ settingsMap.put("account", Settings.ACTION_ADD_ACCOUNT);
24
+ settingsMap.put("airplane_mode", Settings.ACTION_AIRPLANE_MODE_SETTINGS);
25
+ settingsMap.put("apn", Settings.ACTION_APN_SETTINGS);
26
+ settingsMap.put("application_details", Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
27
+ settingsMap.put("application_development", Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS);
28
+ settingsMap.put("application", Settings.ACTION_APPLICATION_SETTINGS);
29
+ settingsMap.put("bluetooth", Settings.ACTION_BLUETOOTH_SETTINGS);
30
+ // Android settings map - expanded
31
+ settingsMap.put("battery_optimization", Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS);
32
+ settingsMap.put("captioning", Settings.ACTION_CAPTIONING_SETTINGS);
33
+ settingsMap.put("cast", Settings.ACTION_CAST_SETTINGS);
34
+ settingsMap.put("data_roaming", Settings.ACTION_DATA_ROAMING_SETTINGS);
35
+ settingsMap.put("date", Settings.ACTION_DATE_SETTINGS);
36
+ settingsMap.put("about", Settings.ACTION_DEVICE_INFO_SETTINGS);
37
+ settingsMap.put("display", Settings.ACTION_DISPLAY_SETTINGS);
38
+ settingsMap.put("dream", Settings.ACTION_DREAM_SETTINGS);
39
+ settingsMap.put("home", Settings.ACTION_HOME_SETTINGS);
40
+ settingsMap.put("keyboard", Settings.ACTION_INPUT_METHOD_SETTINGS);
41
+ settingsMap.put("keyboard_subtype", Settings.ACTION_INPUT_METHOD_SUBTYPE_SETTINGS);
42
+ settingsMap.put("storage", Settings.ACTION_INTERNAL_STORAGE_SETTINGS);
43
+ settingsMap.put("locale", Settings.ACTION_LOCALE_SETTINGS);
44
+ settingsMap.put("location", Settings.ACTION_LOCATION_SOURCE_SETTINGS);
45
+ settingsMap.put("manage_all_applications", Settings.ACTION_MANAGE_ALL_APPLICATIONS_SETTINGS);
46
+ settingsMap.put("manage_applications", Settings.ACTION_MANAGE_APPLICATIONS_SETTINGS);
47
+ settingsMap.put("memory_card", Settings.ACTION_MEMORY_CARD_SETTINGS);
48
+ settingsMap.put("network", Settings.ACTION_NETWORK_OPERATOR_SETTINGS);
49
+ settingsMap.put("nfcsharing", Settings.ACTION_NFCSHARING_SETTINGS);
50
+ settingsMap.put("nfc_payment", Settings.ACTION_NFC_PAYMENT_SETTINGS);
51
+ settingsMap.put("nfc_settings", Settings.ACTION_NFC_SETTINGS);
52
+ settingsMap.put("print", Settings.ACTION_PRINT_SETTINGS);
53
+ settingsMap.put("privacy", Settings.ACTION_PRIVACY_SETTINGS);
54
+ settingsMap.put("quick_launch", Settings.ACTION_QUICK_LAUNCH_SETTINGS);
55
+ settingsMap.put("search", Settings.ACTION_SEARCH_SETTINGS);
56
+ settingsMap.put("security", Settings.ACTION_SECURITY_SETTINGS);
57
+ settingsMap.put("settings", Settings.ACTION_SETTINGS);
58
+ settingsMap.put("show_regulatory_info", Settings.ACTION_SHOW_REGULATORY_INFO);
59
+ settingsMap.put("sound", Settings.ACTION_SOUND_SETTINGS);
60
+ settingsMap.put("sync", Settings.ACTION_SYNC_SETTINGS);
61
+ settingsMap.put("usage", Settings.ACTION_USAGE_ACCESS_SETTINGS);
62
+ settingsMap.put("user_dictionary", Settings.ACTION_USER_DICTIONARY_SETTINGS);
63
+ settingsMap.put("voice_input", Settings.ACTION_VOICE_INPUT_SETTINGS);
64
+ settingsMap.put("wifi_ip", Settings.ACTION_WIFI_IP_SETTINGS);
65
+ settingsMap.put("wifi", Settings.ACTION_WIFI_SETTINGS);
66
+ settingsMap.put("wireless", Settings.ACTION_WIRELESS_SETTINGS);
67
+ }
68
+
69
+ @Override
70
+ public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
71
+ if (action.equals("open")) {
72
+ return openSettings(args, callbackContext);
73
+ } else if (action.equals("isAvailable")) {
74
+ return checkAvailability(args, callbackContext);
75
+ }
76
+ return false;
77
+ }
78
+
79
+ private boolean openSettings(JSONArray args, CallbackContext callbackContext) throws JSONException {
80
+ if (args == null || args.length() == 0) {
81
+ callbackContext.error("Setting name is required");
82
+ return false;
83
+ }
84
+
85
+ String settingName = args.getString(0);
86
+ boolean newTask = args.length() > 1 && args.getBoolean(1);
87
+
88
+ Intent intent = getSettingsIntent(settingName);
89
+ if (intent == null) {
90
+ callbackContext.error("Invalid setting: " + settingName);
91
+ return false;
92
+ }
93
+
94
+ try {
95
+ if (newTask) {
96
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
97
+ }
98
+ this.cordova.getActivity().startActivity(intent);
99
+ callbackContext.success();
100
+ return true;
101
+ } catch (Exception e) {
102
+ callbackContext.error("Failed to open settings: " + e.getMessage());
103
+ return false;
104
+ }
105
+ }
106
+
107
+ private boolean checkAvailability(JSONArray args, CallbackContext callbackContext) throws JSONException {
108
+ if (args == null || args.length() == 0) {
109
+ callbackContext.error("Setting name is required");
110
+ return false;
111
+ }
112
+
113
+ String settingName = args.getString(0);
114
+ Intent intent = getSettingsIntent(settingName);
115
+
116
+ callbackContext.success(intent != null ? 1 : 0);
117
+ return true;
118
+ }
119
+
120
+ private Intent getSettingsIntent(String setting) {
121
+ Context context = this.cordova.getActivity().getApplicationContext();
122
+ Uri packageUri = Uri.parse("package:" + context.getPackageName());
123
+
124
+ String action = settingsMap.get(setting);
125
+ if (action != null) {
126
+ if (action.equals(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)) {
127
+ return new Intent(action, packageUri);
128
+ }
129
+ return new Intent(action);
130
+ }
131
+
132
+ // Special cases
133
+ switch (setting) {
134
+ case "notification_id":
135
+ return getNotificationSettingsIntent(context);
136
+ case "store":
137
+ return new Intent(Intent.ACTION_VIEW,
138
+ Uri.parse("market://details?id=" + context.getPackageName()));
139
+ // Add more special cases...
140
+ }
141
+
142
+ return null;
143
+ }
144
+
145
+ private Intent getNotificationSettingsIntent(Context context) {
146
+ Intent intent = new Intent();
147
+ if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1) {
148
+ intent.setAction(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
149
+ intent.putExtra(Settings.EXTRA_APP_PACKAGE, context.getPackageName());
150
+ } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
151
+ intent.setAction("android.settings.APP_NOTIFICATION_SETTINGS");
152
+ intent.putExtra("app_package", context.getPackageName());
153
+ intent.putExtra("app_uid", context.getApplicationInfo().uid);
154
+ } else {
155
+ intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
156
+ intent.addCategory(Intent.CATEGORY_DEFAULT);
157
+ intent.setData(Uri.parse("package:" + context.getPackageName()));
158
+ }
159
+ return intent;
160
+ }
161
+ }
@@ -0,0 +1,8 @@
1
+ #import <Cordova/CDV.h>
2
+
3
+ @interface NativeSettings : CDVPlugin
4
+
5
+ - (void)open:(CDVInvokedUrlCommand*)command;
6
+ - (void)isAvailable:(CDVInvokedUrlCommand*)command;
7
+
8
+ @end
@@ -0,0 +1,199 @@
1
+ #import "NativeSettings.h"
2
+ #import <UIKit/UIKit.h>
3
+
4
+ @implementation NativeSettings
5
+
6
+ - (void)open:(CDVInvokedUrlCommand*)command {
7
+ CDVPluginResult* pluginResult = nil;
8
+ NSString* setting = [command.arguments objectAtIndex:0];
9
+
10
+ if (!setting) {
11
+ pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Setting name is required"];
12
+ [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
13
+ return;
14
+ }
15
+
16
+ NSURL* url = [self getSettingsURL:setting];
17
+ if (!url) {
18
+ pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Invalid setting"];
19
+ [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
20
+ return;
21
+ }
22
+ NSString* urlString = [url absoluteString];
23
+ NSLog(@"NativeSettings: attempting to open settings URL: %@", urlString);
24
+
25
+ if (@available(iOS 10.0, *)) {
26
+ [[UIApplication sharedApplication] openURL:url options:@{} completionHandler:^(BOOL success) {
27
+ CDVPluginResult* result = nil;
28
+ if (success) {
29
+ // Return the actual URL that was opened for debugging
30
+ result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:urlString];
31
+ } else {
32
+ NSString* msg = [NSString stringWithFormat:@"Failed to open settings: %@", urlString];
33
+ result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:msg];
34
+ }
35
+ [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
36
+ }];
37
+ } else {
38
+ BOOL success = [[UIApplication sharedApplication] openURL:url];
39
+ if (success) {
40
+ pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:urlString];
41
+ } else {
42
+ NSString* msg = [NSString stringWithFormat:@"Failed to open settings: %@", urlString];
43
+ pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:msg];
44
+ }
45
+ [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
46
+ }
47
+ }
48
+
49
+ - (void)isAvailable:(CDVInvokedUrlCommand*)command {
50
+ NSString* setting = [command.arguments objectAtIndex:0];
51
+ BOOL isAvailable = NO;
52
+
53
+ if (setting) {
54
+ NSURL* url = [self getSettingsURL:setting];
55
+ if (url) {
56
+ if (@available(iOS 10.0, *)) {
57
+ isAvailable = [[UIApplication sharedApplication] canOpenURL:url];
58
+ } else {
59
+ isAvailable = YES; // Assume available on older iOS versions
60
+ }
61
+ }
62
+ }
63
+
64
+ CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:isAvailable];
65
+ [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
66
+ }
67
+
68
+ - (NSURL*)getSettingsURL:(NSString*)setting {
69
+ // iOS settings mappings (App-Prefs:root=...) - many of these URL schemes are unofficial
70
+ // and may not work on all iOS versions. We fall back to UIApplicationOpenSettingsURLString
71
+ // (app-specific settings) where appropriate.
72
+ // Helper to prefer App-Prefs URLs when the system allows them, otherwise fallback
73
+ // to the official UIApplicationOpenSettingsURLString which opens the app's settings.
74
+ NSURL* (^prefURLIfAvailable)(NSString*) = ^NSURL*(NSString* urlString) {
75
+ // On iOS 13+, try to use the official Settings URLs first
76
+ if (@available(iOS 13.0, *)) {
77
+ // There's no public UIApplication method `settingsURLString:` — construct the URL
78
+ // from the provided App-Prefs string and verify it can be opened when possible.
79
+ NSURL* url = [NSURL URLWithString:urlString];
80
+ if (@available(iOS 10.0, *)) {
81
+ if (![[UIApplication sharedApplication] canOpenURL:url]) {
82
+ return nil;
83
+ }
84
+ }
85
+ return url;
86
+ }
87
+
88
+ // On older iOS, try App-Prefs scheme
89
+ NSURL* url = [NSURL URLWithString:urlString];
90
+ if (@available(iOS 10.0, *)) {
91
+ // If we can't open App-Prefs URL, return nil to show "not available"
92
+ // instead of falling back to app settings
93
+ if (![[UIApplication sharedApplication] canOpenURL:url]) {
94
+ return nil;
95
+ }
96
+ }
97
+ return url;
98
+ };
99
+ if ([setting isEqualToString:@"about"]) {
100
+ return [NSURL URLWithString:UIApplicationOpenSettingsURLString];
101
+ }
102
+ else if ([setting isEqualToString:@"accessibility"]) {
103
+ return prefURLIfAvailable(@"App-Prefs:root=General&path=ACCESSIBILITY");
104
+ }
105
+ else if ([setting isEqualToString:@"account"]) {
106
+ return prefURLIfAvailable(@"App-Prefs:root=ACCOUNT_SETTINGS");
107
+ }
108
+ else if ([setting isEqualToString:@"airplane_mode"]) {
109
+ return prefURLIfAvailable(@"App-Prefs:root=AIRPLANE_MODE");
110
+ }
111
+ else if ([setting isEqualToString:@"autolock"]) {
112
+ return prefURLIfAvailable(@"App-Prefs:root=General&path=AUTOLOCK");
113
+ }
114
+ else if ([setting isEqualToString:@"battery"]) {
115
+ return prefURLIfAvailable(@"App-Prefs:root=BATTERY_USAGE");
116
+ }
117
+ else if ([setting isEqualToString:@"bluetooth"]) {
118
+ return prefURLIfAvailable(@"App-Prefs:root=Bluetooth");
119
+ }
120
+ else if ([setting isEqualToString:@"browser"]) {
121
+ return prefURLIfAvailable(@"App-Prefs:root=Safari");
122
+ }
123
+ else if ([setting isEqualToString:@"cellular"] || [setting isEqualToString:@"cellular_usage"]) {
124
+ return prefURLIfAvailable(@"App-Prefs:root=MOBILE_DATA_SETTINGS_ID");
125
+ }
126
+ else if ([setting isEqualToString:@"date"]) {
127
+ return prefURLIfAvailable(@"App-Prefs:root=General&path=DATE_AND_TIME");
128
+ }
129
+ else if ([setting isEqualToString:@"facetime"]) {
130
+ return prefURLIfAvailable(@"App-Prefs:root=FACETIME");
131
+ }
132
+ else if ([setting isEqualToString:@"keyboard"]) {
133
+ return prefURLIfAvailable(@"App-Prefs:root=General&path=Keyboard");
134
+ }
135
+ else if ([setting isEqualToString:@"language"]) {
136
+ return prefURLIfAvailable(@"App-Prefs:root=General&path=LANGUAGE_AND_REGION");
137
+ }
138
+ else if ([setting isEqualToString:@"location"]) {
139
+ return prefURLIfAvailable(@"App-Prefs:root=Privacy&path=LOCATION");
140
+ }
141
+ else if ([setting isEqualToString:@"music"]) {
142
+ return prefURLIfAvailable(@"App-Prefs:root=Music");
143
+ }
144
+ else if ([setting isEqualToString:@"network"]) {
145
+ return prefURLIfAvailable(@"App-Prefs:root=General&path=Network");
146
+ }
147
+ else if ([setting isEqualToString:@"notification_id"] || [setting isEqualToString:@"notifications"]) {
148
+ // iOS provides app-specific notification settings via the app settings page
149
+ return [NSURL URLWithString:UIApplicationOpenSettingsURLString];
150
+ }
151
+ else if ([setting isEqualToString:@"phone"]) {
152
+ return prefURLIfAvailable(@"App-Prefs:root=Phone");
153
+ }
154
+ else if ([setting isEqualToString:@"photos"]) {
155
+ return prefURLIfAvailable(@"App-Prefs:root=Photos");
156
+ }
157
+ else if ([setting isEqualToString:@"privacy"]) {
158
+ return prefURLIfAvailable(@"App-Prefs:root=Privacy");
159
+ }
160
+ else if ([setting isEqualToString:@"reset"]) {
161
+ return prefURLIfAvailable(@"App-Prefs:root=General&path=Reset");
162
+ }
163
+ else if ([setting isEqualToString:@"ringtone"]) {
164
+ return prefURLIfAvailable(@"App-Prefs:root=Sounds&path=Ringtone");
165
+ }
166
+ else if ([setting isEqualToString:@"root"]) {
167
+ return prefURLIfAvailable(@"App-Prefs:root");
168
+ }
169
+ else if ([setting isEqualToString:@"safari"]) {
170
+ return prefURLIfAvailable(@"App-Prefs:root=Safari");
171
+ }
172
+ else if ([setting isEqualToString:@"sound"]) {
173
+ return prefURLIfAvailable(@"App-Prefs:root=Sounds");
174
+ }
175
+ else if ([setting isEqualToString:@"software_update"]) {
176
+ return prefURLIfAvailable(@"App-Prefs:root=General&path=SOFTWARE_UPDATE_LINK");
177
+ }
178
+ else if ([setting isEqualToString:@"storage"]) {
179
+ return prefURLIfAvailable(@"App-Prefs:root=General&path=STORAGE");
180
+ }
181
+ else if ([setting isEqualToString:@"vpn"]) {
182
+ return prefURLIfAvailable(@"App-Prefs:root=General&path=VPN");
183
+ }
184
+ else if ([setting isEqualToString:@"wallpaper"]) {
185
+ return prefURLIfAvailable(@"App-Prefs:root=Wallpaper");
186
+ }
187
+ else if ([setting isEqualToString:@"wifi"]) {
188
+ return prefURLIfAvailable(@"App-Prefs:root=WIFI");
189
+ }
190
+ else if ([setting isEqualToString:@"store"]) {
191
+ // App Store cannot be opened to app-specific settings via App-Prefs; open app settings instead
192
+ return [NSURL URLWithString:UIApplicationOpenSettingsURLString];
193
+ }
194
+ // If nothing matches, return nil to indicate not supported
195
+
196
+ return nil;
197
+ }
198
+
199
+ @end
@@ -0,0 +1,32 @@
1
+ export interface INativeSettingsOptions {
2
+ setting: string;
3
+ /**
4
+ * On Android, open the settings screen in a new task (so it appears as a separate app in Recents)
5
+ */
6
+ newTask?: boolean;
7
+ }
8
+
9
+ export class SettingsManager {
10
+ /**
11
+ * Open device settings screen
12
+ * @param options Settings options or setting string
13
+ */
14
+ open(options: INativeSettingsOptions | string): Promise<void>;
15
+
16
+ /**
17
+ * Check if specific settings page is available
18
+ * @param setting The settings page to check
19
+ */
20
+ isAvailable(setting: string): Promise<boolean>;
21
+ }
22
+
23
+ // For global access
24
+ declare global {
25
+ const SettingsPlugin: SettingsManager;
26
+ }
27
+
28
+ // For TypeScript/Angular imports
29
+ declare module 'community-cordova-plugin-native-settings' {
30
+ export { SettingsManager, INativeSettingsOptions };
31
+ export default SettingsPlugin;
32
+ }
@@ -0,0 +1,29 @@
1
+ var exec = require('cordova/exec');
2
+
3
+ class SettingsManager {
4
+ open(options) {
5
+ return new Promise((resolve, reject) => {
6
+ const setting = typeof options === 'string' ? options : options.setting;
7
+ const newTask = typeof options === 'object' ? !!options.newTask : false;
8
+
9
+ exec(function() {
10
+ resolve();
11
+ }, function(error) {
12
+ reject(error);
13
+ }, "NativeSettings", "open", [setting, newTask]);
14
+ });
15
+ }
16
+
17
+ isAvailable(setting) {
18
+ return new Promise((resolve, reject) => {
19
+ exec(function(result) {
20
+ resolve(!!result);
21
+ }, function(error) {
22
+ reject(error);
23
+ }, "NativeSettings", "isAvailable", [setting]);
24
+ });
25
+ }
26
+ }
27
+
28
+ // Create and export a singleton instance as SettingsPlugin
29
+ module.exports = new SettingsManager();