web-dev-qa-db-fra.com

iOS: laissez l'application s'exécuter en arrière-plan

Comment conserver mon application en arrière-plan? Dois-je débrider mon iPhone pour ce faire? J'ai juste besoin de cette application pour vérifier quelque chose sur Internet à chaque intervalle défini et notifier en cas de besoin, pour mon propre usage.

21
Dennis

Oui, pas besoin de jailbreak. Consultez la section "Implémentation de tâches d'arrière-plan de longue durée" de ce document à partir de Apple .

Extrait du document d'Apple: Déclaration des tâches d'arrière-plan prises en charge par votre application

La prise en charge de certains types d'exécution en arrière-plan doit être déclarée à l'avance par l'application qui les utilise. Une application déclare la prise en charge d'un service à l'aide de son fichier Info.plist. Ajoutez la clé UIBackgroundModes à votre fichier Info.plist et définissez sa valeur sur un tableau contenant une ou plusieurs des chaînes suivantes: (voir la documentation d'Apple à partir du lien mentionné ci-dessus.)

19
user523234

Utilisez des notifications locales pour ce faire. Mais cela ne sera pas vérifié à chaque fois. Vous devrez définir une heure où vous pourrez vérifier votre événement spécifique, vous pouvez raccourcir cela en diminuant votre plage horaire. En savoir plus sur la notification locale pour savoir comment y parvenir sur:

http://developer.Apple.com/library/mac/#documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Introduction/Introduction.html

5
Saad
5
Mrunal

J'ai trouvé un moyen de faire fonctionner l'application en arrière-plan en jouant au silence

Assurez-vous que vous avez sélectionné la lecture audio dans les modes d'arrière-plan

De plus, n'utilisez pas cette méthode pendant longtemps, car elle consomme des ressources CPU et du jus de batterie, mais je pense que c'est un moyen approprié de maintenir l'application en vie pendant quelques minutes.

Créez simplement une instance de SilencePlayer, appelez play() puis stop(), lorsque vous avez terminé

import CoreAudio

public class SilencePlayer {
    private var audioQueue: AudioQueueRef? = nil
    public private(set) var isStarted = false

    public func play() {
        if isStarted { return }
        print("Playing silence")
        let avs = AVAudioSession.sharedInstance()
        try! avs.setCategory(AVAudioSessionCategoryPlayback, with: .mixWithOthers)
        try! avs.setActive(true)
        isStarted = true
        var streamFormat = AudioStreamBasicDescription(
            mSampleRate: 16000,
            mFormatID: kAudioFormatLinearPCM,
            mFormatFlags: kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked,
            mBytesPerPacket: 2,
            mFramesPerPacket: 1,
            mBytesPerFrame: 2,
            mChannelsPerFrame: 1,
            mBitsPerChannel: 16,
            mReserved: 0
        )
        let status = AudioQueueNewOutput(
            &streamFormat,
            SilenceQueueOutputCallback,
            nil, nil, nil, 0,
            &audioQueue
        )
        print("OSStatus for silence \(status)")
        var buffers = Array<AudioQueueBufferRef?>.init(repeating: nil, count: 3)
        for i in 0..<3 {
            buffers[i]?.pointee.mAudioDataByteSize = 320
            AudioQueueAllocateBuffer(audioQueue!, 320, &(buffers[i]))
            SilenceQueueOutputCallback(nil, audioQueue!, buffers[i]!)
        }
        let startStatus = AudioQueueStart(audioQueue!, nil)
        print("Start status for silence \(startStatus)")
    }

    public func stop() {
        guard isStarted else { return }
        print("Called stop silence")
        if let aq = audioQueue {
            AudioQueueStop(aq, true)
            audioQueue = nil
        }
        try! AVAudioSession.sharedInstance().setActive(false)
        isStarted = false
    }

}

fileprivate func SilenceQueueOutputCallback(_ userData: UnsafeMutableRawPointer?, _ audioQueueRef: AudioQueueRef, _ bufferRef: AudioQueueBufferRef) -> Void {
    let pointer = bufferRef.pointee.mAudioData
    let length = bufferRef.pointee.mAudioDataByteSize
    memset(pointer, 0, Int(length))
    if AudioQueueEnqueueBuffer(audioQueueRef, bufferRef, 0, nil) != 0 {
        AudioQueueFreeBuffer(audioQueueRef, bufferRef)
    }
}

Testé sur iOS 10 et Swift 4

3
Dima Rostopira

Je sais que ce n'est pas la réponse à votre question, mais je pense que c'est une solution.

Cela suppose que vous essayez de vérifier quelque chose ou d'obtenir régulièrement des données sur Internet?

Créez un service qui vérifie Internet à chaque intervalle défini pour tout ce que vous voulez savoir et créez une notification Push pour vous en avertir, si le serveur est en panne, ou tout ce que vous essayez de surveiller a changé d'état. Juste une idée.

3
nycynik

Oui, vous pouvez faire quelque chose comme ça. Pour cela, vous devez définir l'entrée dans info.plist pour indiquer à os que mon application fonctionnera en arrière-plan. J'ai fait cela alors que je voulais transmettre l'emplacement de l'utilisateur après un horodatage particulier au serveur. Pour cela, j'ai défini "Modes d'arrière-plan requis" sur "Registres d'application pour les mises à jour de localisation".

Vous pouvez écrire un gestionnaire de type UIBackgroundTaskIdentifier.

1
user1988