¿Cómo verificar si Apple Music está instalado en el dispositivo del usuario?

9

Estoy haciendo una aplicación de música con rapidez. La aplicación permite a los usuarios reproducir música a través de su suscripción a Apple Music a través de su aplicación Apple Music. Puedo verificar si el usuario tiene una suscripción a Apple Music a travé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) {
        print("user has Apple Music subscription")
    }

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

}

Sin embargo: hay escenarios en los que, por alguna razón, alguien tendrá una suscripción a Apple Music pero no tendrá la aplicación Apple Music descargada en su dispositivo. Si el usuario tiene la suscripción pero no el dispositivo, esencialmente quiero tratar ese caso como si no tuviera una suscripción, es decir, no podemos reproducir música a través de Apple Music.

Entonces, busco formas de agregar una verificación de si Apple Music está en el dispositivo del usuario. Encuentro que esta respuesta: Comprobar si una aplicación se instala mediante Swift combinado con este recurso para encontrar esquema de URL de Apple Música y concluir que puedo comprobar si un usuario tiene tanto una suscripción de Apple Música y la aplicación de Apple Música instalado en su dispositivo a travé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")
    }

}

El problema es, incluso después de eliminar Apple Music de mi dispositivo, el primer caso, es decir, el que imprime user has Apple Music subscription and has the apple music app installedtodavía se llama. Creo que tengo el esquema de URL correcto porque al cambiar "music://"a "musi://", user does not have subscription or doesn't have apple music installedse llama al segundo caso, es decir, al que imprime .

Cuando intento abrir URL(string: "music://")con Apple Music eliminado UIApplication.shared.open(URL(string: "music://")!), recibo la siguiente alerta:

ingrese la descripción de la imagen aquí

Entonces, ¿por qué el dispositivo dice que puedo abrir URL(string: "music://")incluso después de eliminar Apple Music? ¿Es URLcapaz de abrirse, pero el resultado es simplemente la presentación de la alerta anterior? ¿Es esta la forma correcta de confirmar que el usuario tiene Apple Music instalado en su dispositivo? ¿Existe alguna forma de confirmar que el usuario tiene Apple Music instalado en su dispositivo? Si Apple les da a los usuarios la opción de eliminar la aplicación Apple Music, también deberían darles a los desarrolladores la posibilidad de verificar si la aplicación está instalada.

David Chopin
fuente
Yo nunca trabajé con Apple Music, pero creo que Apple trata este esquema de URL de una manera especial, ya que es su propio producto, por lo tanto, cada vez que acierte ese esquema de URL, es mejor que le proponga al usuario descargar la aplicación, en lugar de regresar falso. ¿Intentaste identificar un esquema de URL válido que realmente abriría un álbum real en Apple Music o reproduciría una canción real? Ej URL(string: "music://trackID=3214534"). : . Tal vez este esquema de URL explícito se trataría de la manera habitual, pero no desencadenaría una app restorealerta.
Starsky
He intentado una serie de direcciones URL que utilizan identificadores de pista y el artista de música de Apple válidos que no parecen a lo profundo vínculo con la música de Apple: URL(string: "music://trackId=1377813289")!, URL(string: "music://track=1377813289"), URL(string: "music://artist=562555")!, URL(string: "music://artistId=562555")!. La única forma en que he podido hacer un enlace profundo es a través de algo como esto URL(string: "https://music.apple.com/us/artist/562555")!, pero esto obviamente no ayuda, ya que es HTTP.
David Chopin el
¿ha incluido en la lista blanca "music: //" en info.plist con LSApplicationQueriesSchemes ?. Si no, se supone que canOpenUrl se comporta mal.
Karthick Ramesh
1
Desafortunadamente, incluir en la lista blanca el esquema en mi info.plist no cambia el comportamiento en absoluto. Mi problema es que UIApplication.shared.canOpenURL(URL(string: "music://")!)está regresando truetodo el tiempo, incluso si se elimina la aplicación Apple Music. Necesito que regrese falsecuando se elimine la aplicación. Incluir en la lista blanca el esquema de URL no solucionará este problema (lo intenté)
David Chopin el
¿Encontraste una mejor solución para eso?
Martin Mlostek

Respuestas:

3

La mejor solución que tengo, aunque espero que haya algo mejor por ahí, es usar MPMusicPlayer.prepareToPlay(completionHandler:)para verificar si hay un error al intentar reproducir una pista:

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

}

No estoy seguro de cómo esto podría aplicarse a cualquier persona que use Apple Music dentro de su aplicación para otra cosa que no sea reproducir pistas, pero esto definitivamente parece funcionar como un cheque cuando estás a punto de tocar un cheque. Cada vez que recibo ese error, simplemente creo una alerta diciéndole a la persona que tiene una suscripción a Apple Music pero que no tiene la aplicación instalada.

Aún así, sería genial poder verificar sin algún controlador de finalización ya que eso permitiría que la verificación booleana se integre en declaraciones condicionales (vía if capability.contains(SKCloudServiceCapability.musicCatalogPlayback) && hasAppleMusicAppInstalled { //do something }).

David Chopin
fuente
Bueno, esta solución funciona al verificar los errores, pero es un poco hacky y requiere ejecutar el siguiente código en un controlador de finalización. Es mejor tener una forma simple de verificar, si es o no parte del marco MusicKit, si la aplicación está instalada.
David Chopin el
Pero sí, esta respuesta es una solución alternativa que utiliza errores al prepararse para reproducir una pista. Un desarrollador puede necesitar saber si Apple Music está instalado sin reproducir una pista.
David Chopin el
1
¿Sigue siendo la mejor solución que encontraste?
Martin Mlostek el
Desafortunadamente, sí
David Chopin el
0

Afortunadamente, Apple le proporciona un método que devuelve falso si no se registra ninguna aplicación instalada en el dispositivo para manejar el esquema de la URL, o si no ha declarado el esquema de la URL en su archivo Info.plist; de lo contrario, cierto.

func canOpenURL(_ url: URL) -> Bool

A continuación estoy publicando los esquemas de URL

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

Agregue los que usará en su archivo info.plist.

Después de esto, use 'canOpenURL' para verificar si hay más información.

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

Zeeshan Ahmed
fuente
El esquema de URL de Apple Music siempre regresa trueal pasarlo canOpenUrl. Ese es el problema principal que quiero abordar con esta pregunta.
David Chopin el
¿ha especificado 'Aplicación de música' en LSApplicationQueriesSchemes?
Zeeshan Ahmed
compruebe la respuesta nuevamente, la he actualizado.
Zeeshan Ahmed
Según el comentario de Karthick Ramesh, anteriormente probé esquemas de URL de lista blanca sin un cambio en el comportamiento
David Chopin el
0

Una posible solución es hacer lo siguiente: configurar un token de desarrollador a través de la API de Apple Music (se utiliza para que pueda consultar los puntos finales REST de Apple Music). Envíe una solicitud a la siguiente función StoreKit ( Documentación ):

requestUserToken(forDeveloperToken:completionHandler:)

Si su token de desarrollador es válido y el valor de token de usuario devuelto sigue siendo nulo / nulo, entonces el usuario del dispositivo no está suscrito al servicio Apple Music. Un error que se genera con el código de estado HTTP es 401 (no autorizado). Esto aún requiere que verifiques un error, sin embargo, no es necesario que intentes reproducir una pista específica (especialmente por alguna razón si la identificación de la pista de contenido con la que verificas no es válida o cambia).

Para el problema de la cuenta que inició sesión en el dispositivo y tiene una suscripción pero no la aplicación de Música descargada: maneje el error al intentar reproducir contenido específico y brinde información al usuario o utilice contenido que no requiera una suscripción de Apple Music como alternativa cuando ocurre un error

SierraMike
fuente
1
Sí, así que ya sé cómo verificar si un usuario tiene una suscripción . Mi respuesta proporcionada anteriormente aborda el manejo real de errores. La solución que estoy buscando es estrictamente si puede saber si el usuario tiene la aplicación Apple Music instalada en el dispositivo sin tener que intentar reproducir una pista.
David Chopin el
0

Sí, podemos verificar la mayoría de las aplicaciones siguiendo estos pasos:

  1. Use la URL profunda o el Esquema de URL para la aplicación particular que desea abrir, agréguelo a info.plist
  2. Use la misma URL y llame a 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!
       }
    }
CP Srinivasan
fuente
Este no es el problema, la pregunta esbozada que UIApplication.shared.canOpenUrl(URL(string: “music://”)!)siempre regresa true, incluso si la aplicación no está instalada.
David Chopin el