Como abro as configurações do telefone quando um botão é clicado?

160

Estou tentando implementar um recurso em um aplicativo que mostra um alerta quando a conexão com a internet não está disponível. O alerta tem duas ações (OK e Configurações). Sempre que um usuário clicar nas configurações, desejo levá-las às configurações do telefone programaticamente.

Estou usando Swift e Xcode.

Solomon Ayoola
fonte

Respostas:

301

Usando UIApplication.openSettingsURLString

Atualização para o 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)
}
Marius Fanu
fonte
Como faço para implementar isso? @Marius Fanu
Solomon Ayoola
Estou usando o iOS8 @Marius Fanu
Solomon Ayoola
@AyoolaSolomon Eu atualizei a minha resposta para adicionar um alerta no viewDidAppearmétodo, com o Settingse Cancelbotão
Marius Fanu
2
Não, acho que não. Para acessar seu aplicativo, ele deve implementar um esquema de URL personalizado e chamar o UIApplication.sharedApplication().openURL(yourCustomURL)aplicativo atual, mas você não tem esse acesso no aplicativo Configurações
Marius Fanu
5
O @PersianBlue está correto no iOS 10.1.1, pois não inicia o aplicativo Configurações.
Michael Garito
237

⚠️ Tenha cuidado!

Esta resposta é baseada em APIs não documentadas e, recentemente (desde iOS12), a Apple está rejeitando aplicativos com essa abordagem.

Resposta original abaixo

Swift 5

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

Swift 4

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

NOTA: O método a seguir funciona para todas as versões abaixo do iOS 11; para versões superiores, o aplicativo pode ser rejeitado, pois é uma API privada

Às vezes, queremos levar um usuário para configurações diferentes das configurações de nossos aplicativos. O método a seguir ajudará você a conseguir isso:

Primeiro, configure os esquemas de URL em seu projeto. Você o encontrará em Destino -> Informações -> Esquema de URL. clique no botão + e digite prefs em esquemas de URL

insira a descrição da imagem aqui

Swift 5

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

Swift 3

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

Rápido

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

Objetivo-C

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

e a seguir estão todos os URLs disponíveis

** No IOS <12 **

  • prefs: root = Geral & caminho = Sobre
  • prefs: root = Geral & caminho = ACESSIBILIDADE
  • prefs: root = AIRPLANE_MODE
  • prefs: root = Geral & caminho = AUTOLOCK
  • prefs: root = Geral e caminho = USAGE / CELLULAR_USAGE
  • prefs: root = Brilho
  • prefs: root = Bluetooth
  • prefs: root = Geral & caminho = DATE_AND_TIME
  • prefs: root = FACETIME
  • prefs: root = Geral
  • prefs: root = Geral & caminho = Teclado
  • prefs: root = CASTLE
  • prefs: root = CASTLE & path = STORAGE_AND_BACKUP
  • prefs: root = Geral & caminho = INTERNACIONAL
  • prefs: root = LOCATION_SERVICES
  • prefs: root = ACCOUNT_SETTINGS
  • prefs: raiz = MÚSICA
  • prefs: root = MÚSICA & path = EQ
  • prefs: root = MUSIC & path = VolumeLimit
  • prefs: root = Geral & caminho = Rede
  • prefs: root = NIKE_PLUS_IPOD
  • prefs: root = NOTES
  • prefs: root = NOTIFICATIONS_ID
  • prefs: root = Telefone
  • prefs: root = Fotos
  • prefs: root = Geral & caminho = ManagedConfigurationList
  • prefs: root = Geral & caminho = Redefinir
  • prefs: root = Sons e caminho = Toque
  • prefs: root = Safari
  • prefs: root = Geral & caminho = Assistente
  • prefs: root = Sons
  • prefs: root = Geral & caminho = SOFTWARE_UPDATE_LINK
  • prefs: root = LOJA
  • prefs: root = TWITTER
  • prefs: root = FACEBOOK
  • prefs: root = Geral & caminho = USAGE prefs: root = VIDEO
  • prefs: root = Geral & caminho = Rede / VPN
  • prefs: root = Papel de parede
  • prefs: root = WIFI
  • prefs: root = INTERNET_TETHERING
  • prefs: root = Phone & path = Bloqueado
  • prefs: root = DO_NOT_DISTURB

No IOS 13

  • Preferências de aplicativos: Geral & caminho = Sobre
  • Preferências de aplicativo: AIRPLANE_MODE
  • Preferências de aplicativo: Geral & caminho = AUTOLOCK
  • Preferências de aplicativo: Bluetooth
  • Preferências de aplicativo: geral e caminho = DATE_AND_TIME
  • Preferências de aplicativo: FACETIME
  • Preferências de aplicativos: Geral
  • Preferências de aplicativo: Geral & caminho = Teclado
  • Preferências de aplicativo: CASTLE
  • Preferências de aplicativo: CASTLE & path = STORAGE_AND_BACKUP
  • Preferências de aplicativo: Geral & caminho = INTERNACIONAL
  • Preferências de aplicativo: MUSIC
  • Preferências de aplicativos: NOTAS
  • Preferências de aplicativo: NOTIFICATIONS_ID
  • Preferências de aplicativos: telefone
  • Preferências de aplicativos: fotos
  • Preferências de aplicativo: Geral & caminho = ManagedConfigurationList
  • Preferências de aplicativo: Geral & caminho = Redefinir
  • Preferências de aplicativos: sons e caminho = toque
  • Preferências de aplicativos: sons
  • Preferências de aplicativo: geral e caminho = SOFTWARE_UPDATE_LINK
  • Preferências de aplicativo: STORE
  • Preferências de aplicativo: papel de parede
  • Preferências de aplicativo: WIFI
  • Preferências de aplicativo: INTERNET_TETHERING
  • Preferências de aplicativo: DO_NOT_DISTURB

    Não testado

  • Preferências de aplicativo: TWITTER (??)

  • Preferências de aplicativo: FACEBOOK (??)
  • Preferências de aplicativo: NIKE_PLUS_IPOD (??)

Nota: A configuração de rede não será aberta em um simulador, mas o link funcionará em um dispositivo real.

vivek takrani
fonte
7
Isso não funciona no iOS 10. Executou o mesmo código no iOS 9.3. e funcionou, funcionou em iOS 10 e isso não aconteceu (independentemente de qual url é usado)
Gruntcakes
18
Para iOS 10, use em App-Prefsvez de prefscomo o esquema da cadeia de caracteres da URL. por exemploApp-Prefs:root=WIFI
Desmond DAI
8
recentemente revisou um aplicativo para lançá-lo na App Store, e a Apple o recusou devido ao uso de "prefs: root" ou "App-Prefs: root". Eu usei para abrir as configurações de wifi, quando o usuário não tem conexão com a internet.
Marcel T
21
Desde o lançamento do iOS 12 em breve, a Apple rejeitou o aplicativo que inclui esse pref. Por favor, esteja ciente disso. Até meu aplicativo também foi rejeitado #
Thiha Aung
8
NÃO use App-Prefsou prefs:rootcomo essas são APIs privadas e, a menos que você tenha muita sorte, seu aplicativo será rejeitado.
Tejas K
45

No iOS 8+, você pode fazer o seguinte:

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

Swift 4

    let settingsUrl = URL(string: UIApplicationOpenSettingsURLString)!
    UIApplication.shared.open(settingsUrl)
cristão
fonte
16
Isso leva você às configurações específicas do aplicativo, como as levo para a página de configurações gerais ou melhor ainda para a seção de saúde?
Ace Green
2
Swift 3 -UIApplication.shared.openURL(URL(string: UIApplicationOpenSettingsURLString)!)
Aviv Ben Shabat
@AceGreen você chegou à seção de saúde?
Saad
Como você abre apenas o aplicativo Configurações? A "página inicial" dele
Daniel Springer
sem "!" sinalURL(string: UIApplication.openSettingsURLString).map { UIApplication.shared.open($0, options: [:], completionHandler: nil) }
ober
21

Usando a dica de @ vivek, desenvolvo uma classe utils baseada no Swift 3 , espero que você goste!

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)
        }
    }

}

Isso é muito útil, pois as APIs mudarão com certeza e você pode refatorar uma vez e muito rápido!

Luca Davanzo
fonte
5
Isso passaria pela revisão da apple?
L_Sonic
Vou adicionar mais uma coisa para torná-la um pouco melhor. Na enumeração, você pode criar uma variável do tipo String com o nome urlString. Em seguida, retorne "App-Prefs: root =" = self.rawValue. Basicamente, isso removerá a necessidade do appPath e do let private estático. Felicidades.
MN1
Configurações de notificação não é de abertura no iOS 11.
Metin Atalay
2
isso não funcionará porque recebemos esta mensagem do aplicativo: "Seu aplicativo usa o esquema de URL não público" prefs: root = ", que é uma entidade privada. O uso de APIs não públicas não é permitido na App Store porque pode levar a uma má experiência do usuário caso essas APIs sejam alteradas. Continuar usando ou ocultando APIs não públicas em envios futuros deste aplicativo pode resultar no encerramento da sua conta Apple Developer, bem como na remoção de todos os aplicativos associados do aplicativo Loja."
CodeOverRide
1
@L_Sonic não, não vai passar pela avaliação, e se isso acontecer, ele poderia se aleatoriamente sinalizado em quaisquer futuras atualizações você empurra
RP Carson
16

A primeira resposta dos esquemas de URL específicos do aplicativo funcionou para mim no iOS 10.3.

if let appSettings = URL(string: UIApplicationOpenSettingsURLString + Bundle.main.bundleIdentifier!) {
    if UIApplication.shared.canOpenURL(appSettings) {
      UIApplication.shared.open(appSettings)
    }
  }
inc_london
fonte
O que isso deve abrir?
Daniel Springer
12

App-Prefs:root=Privacy&path=LOCATIONtrabalhou para mim para obter as configurações gerais de localização. Nota: só funciona em um dispositivo.

Joe Susnick
fonte
12
Esta é rejeitada
Daniel Springer
7

no ios10 / Xcode 8 no simulador:

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

trabalho

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

não.

ingconti
fonte
O NSprefixo foi removido no iOS 10?
JC Rocamonde
2
Isso só vai funcionar se a sua aplicação tem de arquivo .bundle (suas preferências de aplicativos)
Sophy Swicz
@Sophy Swicz Como posso adicionar o arquivo .bundle?
Desenvolvedor
1
@Developer github.com/phynet/SettingBundleiOSProject também, as definições da aplicação são todos os serviços que a sua aplicação permite o uso e são mostrados em Geral -> configurações do seu aplicativo
Sophy Swicz
7

Eu vi essa linha de código

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

não está funcionando, não funcionou para mim no ios10 / Xcode 8, apenas uma pequena diferença de código, substitua-a por

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

Swift3

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

Substituir com

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

Espero que ajude. Felicidades.

niravdesai21
fonte
1
Causas: App rejeitado
ergunkocak
7

aviso: os esquemas de URL prefs:rootou App-Prefs:rootsão considerados API privada. A Apple pode rejeitar seu aplicativo, se você os usar, eis o que você pode obter ao enviar seu aplicativo:

Seu aplicativo usa o esquema de URL não público "prefs: root =", que é uma entidade privada. O uso de APIs não públicas não é permitido na App Store, pois pode levar a uma má experiência do usuário, caso essas APIs sejam alteradas. Continuar usando ou ocultando APIs não públicas em envios futuros deste aplicativo pode resultar no encerramento da sua conta de desenvolvedor da Apple e na remoção de todos os aplicativos associados da App Store.

Próximos passos

Para resolver esse problema, revise seu aplicativo para fornecer a funcionalidade associada usando APIs públicas ou remova a funcionalidade usando o esquema de URL "prefs: root" ou "App-Prefs: root".

Se não houver alternativas para fornecer a funcionalidade que seu aplicativo exige, você poderá registrar uma solicitação de aprimoramento.

ofer
fonte
Não há maneira suportada de abrir Configurações na 'página' de Wi-Fi / Idioma / Local. O fato de que isso funcionou em iOS 9 é um bug que foi corrigido no iOS 10. Para mais informações consulte forums.developer.apple.com/message/186656#186656
Mohit Kumar
6

Swift 4.2, iOS 12

O open(url:options:completionHandler:)método foi atualizado para incluir um dicionário de opções não nulo, que, a partir desta postagem, contém apenas uma opção possível do tipo UIApplication.OpenExternalURLOptionsKey(no exemplo).

@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)

}

A criação explícita de um URL, como com "App-Prefs", AFAIK, recebeu alguns aplicativos rejeitados da loja.

bsod
fonte
Confirmo que o aplicativo estava bem com "App-Prefs" antes, mas após o Evento Especial da Apple, minha atualização foi rejeitada, voltando a UIApplicationOpenSettingsURLString.
Vitalii 13/09/18
5

Adicionando a @Luca Davanzo

iOS 11, algumas configurações de permissões foram movidas para o caminho do aplicativo:

Suporte para iOS 11

 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)
    }
}
Tal Zion
fonte
2
isso pode passar pela Apple Review? Quero dizer, isso levará à rejeição de aplicativos?
Aakash Dave
4
quando executo esse código, apenas me leva à página de configurações. Não é a guia de configurações específicas.
Aakash Dave
2

SWIFT 4

Isso pode levar as configurações específicas do seu aplicativo, se é isso que você está procurando.

UIApplication.shared.openURL(URL(string: UIApplicationOpenSettingsURLString)!)
BennyTheNerd
fonte
obrigado ... Eu tenho esse trabalho ... mas quero alterar as configurações de aplicativos que são de outros desenvolvedores. Por exemplo, pressione um botão e altere as configurações de notificação por push do facebook para que elas não sejam enviadas durante uma reunião. Eu prevejo que poderia haver soluções MDM ... ou não.
22718 IrishGringo
@IrishGringo a única maneira de alterar as configurações do Facebook aplicativo é para o usuário para abrir as configurações do aplicativo do Facebook-se ao navegar através das configurações gerais >> Notificações >> Facebook
BennyTheNerd
0

Como acima @niravdesai disse App-prefs. Descobri que App-Prefs:funciona para dispositivos iOS 9, 10 e 11. testados. onde prefs:só funciona no iOS 9.

Alix
fonte