How do I open phone settings when a button is clicked?
Asked Answered
K

14

218

I am trying to implement a feature in an App that shows an alert when the internet connection is not available. The alert has two actions (OK and Settings), whenever a user clicks on settings, I want to take them to the phone settings programmatically.

I am using Swift and Xcode.

Kreg answered 26/1, 2015 at 14:52 Comment(0)
R
405

Using UIApplication.openSettingsURLString

Update for Swift 5.1

 override func viewDidAppear(_ animated: Bool) {
    let alertController = UIAlertController (title: "Title", message: "Go to Settings?", preferredStyle: .alert)

    let settingsAction = UIAlertAction(title: "Settings", style: .default) { (_) -> Void in

        guard let settingsUrl = URL(string: UIApplication.openSettingsURLString) else {
            return
        }

        if UIApplication.shared.canOpenURL(settingsUrl) {
            UIApplication.shared.open(settingsUrl, completionHandler: { (success) in
                print("Settings opened: \(success)") // Prints true
            })
        }
    }
    alertController.addAction(settingsAction)
    let cancelAction = UIAlertAction(title: "Cancel", style: .default, handler: nil)
    alertController.addAction(cancelAction)

    present(alertController, animated: true, completion: nil)
}

Swift 4.2

override func viewDidAppear(_ animated: Bool) {
    let alertController = UIAlertController (title: "Title", message: "Go to Settings?", preferredStyle: .alert)

    let settingsAction = UIAlertAction(title: "Settings", style: .default) { (_) -> Void in

        guard let settingsUrl = URL(string: UIApplicationOpenSettingsURLString) else {
            return
        }

        if UIApplication.shared.canOpenURL(settingsUrl) {
            UIApplication.shared.open(settingsUrl, completionHandler: { (success) in
                print("Settings opened: \(success)") // Prints true
            })
        }
    }
    alertController.addAction(settingsAction)
    let cancelAction = UIAlertAction(title: "Cancel", style: .default, handler: nil)
    alertController.addAction(cancelAction)

    present(alertController, animated: true, completion: nil)
}
Refractive answered 26/1, 2015 at 14:57 Comment(10)
How do i implement that ? @Marius FanuKreg
it using iOS8 @Marius FanuKreg
@AyoolaSolomon I've updated my answer to add an alert on viewDidAppear method, with the Settings and Cancel buttonRefractive
Is there a way i can navigate back to the app programmaticallyKreg
Nope, I don't think so. In order to go to your app, your application should implement a custom URL scheme, and call the UIApplication.sharedApplication().openURL(yourCustomURL) from the current app, but you don't have that access from the Settings appRefractive
@MariusFanu This solution is not working for iOS 10 . I am working on Xcode 8, swift 3. Any alternate solution please?Selfmoving
@PersianBlue is correct in iOS 10.1.1 this fails to launch the Settings app.Incentive
You may want to update the settingsURL string to UIApplication.openSettingsURLStringGaelic
Is this apple allowed when we use UIApplication.openSettingsURLString, because apple rejected when we open the settings app some times.Blindstory
This opens the app specific page in the settings application, any idea how to open settings on the main page?Outlet
G
295

⚠️ Be careful!

This answer is based on undocumented APIs and recently (since iOS12) Apple is rejecting apps with this approach.

Original answer below

Swift 5

UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!, options: [:], completionHandler: nil)

Swift 4

UIApplication.shared.open(URL(string: UIApplicationOpenSettingsURLString)!, options: [:], completionHandler: nil)

NOTE: The following method works for all the versions below iOS 11, for higher versions the app might get rejected since it's a private API

Sometimes we want to take a user to settings other than our app settings. The following method will help you achieve that:

First, configure the URL Schemes in your project. You will find it in Target -> Info -> URL Scheme. click on + button and type prefs in URL Schemes

enter image description here

Swift 5

UIApplication.shared.open(URL(string: "App-prefs:Bluetooth")!)

Swift 3

UIApplication.shared.open(URL(string:"App-Prefs:root=General")!, options: [:], completionHandler: nil)

Swift

UIApplication.sharedApplication().openURL(NSURL(string:"prefs:root=General")!)

Objective-C

[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=General"]];

and following are all the available URLs

**On IOS < 12 **

  • prefs:root=General&path=About
  • prefs:root=General&path=ACCESSIBILITY
  • prefs:root=AIRPLANE_MODE
  • prefs:root=General&path=AUTOLOCK
  • prefs:root=General&path=USAGE/CELLULAR_USAGE
  • prefs:root=Brightness
  • prefs:root=Bluetooth
  • prefs:root=General&path=DATE_AND_TIME
  • prefs:root=FACETIME
  • prefs:root=General
  • prefs:root=General&path=Keyboard
  • prefs:root=CASTLE
  • prefs:root=CASTLE&path=STORAGE_AND_BACKUP
  • prefs:root=General&path=INTERNATIONAL
  • prefs:root=LOCATION_SERVICES
  • prefs:root=ACCOUNT_SETTINGS
  • prefs:root=MUSIC
  • prefs:root=MUSIC&path=EQ
  • prefs:root=MUSIC&path=VolumeLimit
  • prefs:root=General&path=Network
  • prefs:root=NIKE_PLUS_IPOD
  • prefs:root=NOTES
  • prefs:root=NOTIFICATIONS_ID
  • prefs:root=Phone
  • prefs:root=Photos
  • prefs:root=General&path=ManagedConfigurationList
  • prefs:root=General&path=Reset
  • prefs:root=Sounds&path=Ringtone
  • prefs:root=Safari
  • prefs:root=General&path=Assistant
  • prefs:root=Sounds
  • prefs:root=General&path=SOFTWARE_UPDATE_LINK
  • prefs:root=STORE
  • prefs:root=TWITTER
  • prefs:root=FACEBOOK
  • prefs:root=General&path=USAGE prefs:root=VIDEO
  • prefs:root=General&path=Network/VPN
  • prefs:root=Wallpaper
  • prefs:root=WIFI
  • prefs:root=INTERNET_TETHERING
  • prefs:root=Phone&path=Blocked
  • prefs:root=DO_NOT_DISTURB

On IOS 13

  • App-prefs:General&path=About
  • App-prefs:AIRPLANE_MODE
  • App-prefs:General&path=AUTOLOCK
  • App-prefs:Bluetooth
  • App-prefs:General&path=DATE_AND_TIME
  • App-prefs:FACETIME
  • App-prefs:General
  • App-prefs:General&path=Keyboard
  • App-prefs:CASTLE
  • App-prefs:CASTLE&path=STORAGE_AND_BACKUP
  • App-prefs:General&path=INTERNATIONAL
  • App-prefs:MUSIC
  • App-prefs:NOTES
  • App-prefs:NOTIFICATIONS_ID
  • App-prefs:Phone
  • App-prefs:Photos
  • App-prefs:General&path=ManagedConfigurationList
  • App-prefs:General&path=Reset
  • App-prefs:Sounds&path=Ringtone
  • App-prefs:Sounds
  • App-prefs:General&path=SOFTWARE_UPDATE_LINK
  • App-prefs:STORE
  • App-prefs:Wallpaper
  • App-prefs:WIFI
  • App-prefs:INTERNET_TETHERING
  • App-prefs:DO_NOT_DISTURB

Not tested

  • App-prefs:TWITTER (??)
  • App-prefs:FACEBOOK (??)
  • App-prefs:NIKE_PLUS_IPOD (??)

Tested IOS > 12

  • App-prefs:HEALTH&path=SOURCES

Note: Network setting will not be opened in a simulator, but the link will work on a real device.

Granjon answered 1/12, 2015 at 15:52 Comment(44)
And just opening the settings without a specific page: "prefs:root"Entertainment
Interesting, I just tested it on ios 7 & 9. It works!Typhoon
Url schema for Bluetooth settings is now "prefs:root=Bluetooth"Prepared
We were just rejected for using a private api.Subjunction
@jestro, did Apple rejected your app even after adding "prefs" in Xcode's URL Schemas? Because i see lot of apps in app store, which takes player to any settings screen.Menzies
Anyone knows the url for the blocked callers? (settings -> Phone -> Calls -> Blocked) and for do not disturb mode (settings -> Do Not Disturb) ?Goodill
How about opening Mail settings? it seems there's no url option for mail settings.Putamen
Sorry @Hokage there is not URL available to open Mail settings.Granjon
@Karl-JohnChow You can use "prefs:root=Phone&path=Blocked" for blocked calls and "prefs:root=DO_NOT_DISTURB" for Do Not DisturbGranjon
@vivektakrani actually there is: #9404607Putamen
Yeah just checked and it's working...and btw it's already there in the list above :DGranjon
This doesn't work with iOS 10. Ran the same code on iOS 9.3. and it worked, ran on iOS 10 and it didn't (regardless of which url is used)Silsbye
Any solution for iOS 10?Mow
prefs:root=FACEBOOK not working in iOS 10.1 and Xcode 8.1 but working fine in iOS 9.3.5 does any have solution?Clime
Worked well for me - iOS10, Note:- Don't change prefs with anything else.Laquitalar
prefs:root=FACEBOOK but not works could assist me here? @ZaidPathanClime
@SaumilShah Have you added prefs In URL schemes?Laquitalar
Yes I used " UIApplication.shared.openURL(URL(string: "prefs:root=FACEBOOK")!)" code and also added Xcode Target -> Info -> URL Types -> URL Schemes "prefs" strings.Clime
How did you find out the path names @vivektakrani?Decker
How to just go to the root of the settings?Plowboy
@prettyitgirl.com try this UIApplication.shared.openURL(URL(string:"prefs:root")!)Granjon
Thanks, I just realized that as soon as I posted my comment. :) Also, Apps-Pref works on iOS 10.Plowboy
For iOS 10, use App-Prefs instead of prefs as the scheme of the URL string. e.g. App-Prefs:root=WIFIGyroscope
App-Prefs works for iOS 10, but is it legal. Apple might reject the application as it is not documented anywhere.Jeanene
For me it only works inside the simulator.. not on device. Trying to open the Safari PrefsPoplin
Is it possible to open settings for custom app, like: prefs:root=myApp ?Sancha
IS POSSIBLE TO ACCESS: Storage & iCloud Usage -> Manage StorageRodrickrodrigez
Also use UPPER CASE if this keys don't work. For example WALLPAPER instead of Wallpaper.Clinkerbuilt
@Sancha Yes you can by replacing this "App-Prefs:root=General" with UIApplicationOpenSettingsURLStringUmmersen
In ios11 it Opens Setting default page.Petrinapetrine
recently gave an app into review to release it in the App Store, and Apple declined it because of the usage of "prefs:root" or "App-Prefs:root". I used it to open the wifi settings, when the user has no internet connection.Shinbone
Since iOS 12 coming out soon, Apple rejecting app which include such pref. Please be-aware of it. Even my app got rejected tooQuartz
DO NOT use App-Prefs or prefs:root as these are private API's, and unless you are very lucky your app will get rejected.Erlineerlinna
my app was rejected for an update by apple for using prefs:root=LOCATION_SERVICESZanezaneski
Yes ..exactly these are the private apis and app will get reject by apple.Leporide
So what is everyone doing to fix this the right way?Wivinah
Be careful it is a private API, you'll be rejected at Apple Store submissionConnote
What is the alternative for iOS 12?Yuan
@ThihaAung so any better solution?Luella
@EICaptainv2.0, now all App-Prefs and pref are non-public url now. The best way to handle was, show the popup, inside show navigation steps [GIF or Images Slides] then when user click "ok", leads to setting using this UIApplicationOpenSettingsURLString Quartz
Since Facebook SDK used URL Types I can't open Settings page. The code that you gave opens only Settings>My Application Name. Is there a way to fix it.Rigger
hi, is possibile to open iphone storage page?Gallia
for open storage page?Gallia
"App-prefs:MESSAGES" works for me to open Messages Setting from App.Arcadia
D
73

SWIFT 5

if let settingsUrl = URL(string: UIApplication.openSettingsURLString) {

   UIApplication.shared.open(settingsUrl)

 }

In iOS 8+ you can do the following:

 func buttonClicked(sender:UIButton)
    {
        UIApplication.sharedApplication().openURL(NSURL(string: UIApplicationOpenSettingsURLString))
    }

Swift 4

    let settingsUrl = URL(string: UIApplicationOpenSettingsURLString)!
    UIApplication.shared.open(settingsUrl)
Daggna answered 26/1, 2015 at 14:59 Comment(6)
This takes you to the app specific settings, how do I take them to the general settings page or even better to the health section?Dermatosis
Swift 3 - UIApplication.shared.openURL(URL(string: UIApplicationOpenSettingsURLString)!)Understate
@AceGreen did you make it to the health section?Superordinate
How do you open just the Settings app? The "Home page" of itMurphy
without "!" sign URL(string: UIApplication.openSettingsURLString).map { UIApplication.shared.open($0, options: [:], completionHandler: nil) }Brochette
Is this apple allowed when we use UIApplication.openSettingsURLString, because apple rejected when we open the settings app some times.Blindstory
H
24

Using @vivek's hint I develop an utils class based on Swift 3, hope you appreciate!

import Foundation
import UIKit

public enum PreferenceType: String {

    case about = "General&path=About"
    case accessibility = "General&path=ACCESSIBILITY"
    case airplaneMode = "AIRPLANE_MODE"
    case autolock = "General&path=AUTOLOCK"
    case cellularUsage = "General&path=USAGE/CELLULAR_USAGE"
    case brightness = "Brightness"
    case bluetooth = "Bluetooth"
    case dateAndTime = "General&path=DATE_AND_TIME"
    case facetime = "FACETIME"
    case general = "General"
    case keyboard = "General&path=Keyboard"
    case castle = "CASTLE"
    case storageAndBackup = "CASTLE&path=STORAGE_AND_BACKUP"
    case international = "General&path=INTERNATIONAL"
    case locationServices = "LOCATION_SERVICES"
    case accountSettings = "ACCOUNT_SETTINGS"
    case music = "MUSIC"
    case equalizer = "MUSIC&path=EQ"
    case volumeLimit = "MUSIC&path=VolumeLimit"
    case network = "General&path=Network"
    case nikePlusIPod = "NIKE_PLUS_IPOD"
    case notes = "NOTES"
    case notificationsId = "NOTIFICATIONS_ID"
    case phone = "Phone"
    case photos = "Photos"
    case managedConfigurationList = "General&path=ManagedConfigurationList"
    case reset = "General&path=Reset"
    case ringtone = "Sounds&path=Ringtone"
    case safari = "Safari"
    case assistant = "General&path=Assistant"
    case sounds = "Sounds"
    case softwareUpdateLink = "General&path=SOFTWARE_UPDATE_LINK"
    case store = "STORE"
    case twitter = "TWITTER"
    case facebook = "FACEBOOK"
    case usage = "General&path=USAGE"
    case video = "VIDEO"
    case vpn = "General&path=Network/VPN"
    case wallpaper = "Wallpaper"
    case wifi = "WIFI"
    case tethering = "INTERNET_TETHERING"
    case blocked = "Phone&path=Blocked"
    case doNotDisturb = "DO_NOT_DISTURB"

}

enum PreferenceExplorerError: Error {
    case notFound(String)
}

open class PreferencesExplorer {

    // MARK: - Class properties -

    static private let preferencePath = "App-Prefs:root"

    // MARK: - Class methods -

    static func open(_ preferenceType: PreferenceType) throws {
        let appPath = "\(PreferencesExplorer.preferencePath)=\(preferenceType.rawValue)"
        if let url = URL(string: appPath) {
            if #available(iOS 10.0, *) {
                UIApplication.shared.open(url, options: [:], completionHandler: nil)
            } else {
               UIApplication.shared.openURL(url)
            }
        } else {
            throw PreferenceExplorerError.notFound(appPath)
        }
    }

}

This is very helpful since that API's will change for sure and you can refactor once and very fast!

Hystero answered 8/6, 2017 at 15:37 Comment(6)
Would this go through apple review?Omidyar
I am going to add one more thing to make it slightly better. In the enum, you can make a variable of type String with the name urlString. Then return "App-Prefs:root=" = self.rawValue. This will basically remove the need for appPath and the static private let. Cheers.Totally
Notification settings is not opening on iOS 11.Printable
Any answer for notification settings on iOS 11?Empire
this will not work as we got this message from app: "Your app uses the "prefs:root=" non-public URL scheme, which is a private entity. The use of non-public APIs is not permitted on the App Store because it can lead to a poor user experience should these APIs change. Continuing to use or conceal non-public APIs in future submissions of this app may result in the termination of your Apple Developer account, as well as removal of all associated apps from the App Store."Antalya
@Omidyar no it will not pass review, and if it does, it could get randomly flagged in any future updates you pushPerfoliate
C
21

The first response from App-Specific URL Schemes worked for me on iOS 10.3.

if let appSettings = URL(string: UIApplicationOpenSettingsURLString + Bundle.main.bundleIdentifier!) {
    if UIApplication.shared.canOpenURL(appSettings) {
      UIApplication.shared.open(appSettings)
    }
  }
Creodont answered 24/4, 2017 at 9:27 Comment(1)
What's this supposed to open?Murphy
E
13

App-Prefs:root=Privacy&path=LOCATION worked for me for getting to general location settings. Note: only works on a device.

Etymology answered 22/6, 2017 at 16:36 Comment(1)
This gets rejectedMurphy
J
11

iOS 12+

The open(url:options:completionHandler:) method has been updated to include a non-nil options dictionary, which as of this post only contains one possible option of type UIApplication.OpenExternalURLOptionsKey (in the example).

@objc func openAppSpecificSettings() {
    guard let url = URL(string: UIApplication.openSettingsURLString),
        UIApplication.shared.canOpenURL(url) else {
            return
    }
    let optionsKeyDictionary = [UIApplication.OpenExternalURLOptionsKey(rawValue: "universalLinksOnly"): NSNumber(value: true)]
    
    UIApplication.shared.open(url, options: optionsKeyDictionary, completionHandler: nil)
}

Explicitly constructing a URL, such as with "App-Prefs", has gotten some apps rejected from the store.

Jacynth answered 30/8, 2018 at 18:28 Comment(2)
I confirm this, app was fine with "App-Prefs" before, but after Apple's Special Event my update got rejection, falling back to UIApplicationOpenSettingsURLString.Whacking
Is this apple allowed when we use UIApplication.openSettingsURLString, because apple rejected when we open the settings app some times.Blindstory
N
8

word of warning: the prefs:root or App-Prefs:root URL schemes are considered private API. Apple may reject you app if you use those, here is what you may get when submitting your app:

Your app uses the "prefs:root=" non-public URL scheme, which is a private entity. The use of non-public APIs is not permitted on the App Store because it can lead to a poor user experience should these APIs change. Continuing to use or conceal non-public APIs in future submissions of this app may result in the termination of your Apple Developer account, as well as removal of all associated apps from the App Store.

Next Steps

To resolve this issue, please revise your app to provide the associated functionality using public APIs or remove the functionality using the "prefs:root" or "App-Prefs:root" URL scheme.

If there are no alternatives for providing the functionality your app requires, you can file an enhancement request.

Nakamura answered 17/8, 2018 at 11:41 Comment(1)
There’s no supported way to open Settings to the Wi-Fi/Language/Location ‘page’. The fact that this worked in iOS 9 is a bug that’s been fixed in iOS 10. For more info please refer forums.developer.apple.com/message/186656#186656Frosting
E
7

in ios10/ Xcode 8 in simulator:

UIApplication.shared.openURL(URL(string:UIApplicationOpenSettingsURLString)!)

works

UIApplication.shared.openURL(URL(string:"prefs:root=General")!)

does not.

Earhart answered 18/8, 2016 at 18:22 Comment(4)
Has the NS prefix been removed in iOS 10?Recondite
This will only work if your app have .bundle file (your app preferences)Gemini
@Sophy Swicz HOw can I add .bundle file?Andromeda
@Andromeda github.com/phynet/SettingBundleiOSProject also, your app settings are all the services that your app allows to use and are shown in General -> settings of your appGemini
F
7

I have seen this line of code

UIApplication.sharedApplication() .openURL(NSURL(string:"prefs:root=General")!)

is not working, it didn't work for me in ios10/ Xcode 8, just a small code difference, please replace this with

UIApplication.sharedApplication().openURL(NSURL(string:"App-Prefs:root=General")!)

Swift3

UIApplication.shared.openURL(URL(string:"prefs:root=General")!)

Replace with

UIApplication.shared.openURL(URL(string:"App-Prefs:root=General")!)

Hope it helps. Cheers.

Falgout answered 14/2, 2017 at 8:38 Comment(1)
Causes: App rejectedAmbiversion
S
5

Adding to @Luca Davanzo

iOS 11, some permissions settings have moved to the app path:

iOS 11 Support

 static func open(_ preferenceType: PreferenceType) throws {
    var preferencePath: String
    if #available(iOS 11.0, *), preferenceType == .video || preferenceType == .locationServices || preferenceType == .photos {
        preferencePath = UIApplicationOpenSettingsURLString
    } else {
        preferencePath = "\(PreferencesExplorer.preferencePath)=\(preferenceType.rawValue)"
    }

    if let url = URL(string: preferencePath) {
        if #available(iOS 10.0, *) {
            UIApplication.shared.open(url, options: [:], completionHandler: nil)
        } else {
            UIApplication.shared.openURL(url)
        }
    } else {
        throw PreferenceExplorerError.notFound(preferencePath)
    }
}
Sexagenarian answered 26/9, 2017 at 7:39 Comment(2)
can this go through Apple Review? I mean, will this lead to app rejection?Vera
when I run this code, I just takes me to the settings page. Not the specific settings tab in it.Vera
L
3

SWIFT 4

This could take your app's specific settings, if that's what you're looking for.

UIApplication.shared.openURL(URL(string: UIApplicationOpenSettingsURLString)!)
Lacrosse answered 17/5, 2017 at 18:37 Comment(2)
thanks... I have that working... but I want to change settings on apps that are by other developers. For example, press a button and change the Push notification settings of facebook so they do not message during a meeting. I predict there could be an MDM solutions... or not.Commutable
@Commutable the only way to change the settings of the Facebook app is for the user to open the settings of the Facebook app themselves by navigating via the General Settings >> Notifications >> FacebookLacrosse
M
3

UIApplication.open(_:options:completionHandler:) must be used from main thread only

Solution:

if let appSettings = URL(string: UIApplication.openSettingsURLString + Bundle.main.bundleIdentifier!) {
  if UIApplication.shared.canOpenURL(appSettings) {
    DispatchQueue.main.async {
        UIApplication.shared.open(appSettings)
    }
  }
}
Mosira answered 15/9, 2022 at 18:32 Comment(0)
B
0

As above @niravdesai said App-prefs. I found that App-Prefs: works for both iOS 9, 10 and 11. devices tested. where as prefs: only works on iOS 9.

Barbellate answered 2/3, 2017 at 16:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.