Como verificar se o Apple Music está instalado no dispositivo do usuário?

9

Estou criando um aplicativo de música com rapidez. O aplicativo permite que os usuários reproduzam músicas por meio da assinatura do Apple Music por meio do aplicativo Apple Music. Consigo verificar se o usuário tem uma assinatura do Apple Music via:

SKCloudServiceController().requestCapabilities { (capability:SKCloudServiceCapability, err:Error?) in

    guard err == nil else {
        print("error in capability check is \(err!)")
        return
    }

    if capability.contains(SKCloudServiceCapability.musicCatalogPlayback) {
        print("user has Apple Music subscription")
    }

    if capability.contains(SKCloudServiceCapability.musicCatalogSubscriptionEligible) {
        print("user does not have subscription")
    }

}

No entanto: existem cenários em que alguém, por algum motivo, possui uma assinatura do Apple Music, mas não o aplicativo Apple Music baixado em seu dispositivo. Se o usuário tiver a assinatura, mas não o dispositivo, quero tratar essencialmente esse caso como se eles não tivessem uma assinatura, ou seja, não podemos tocar música pelo Apple Music.

Então, vou procurar maneiras de adicionar uma verificação para ver se o Apple Music está no dispositivo do usuário. Acho que esta resposta: Verificar se um aplicativo é instalado usando Swift combinado com este recurso para encontrar esquema de url da Apple Música e concluir posso verificar se um usuário tem tanto uma assinatura Apple Music e o aplicativo Apple Music instalado em seu dispositivo através de:

SKCloudServiceController()requestCapabilities { (capability:SKCloudServiceCapability, err:Error?) in

    guard err == nil else {
        print("error in capability check is \(err!)")
        return
    }

    if capability.contains(SKCloudServiceCapability.musicCatalogPlayback) && UIApplication.shared.canOpenURL(URL(string: "music://")!) {
        print("user has Apple Music subscription and has the apple music app installed")
    }

    if capability.contains(SKCloudServiceCapability.musicCatalogSubscriptionEligible) || !UIApplication.shared.canOpenURL(URL(string: "music://")!) {
        print("user does not have subscription or doesn't have apple music installed")
    }

}

O problema é que, mesmo depois de excluir o Apple Music do meu dispositivo, o primeiro caso, ou seja, aquele que imprime user has Apple Music subscription and has the apple music app installedainda está sendo chamado. Acredito que possuo o esquema de URL correto, pois ao mudar "music://"para "musi://"o segundo caso, ou seja, aquele que imprime user does not have subscription or doesn't have apple music installedestá sendo chamado.

Ao tentar abrir URL(string: "music://")com o Apple Music excluído via UIApplication.shared.open(URL(string: "music://")!), recebo o seguinte alerta:

insira a descrição da imagem aqui

Então, por que o dispositivo está dizendo que eu posso abrir URL(string: "music://")mesmo após a exclusão do Apple Music? É URLcapaz de ser aberto, mas o resultado é simplesmente a apresentação do alerta acima? Essa é a maneira correta de confirmar que o usuário tem o Apple Music instalado no dispositivo? Existe alguma maneira de confirmar que o usuário tem o Apple Music instalado no dispositivo? Se a Apple oferecer aos usuários a opção de excluir o aplicativo Apple Music, eles também deverão dar aos desenvolvedores a capacidade de verificar se o aplicativo está instalado.

David Chopin
fonte
Eu nunca trabalhei com a música da Apple, mas acredito que a Apple trata esse esquema de URL de uma maneira especial, pois é um produto próprio; portanto, sempre que você acessa esse esquema, é melhor propor ao usuário que faça o download do aplicativo, em vez de retornar falso. Você tentou identificar um esquema de URL válido que realmente abriria um álbum real no Apple Music ou tocaria uma música real? Ex URL(string: "music://trackID=3214534"). : . Talvez esse esquema de URL explícito seja tratado da maneira usual, mas não acione um app restorealerta.
Starsky
Eu tentei um número de URLs usando válidos pista e artista IDs da Apple de música que não parecem profunda ligação com a música Apple: URL(string: "music://trackId=1377813289")!, URL(string: "music://track=1377813289"), URL(string: "music://artist=562555")!, URL(string: "music://artistId=562555")!. A única maneira pela qual consegui fazer o link direto é por meio de algo assim URL(string: "https://music.apple.com/us/artist/562555")!, mas isso obviamente não ajuda, pois é HTTP.
David Chopin
você listou branco "music: //" em info.plist com LSApplicationQueriesSchemes ?. Caso contrário, canOpenUrl deve se comportar mal.
Karthick Ramesh
11
Infelizmente, a lista de permissões do esquema em meu info.plist não altera o comportamento. Meu problema é que ele UIApplication.shared.canOpenURL(URL(string: "music://")!)volta truesempre, mesmo que o aplicativo Apple Music seja excluído. Preciso retornar falsequando o aplicativo for excluído. A lista de permissões do esquema de URL não corrigirá esse problema (tentei).
David Chopin
você encontrou uma solução melhor para isso?
Martin Mlostek 08/12/19

Respostas:

3

A melhor solução que eu tenho, embora eu espere que exista algo melhor por aí, é usar MPMusicPlayer.prepareToPlay(completionHandler:)para verificar se há algum erro ao tentar reproduzir uma faixa:

SKCloudServiceController().requestCapabilities { (capability:SKCloudServiceCapability, err:Error?) in

    guard err == nil else {
        print("error in capability check is \(err!)")
        return
    }

    if capability.contains(SKCloudServiceCapability.musicCatalogPlayback) {
        print("user has Apple Music subscription")
        MPMusicPlayerController.systemMusicPlayer.setQueue(with: ["1108845248"])
        systemMusicPlayer.prepareToPlay { (error) in
            if error != nil && error!.localizedDescription == "The operation couldn’t be completed. (MPCPlayerRequestErrorDomain error 1.)" {
                //It would appear that the user does not have the Apple Music App installed
            }
        }
    }

    if capability.contains(SKCloudServiceCapability.musicCatalogSubscriptionEligible) {
        print("user does not have subscription")
    }

}

Não sei como isso se aplica a qualquer pessoa que use o Apple Music em seu aplicativo para outra coisa que não seja reproduzir faixas, mas isso parece funcionar definitivamente como uma verificação quando você está prestes a executar uma verificação. Sempre que sou atingido por esse erro, simplesmente crio um alerta informando à pessoa que ela possui uma assinatura do Apple Music, mas não tem o aplicativo instalado.

Ainda assim, seria ótimo poder verificar sem algum manipulador de conclusão, pois isso permitiria que a verificação booleana fosse integrada às instruções condicionais (via if capability.contains(SKCloudServiceCapability.musicCatalogPlayback) && hasAppleMusicAppInstalled { //do something }).

David Chopin
fonte
Bem, essa solução funciona verificando se há erros, mas é um pouco invasiva e requer a execução do código a seguir em um manipulador de conclusão. É melhor ter uma maneira de verificar com facilidade, se faz parte da estrutura do MusicKit, se o aplicativo está instalado.
David Chopin
Mas sim, essa resposta é uma solução alternativa que utiliza erros ao se preparar para reproduzir uma faixa. Um desenvolvedor pode precisar saber se o Apple Music está instalado sem reproduzir uma faixa.
David Chopin
11
essa ainda é a melhor solução que você encontrou?
Martin Mlostek
Infelizmente, sim
David Chopin
0

Felizmente, a Apple fornece um método que retorna false se nenhum aplicativo instalado no dispositivo estiver registrado para lidar com o esquema da URL ou se você não tiver declarado o esquema da URL no arquivo Info.plist; caso contrário, é verdade.

func canOpenURL(_ url: URL) -> Bool

A seguir, estou postando os esquemas de URL

Open = music://
Open = musics://
Open = audio-player-event://

Adicione os que você usará mais no seu arquivo info.plist.

Após esse uso, 'canOpenURL' para verificar mais informações, consulte os documentos da Apple

https://developer.apple.com/documentation/uikit/uiapplication/1622952-canopenurl

Zeeshan Ahmed
fonte
O esquema de URL do Apple Music está sempre retornando trueao ser transmitido canOpenUrl. Essa é a questão principal que quero abordar com esta pergunta.
David Chopin
você especificou 'Music app' em LSApplicationQueriesSchemes?
Zeeshan Ahmed
verifique a resposta novamente, eu a atualizei.
Zeeshan Ahmed
Por comentário do Karthick Ramesh, eu já tentou whitelisting esquemas de URL sem uma mudança de comportamento
David Chopin
0

Uma solução possível é fazer o seguinte: Configure um token de desenvolvedor por meio da API Apple Music (Usado para que você possa consultar os pontos de extremidade REST do Apple Music). Envie uma solicitação para a seguinte função StoreKit ( Documentação ):

requestUserToken(forDeveloperToken:completionHandler:)

Se o seu token de desenvolvedor for válido e o valor do token de usuário retornado ainda for nulo / nulo, o usuário do dispositivo não é assinante do serviço Apple Music. Um erro gerado com o código de status HTTP é 401 (Não autorizado). Isso ainda exige que você verifique um erro, no entanto, não é necessário tentar reproduzir uma faixa específica (especialmente por algum motivo, se o ID da faixa de conteúdo sob sua verificação se tornar inválido ou alterado).

Para o problema de conta conectada ao dispositivo e com uma assinatura, mas não o aplicativo Music baixado: lide com o erro ao tentar reproduzir conteúdo específico e forneça informações ao usuário ou use conteúdo que não requer uma assinatura do Apple Music como alternativa quando ocorrer um erro.

SierraMike
fonte
11
Sim, então eu já sei como verificar se um usuário tem uma assinatura . Minha resposta fornecida acima aborda o tratamento real de erros. A solução que estou procurando é estritamente se você pode saber se o usuário tem o aplicativo Apple Music instalado no dispositivo sem ter que tentar reproduzir uma faixa.
David Chopin
0

Sim, podemos verificar a maioria dos aplicativos seguindo estas etapas:

  1. Use o URL profundo ou o esquema de URL para o aplicativo específico que você deseja abrir, adicione-o a info.plist
  2. Use o mesmo URL e chame este método
    func canOpenURL(_ url: URL) -> Bool
    let url = URL(string: "music://")

    UIApplication.shared.open(url!) { (result) in
       if result {
          // The URL was delivered successfully!
       }
    }
Srinivasan CP
fonte
Esse não é o problema, a questão descrita que UIApplication.shared.canOpenUrl(URL(string: “music://”)!)está sempre retornando true, mesmo que o aplicativo não esteja instalado.
David Chopin