Как сохранить вибрацию устройства в фоновом режиме

Я делаю приложение VOIP, когда поступает входящий вызов, а приложение находится на переднем плане. Я играю на звонке с кодом ниже

self.ringTimer = [[TimerService sharedInstance] createIntervalTimerWithInterval:2500 queue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) andBlock:^{
    AudioServicesPlayAlertSound(kSystemSoundID_Vibrate);
}];

NSString *ringingPath = [[NSBundle mainBundle] pathForResource:@"incoming_sound" ofType:@"mp3"];

AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryAmbient withOptions:AVAudioSessionCategoryOptionAllowBluetooth | AVAudioSessionCategoryOptionMixWithOthers error:nil];

// for normal phone receiver route it to speaker
if ([[audioSession audioRoute] isEqualToString:kAudioSessionDevice_Phone]) {
    [audioSession overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:nil];
}

NSURL *soundUrl = [NSURL fileURLWithPath:ringingPath];
NSError *error;
self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:soundUrl error:&error];

self.audioPlayer.numberOfLoops = -1;
[self.audioPlayer play];

Приведенный выше код работает хорошо, и он также учитывает кнопку бесшумного переключения при воспроизведении звука.

Однако, если я сверну приложение, устройство перестанет вибрировать и воспроизводить входящий звук. Это можно обойти, если я установлю категорию AVAudioSession на AVAudioSessionCategoryPlayback, но эта категория не отключит звук, когда переключатель без звука включен.

Я вижу другие приложения, такие как

Строка

  • (Получать входящие в приложении) они могут продолжать вибрировать устройство после сворачивания до тех пор, пока не будет достигнуто время ожидания вызова (никто не ответит) около одной минуты без отображения уведомления перед остановкой (Получить уведомление об окончании вызова).
  • (Получать входящие, когда приложение закрыто) они также делают то же самое, потому что, когда я отклоняю уведомление, устройство все еще может вибрировать в течение той же продолжительности.

Facebook Messenger

  • (Получайте входящие в приложении) они показывают длинное уведомление, чтобы устройство вибрировало. Если я отклоню это уведомление, оно сразу же прекратится.

  • (Получить входящее, когда приложение закрыто) если я отклоняю уведомление, устройство вибрирует еще 2-3 раза и показывает длинное уведомление (так же, как при получении входящего в приложении)

Viber, Skype

  • (Принимать входящие в приложении) Не уверен для скайпа, но для вайбера при сворачивании приложения он мгновенно перестает вибрировать.

  • (Получить входящие, когда приложение закрыто) Я думаю, что они сделали то же самое, что и facebook (не уверен)

Как сделать так, чтобы устройство вибрировало без уведомления типа Line при сворачивании приложения?

Если мне удастся найти способ и заставить его работать как Line, нужно ли мне использовать VoIP push, когда приложение не находится на переднем плане, чтобы реализовать этот метод? (Будет ли работать обычное push-уведомление?)


person SaintTail    schedule 22.11.2016    source источник
comment
Используете ли вы push-уведомления или Pushkit (тихие push-уведомления)?   -  person Hasya    schedule 23.11.2016
comment
Это сработало?   -  person Hasya    schedule 24.11.2016
comment
@Hasya Извините, пока нет времени разбираться в этом. Мне удается заставить его работать без PushKit для Receive incoming in the app (продолжать вибрировать устройство при сворачивании). Но для вне приложения, я думаю, требуется PushKit. Последуйте вашему предложению и дайте обратную связь в течение выходных.   -  person SaintTail    schedule 24.11.2016
comment
Не беспокойтесь, удачного кодирования. Дайте мне знать для любой помощи для приложения на основе VOIP.   -  person Hasya    schedule 24.11.2016


Ответы (2)


Вы должны использовать pushkit (тихое push-уведомление).

Для приложения в фоновом режиме или в состоянии остановки.

Skype, whatsapp, viber и т. д. Приложение на основе VOIP работает, как показано ниже.

Когда вы получаете полезную нагрузку, вы должны запланировать локальное уведомление. вы можете установить звуковой файл в локальном уведомлении. этот звуковой файл воспроизводится максимум 30 секунд. Если вы хотите повторять звуковой файл до тех пор, пока конечные пользователи не перестанут принимать или отклонять вызов, это также можно сделать с помощью управления флагами и переназначения локальных уведомлений.

Используйте приведенную ниже структуру для достижения вашей задачи.

Используйте этот файл simplepush.php

<?php

// Put your device token here (without spaces):


      $deviceToken = '1234567890123456789';
//


// Put your private key's passphrase here:
$passphrase = 'ProjectName';

// Put your alert message here:
$message = 'My first push notification!';



$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'PemFileName.pem');
stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);

// Open a connection to the APNS server
$fp = stream_socket_client(
//  'ssl://gateway.push.apple.com:2195', $err,
    'ssl://gateway.sandbox.push.apple.com:2195', $err,
    $errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);

if (!$fp)
    exit("Failed to connect: $err $errstr" . PHP_EOL);

echo 'Connected to APNS' . PHP_EOL;

// Create the payload body

$body['aps'] = array(
                     'content-available'=> 1,
                     'alert' => $message,
                     'sound' => 'default',
                     'badge' => 0,
                     );



// Encode the payload as JSON

$payload = json_encode($body);

// Build the binary notification
$msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload;

// Send it to the server
$result = fwrite($fp, $msg, strlen($msg));

if (!$result)
    echo 'Message not delivered' . PHP_EOL;
else
    echo 'Message successfully delivered' . PHP_EOL;

// Close the connection to the server
fclose($fp);

Используйте команды ниже, чтобы создать файл pem и использовать его в приведенном выше коде.

$ openssl x509 -in aps_development.cer -inform der -out PushCert.pem

# Convert .p12 to .pem. Enter your pass pharse which is the same pwd that you have given while creating the .p12 certificate. PEM pass phrase also same as .p12 cert.  
$ openssl pkcs12 -nocerts -out PushKey1.pem -in pushkey.p12

Enter Import Password:

MAC verified OK

Enter PEM pass phrase:

Verifying - Enter PEM pass phrase:

# To remove passpharse for the key to access globally. This only solved my stream_socket_client() & certificate capath warnings.
$ openssl rsa -in PushKey1.pem -out PushKey1_Rmv.pem

Enter pass phrase for PushChatKey1.pem:

writing RSA key

# To join the two .pem file into one file:
$ cat PushCert.pem PushKey1_Rmv.pem > ApnsDev.pem

После этого перейдите в папку simplepush.php и выполните команду fire -> php simplepush.php.

Таким образом, вы можете протестировать архитектуру настройки push-уведомлений.

https://zeropush.com/guide/guide-to-pushkit-and-voip

https://www.raywenderlich.com/123862/push-notifications-tutorial

Загрузить

import UIKit
import PushKit


class AppDelegate: UIResponder, UIApplicationDelegate,PKPushRegistryDelegate{



func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {


    let types: UIRemoteNotificationType = [.Alert, .Badge, .Sound]
    application.registerForRemoteNotificationTypes(types)

    self. PushKitRegistration()

    return true
}



//MARK: - PushKitRegistration

func PushKitRegistration()
{

    let mainQueue = dispatch_get_main_queue()
    // Create a push registry object
    if #available(iOS 8.0, *) {

        let voipRegistry: PKPushRegistry = PKPushRegistry(queue: mainQueue)

        // Set the registry's delegate to self

        voipRegistry.delegate = self

        // Set the push type to VoIP

        voipRegistry.desiredPushTypes = [PKPushTypeVoIP]

    } else {
        // Fallback on earlier versions
    }


}


@available(iOS 8.0, *)
func pushRegistry(registry: PKPushRegistry!, didUpdatePushCredentials credentials: PKPushCredentials!, forType type: String!) {
    // Register VoIP push token (a property of PKPushCredentials) with server

    let hexString : String = UnsafeBufferPointer<UInt8>(start: UnsafePointer(credentials.token.bytes),
        count: credentials.token.length).map { String(format: "%02x", $0) }.joinWithSeparator("")

    print(hexString)


}


@available(iOS 8.0, *)
func pushRegistry(registry: PKPushRegistry!, didReceiveIncomingPushWithPayload payload: PKPushPayload!, forType type: String!) {
    // Process the received push
    // From here you have to schedule your local notification

}

}

Параллельно, если вы настраиваете архитектуру Socket. Затем Socket используется для передачи данных, например, какие пользователи находятся в сети/офлайн, и вам нужно знать, не вызывая API, тогда вы можете использовать сокет, архитектура сокета на сервере будет отправлять данные о пользователе онлайн/офлайн на устройства без запроса с устройства.

Дайте мне знать, если я мог бы помочь вам где-нибудь.

Удачного кодирования.

person Hasya    schedule 23.11.2016
comment
Я заставляю это работать и добавляю ответ, чтобы включить вибрацию устройства в фоновом режиме. Спасибо. - person SaintTail; 27.11.2016

После некоторого теста я нашел способ, как Line это сделал.

Прием входящего вызова в приложении

Они используют

[[UIApplication sharedApplication] beginBackgroundTaskWithName:expirationHandler:]

чтобы приложение вибрировало, даже если вы уже свернули его. Этот метод будет поддерживать работу приложения и будет иметь продолжительность 180 секунд до истечения срока их действия.

Принимать входящие звонки, когда приложение закрыто

Это необходимо использовать PushKit как @Hasya, чтобы приложение проснулось, а также вызвать тот же метод, что и в приведенном выше сценарии (сохранять вибрацию устройства )

[[UIApplication sharedApplication] beginBackgroundTaskWithName:expirationHandler:]

На этот раз он истечет через 40 вместо 180 секунд. Также здесь нельзя воспроизводить входящий звук через AVAudioPlayer с категорией Ambient.

Итак, вам нужно прикрепить звук (нужна расширенная версия, так как для вас нет функции повтора) к UILocalNotification, который я где-то читал, что вы можете воспроизводить звук до 30 секунд.

Некоторые проблемы при использовании PushKit

Если у вас старая система, использующая APNS, вам необходимо поддерживать оба токена (APNS и VOIP) на стороне сервера. Потому что вы не можете отправить токен APNS с сертификатом VOIP. Токен должен быть отправлен с правильным типом сертификата.

person SaintTail    schedule 27.11.2016