É possível saber se o aplicativo foi iniciado / aberto a partir de uma notificação por push?
Eu acho que o evento de lançamento pode ser pego aqui:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if (launchOptions != nil) {
// Launched from push notification
NSDictionary *notification = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
}
}
No entanto, como posso detectar que ele foi aberto a partir de uma notificação por push quando o aplicativo estava em segundo plano?
Respostas:
Veja este código:
igual a
fonte
tarde, mas talvez útil
Quando o aplicativo não está sendo executado
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
é chamado ..
onde você precisa verificar a notificação por push
fonte
O problema que tivemos foi ao atualizar corretamente a exibição após o lançamento do aplicativo. Existem sequências complicadas de métodos de ciclo de vida aqui que ficam confusas.
Métodos do ciclo de vida
Nosso teste para iOS 10 revelou as seguintes sequências de métodos de ciclo de vida para os vários casos:
O problema
Ok, agora precisamos:
O mais complicado é que a atualização da exibição deve ocorrer quando o aplicativo realmente se torna ativo, que é o mesmo método de ciclo de vida em todos os casos.
Esboço da nossa solução
Aqui estão os principais componentes da nossa solução:
notificationUserInfo
variável de instância no AppDelegate.notificationUserInfo = nil
em ambosapplicationWillEnterForeground
edidFinishLaunchingWithOptions
.notificationUserInfo = userInfo
emdidReceiveRemoteNotification:inactive
applicationDidBecomeActive
sempre chamar um método personalizadoopenViewFromNotification
e passarself.notificationUserInfo
. Seself.notificationUserInfo
for nulo, retorne mais cedo; caso contrário, abra a exibição com base no estado de notificação encontrado emself.notificationUserInfo
.Explicação
Ao abrir a partir de um push
didFinishLaunchingWithOptions
ouapplicationWillEnterForeground
sempre é chamado imediatamente antesdidReceiveRemoteNotification:inactive
, primeiro redefinimos o notificationUserInfo nesses métodos para que não haja estado obsoleto. Então, sedidReceiveRemoteNotification:inactive
é chamado, sabemos que estamos abrindo a partir de um push, então definimos oself.notificationUserInfo
que é captado porapplicationDidBecomeActive
para encaminhar o usuário para a visualização correta.Há um caso final: o usuário tem o aplicativo aberto no alternador de aplicativos (ou seja, tocando duas vezes no botão de início enquanto o aplicativo está em primeiro plano) e recebe uma notificação por push. Apenas neste caso
didReceiveRemoteNotification:inactive
é chamado e nem WillEnterForeground nem didFinishLaunching são chamados, portanto, você precisa de algum estado especial para lidar com esse caso.Espero que isto ajude.
fonte
receive
métodos quando o estado do aplicativo estiver ativo ou o aplicativo estiver sendo retomado. Isso pode causar problemas com a alteração de VCs quando o aplicativo ainda está inativo. Sua solução parece ótima, até que a Apple altere o ciclo de vida novamente.applicationWillResignActive
é chamado e depois oapplicationDidBecomeActive
. Portanto, após oapplicationWillResignActive
chamado, não salve a notificação recebida até que umapplicationDidEnterBackground
ouapplicationDidBecomeActive
seja chamado.Esta é uma publicação bem usada ... mas ainda falta uma solução real para o problema (como é apontado nos vários comentários).
O motivo pode ser visto no fluxo de chamadas quando uma notificação chega,
application:didReceiveRemoteNotification...
é chamado quando a notificação é recebida E novamente quando a notificação é tocada pelo usuário. Por causa disso, você não pode dizer apenas olhando se
UIApplicationState
o usuário tocou nele.Além disso, você não precisa mais lidar com a situação de 'partida a frio' do aplicativo,
application:didFinishLaunchingWithOptions...
comoapplication:didReceiveRemoteNotification...
é chamado novamente após o lançamento no iOS 9+ (talvez 8 também).Então, como você pode saber se o usuário tocou na cadeia de eventos? Minha solução é marcar o horário em que o aplicativo começa a sair do segundo plano ou iniciar a frio e verificar o horário
application:didReceiveRemoteNotification...
. Se for menor que 0,1s, você pode ter certeza de que o toque acionou a inicialização.Swift 2.x
Swift 3
Eu testei isso nos dois casos (aplicativo em segundo plano, aplicativo não em execução) no iOS 9 ou superior e funciona como um encanto. 0.1s também é bastante conservador, o valor real é ~ 0.002s, então 0.01 também é bom.
fonte
UNNotificationCenter
API, especificamente os métodos UNNotificationCenterDelegate. Essas API chamam ouserNotificationCenter(UNUserNotificationCenter, didReceive: UNNotificationResponse, withCompletionHandler: @escaping () -> Void)
método func apenas quando o usuário realmente toca na notificação.applicationWillEnterForeground
chamadas, como resultado, a solução falha ao detectar a torneira.UNUserNotificationCenter.current().delegate
emapplication:didFinishLaunchingWithOptions
, o aplicativo chamauserNotificationCenter(didReceive response)
após a torneira no caso que você descreveuQuando o aplicativo é encerrado e o usuário toca na notificação por push
Quando o aplicativo está em segundo plano e o usuário toca na notificação por push
Dependendo do seu aplicativo, ele também pode enviar push silencioso com o
content-available
interioraps
, então esteja ciente disso também :) Consulte https://stackoverflow.com/a/33778990/1418457fonte
Swift 2.0 para o estado 'Não em execução' (notificação local e remota)
fonte
No
application:didReceiveRemoteNotification:
cheque se você recebeu a notificação quando o aplicativo está em primeiro ou segundo plano.Se foi recebido em segundo plano, inicie o aplicativo a partir da notificação.
fonte
Para rápida:
fonte
Sim, você pode detectar por esse método no appDelegate :
Para Notificação local:
fonte
se alguém quiser a resposta rapidamente 3
fonte
Publicando isso para usuários do Xamarin.
A chave para detectar se o aplicativo foi iniciado por meio de uma notificação por push é o
AppDelegate.FinishedLaunching(UIApplication app, NSDictionary options)
método e o dicionário de opções que é passado.O dicionário opções terão esta chave nele se é uma notificação local:
UIApplication.LaunchOptionsLocalNotificationKey
.Se for uma notificação remota, será
UIApplication.LaunchOptionsRemoteNotificationKey
.Quando a chave é
LaunchOptionsLocalNotificationKey
, o objeto é do tipoUILocalNotification
. Você pode examinar a notificação e determinar qual é a notificação específica.Dica profissional:
UILocalNotification
não possui um identificador, da mesma formaUNNotificationRequest
. Coloque uma chave de dicionário na UserInfo contendo um requestId para que, ao testar oUILocalNotification
, você tenha um requestId específico disponível para basear alguma lógica.Eu descobri que, mesmo em dispositivos iOS 10+ que, ao criar notificações de localizações usando o
UNUserNotificationCenter
'sAddNotificationRequest
&UNMutableNotificationContent
, que quando o aplicativo não está sendo executado (eu o matei)), é iniciado tocando na notificação no centro de notificações, que o dicionário ainda contém oUILocalNotificaiton
objetoIsso significa que meu código que verifica o lançamento baseado em notificação funcionará em dispositivos iOS8 e iOS 10+
fonte
Diretamente da documentação para
Se o aplicativo estiver em execução e receber uma notificação remota, o aplicativo chamará esse método para processar a notificação.
Sua implementação desse método deve usar a notificação para executar um curso de ação apropriado.
E um pouco depois
Se o aplicativo não estiver em execução quando uma notificação por push chegar, o método iniciará o aplicativo e fornecerá as informações apropriadas no dicionário de opções de inicialização.
O aplicativo não chama esse método para lidar com essa notificação por push.
Em vez disso, sua implementação do
ou
O método precisa obter os dados da carga útil da notificação por push e responder adequadamente.
fonte
Começarei com um gráfico de estados que criei para meu próprio uso para visualizá-lo com mais precisão e considerar todos os outros estados: https://docs.google.com/spreadsheets/d/e/2PACX-1vSdKOgo_F1TZwGJBAED4C_7cml0bEATqeL3P9UKpBwASlTengZOUZi3DL4ZO3 ? gid = 0 & single = true
Usando esse gráfico, podemos ver o que é realmente necessário para desenvolver um sistema robusto de manipulação de notificações que funcione em quase todos os casos de uso possíveis.
Solução completa ↓
Nota: Uma resposta semelhante é sugerida nos comentários da resposta de Eric, no entanto, a folha de estado ajuda a encontrar todos os cenários possíveis, como eu fiz no meu aplicativo.
Encontre o código completo abaixo e comente abaixo se algum caso específico não for tratado:
AppDelegate
NotificationUtils : é aqui que você pode escrever todo o seu código para navegar para diferentes partes do aplicativo, manipular bancos de dados (CoreData / Realm) e fazer todo o resto que precisa ser feito quando uma notificação é recebida.
fonte
fonte
Existe apenas uma maneira confiável e funciona apenas no iOS 10 ou superior :
Usando o método de
UNUserNotificationCenter
implementaçãoUNUserNotificationCenterDelegate
:fonte
Você pode usar:
para lidar com as notificações push remotas.
Confira aqui a documentação
fonte
Ainda não tentei, mas talvez você possa enviar uma notificação a si mesmo? http://nshipster.com/nsnotification-and-nsnotificationcenter/
fonte
fonte
O problema com esta pergunta é que "abrir" o aplicativo não está bem definido. Um aplicativo é iniciado a frio a partir de um estado de não execução ou é reativado a partir de um estado inativo (por exemplo, ao voltar para outro aplicativo). Aqui está minha solução para distinguir todos esses estados possíveis:
E
MXDefaults
é apenas um pequeno invólucro paraNSUserDefaults
.fonte
Para
swift
fonte
Xcode 10 Swift 4.2
fonte
Para o iOS 10 ou superior, você pode usar esse método para saber quando sua notificação é clicada, independentemente do estado do aplicativo.
fonte
A resposta de M.Othman está correta para aplicativos que não contêm delegado de cena Para aplicativos de delegado de cena Isso funcionou para mim no iOS 13
Aqui está o código para o qual deve ser escrito a cena de conexão
Código para o delegado do aplicativo dar suporte a versões anteriores didFinishLaunchingWithOptions
fonte
Para usuários rápidos:
Se você deseja iniciar uma página diferente na abertura do push ou algo assim, é necessário fazer check-in
didFinishLaunchingWithOptions
como:fonte
EM SWIFT:
Estou executando o Push Notifications (com busca em segundo plano). Quando meu aplicativo está em segundo plano e recebo uma notificação por push, descobri que didReceiveRemoteNotification em appDelegate seria chamado duas vezes; uma vez quando a notificação é recebida e outra quando o usuário clica no alerta de notificação.
Para detectar se o alerta de notificação foi clicado, verifique se o valor bruto applicationState == 1 dentro do didReceiveRemoteNotification no appDelegate.
Eu espero que isso ajude.
fonte
Quando o aplicativo está em segundo plano como Shanegao, você pode usar
Mas se você deseja iniciar o aplicativo e quando o aplicativo é fechado e deseja depurá-lo, você pode ir para Editar esquema e, no menu esquerdo, selecione Executar e, em seguida, selecione Iniciar Aguardar o lançamento do executável. e iniciar o aplicativo quando você clique na notificação push
Editar esquema> Executar> Aguarde o lançamento do executável
fonte