Recently, I applied for the qr code of Alipay to collect money. Alipay has such a function, that is, after someone scans your QR code to transfer money to you, there will be a voice push message like “Alipay has received 10 million yuan”, whether your Alipay app is killed or not.

As long as your remote push is turned on and alipay’s “QR code to receive money to account voice reminder” is turned on, you can receive it.

Open method: Alipay click Settings – General – New message notification in the upper right corner to open the account reminder.






image.png

And how much money others transfer to you will be reported to the account of how much money.

Explore and implement it.

There are currently two scenarios that implement the scenario described above.

Prerequisites the scenario described above is available only in iOS10 or later, because it must be based on Notification Servivice Extension





image.png

Notification Service Extension (iOS10) Notification Service Extension (iOS10)

1. ServiceExtension uses the AVSpeechSynthesisVoice class to transform the text you want to broadcast into a speech broadcast. 2. ServiceExtension uses the AVSpeechSynthesisVoice class to transform the number you want to broadcast into a speech broadcast. Find corresponding to a single audio, sorting, by joining together audio < through the push over the text to find related audio, then joining together into an audio >, then use the AudioServicesCreateSystemSoundID play

Before introducing the related methods, let’s introduce a test tool, SmartPush

It is also very simple to use and should be understood at a glance






image.png


Formal entry into the subject way one

@implementation NotificationService - (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler { self.contentHandler = contentHandler; self.bestAttemptContent = [request.content mutableCopy]; // Modify the notification content here... self.bestAttemptContent.title = [NSString stringWithFormat:@"%@ [modified]", self.bestAttemptContent.title]; self.contentHandler(self.bestAttemptContent); [self playVoiceWithAVSpeechSynthesisVoiceWithContent:self.bestAttemptContent.body]; } - (void)playVoiceWithAVSpeechSynthesisVoiceWithContent:(NSString *)content { if (content.length == 0) { return; } // Create a voice and return nil AVSpeechSynthesisVoice *voice = [AVSpeechSynthesisVoice voiceLanguage :@" zh-cn "]; AVSpeechSynthesizer *synthesizer = [[AVSpeechSynthesizer alloc] init]; / / instantiate the sound object AVSpeechUtterance * utterance = [AVSpeechUtterance speechUtteranceWithString: content]; utterance.voice = voice; Utterance. Rate = 0.5; [synthesizer speakUtterance:utterance]; }Copy the code

The content of the push is:

{"aps":{"alert":{"title":"iOS 10 title", "subtitle":"iOS 10 subtitle", "body":" there is only a good mother, mother's child like a block of treasure. Into the mother's arms, where to find happiness. Didn't mama of children like a blade of grass "}, "my - attachment" : "http://img01.taopic.com/160317/240440-16031FU23937.jpg", "mutable - content" : 1, "category":"myNotificationCategory1", "badge":3 } }Copy the code

Pit point description: 1. If you receive push but add system ringtone, i.e. you add “sound”:”default” to push JSON, then it may affect the playback of push sound. 2





image.png


3. After testing, the maximum sound duration is 5 seconds, which should be limited by Apple. Take the content pushed above as an example
Mother is the only good one in the world. A mother's child is like a treasure. Into the mother's arms, where to find happiness. A child without a mother is like grass."At most, it plays to
There is only a good mother, a mother's child like a treasure. Into her mother's arms


Method two after comparison, the sound of alipay playback is obviously better than the system method text to voice playback, a little girl is recorded. Or they’ve built their own text-to-speech thing. First try to use iFLYtek to achieve, the result failed. And then try to play it in a speech synthesis way like pre-recording the following possible broadcast


Pay treasure to account, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, hundreds, thousands, thousands and thousands and millions and millions, billions, yuan and so on


Such several recordings, and then use related names < related rules name themselves good >. For example, the content of push is 10010, then the array of the name of the converted recording file is @[@” Alipay account “,@”1″,@” wan “,@”0″,@”1″,@” ten “,@” yuan “] and then find these files, and then join them into a voice file for playing in sequence

Code demo:

@implementation NotificationService static int lianxunPlay = 1; - (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler { self.contentHandler = contentHandler; self.bestAttemptContent = [request.content mutableCopy]; // Modify the notification content here... self.bestAttemptContent.title = [NSString stringWithFormat:@"%@ [modified]", self.bestAttemptContent.title]; self.contentHandler(self.bestAttemptContent); / / 4, speech synthesis, using AudioServicesPlayAlertSoundWithCompletion play, success, but most time 5 seconds [self hechengVoice]; }Copy the code
- (void) hechengVoice {/ * * * * * * * * * * * * * * * * * * * * * * * * synthetic audio and play * * * * * * * * * * * * * * * * * * * * * * * * * * * * * / NSMutableArray * audioAssetArray = [[NSMutableArray alloc] init]; NSMutableArray *durationArray = [[NSMutableArray alloc] init]; [durationArray addObject:@(0)]; AVMutableComposition *composition = [AVMutableComposition composition]; NSArray *fileNameArray = @[@"daozhang",@"1",@"2",@"3",@"4",@"5",@"6"]; CMTime allTime = kCMTimeZero; for (NSInteger i = 0; i < fileNameArray.count; i++) { NSString *auidoPath = [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"%@",fileNameArray[i]] ofType:@"m4a"]; AVURLAsset *audioAsset = [AVURLAsset assetWithURL:[NSURL fileURLWithPath:auidoPath]]; [audioAssetArray addObject:audioAsset]; / / audio track AVMutableCompositionTrack * audioTrack = [composition addMutableTrackWithMediaType: AVMediaTypeAudio preferredTrackID:0]; / / audio material orbital AVAssetTrack * audioAssetTrack = [[audioAsset tracksWithMediaType: AVMediaTypeAudio] firstObject]; / / audio merger - insert audio track file [audioTrack insertTimeRange: CMTimeRangeMake (kCMTimeZero, audioAsset.duration) ofTrack:audioAssetTrack atTime:allTime error:nil]; // Update current position allTime = CMTimeAdd(allTime, Audioasset-.duration); } // Export the merged file - 'presetName' corresponds to the session.outputFileType. AVAssetExportSession *session = [[AVAssetExportSession alloc] initWithAsset:composition presetName:AVAssetExportPresetAppleM4A]; NSString *outPutFilePath = [[self.filePath stringByDeletingLastPathComponent] stringByAppendingPathComponent:@"xindong.m4a"]; if ([[NSFileManager defaultManager] fileExistsAtPath:outPutFilePath]) { [[NSFileManager defaultManager] removeItemAtPath:outPutFilePath error:nil]; NSLog(@"-- --%@",[session supportedFileTypes]); session.outputURL = [NSURL fileURLWithPath:outPutFilePath]; session.outputFileType = AVFileTypeAppleM4A; / / with the aforementioned ` present ` session. The corresponding shouldOptimizeForNetworkUse = YES; / / to optimize network [session exportAsynchronouslyWithCompletionHandler: ^ {if (session. Status = = AVAssetExportSessionStatusCompleted) {NSLog (@ "merger success - % @", outPutFilePath); NSURL * url = [NSURL fileURLWithPath: outPutFilePath];  static SystemSoundID soundID = 0; AudioServicesCreateSystemSoundID((__bridge CFURLRef _Nonnull)(url), &soundID); AudioServicesPlayAlertSoundWithCompletion (sound id, ^ {NSLog (@ "broadcast complete");}); } else {/ / other, concrete is described here ` AVAssetExportSessionStatus `.}}]; / * * * * * * * * * * * * * * * * * * * * * * * * synthetic audio and play * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /}Copy the code

Note: the above did not realize the number to correspond to the audio file name array process, direct implementation is the method of synthesizing audio.

1. The playing time is still limited to about 5 seconds. But if you play a money number, that’s enough. 2. The synthesized audio files are played without sound by AVAudioPlayer


Analysis: the above function is only for iOS10 above the system version can, then iOS10 below how to do? Can do so, do not broadcast how much money to the account, you can customize the remote push voice, to broadcast “Alipay, you have a payment to the account, please timely check” and so on, Alipay seems to be this routine.

Before each push, go to the background to check the current system version of the device to be pushed (this is not difficult to achieve), and then customize the push of different content. IOS10 and above will push money, and will not push sound. IOS10 below push “sound”=” custom sound file name “.

To sum up, alipay should be implemented in the way of mode 2, local synthetic audio file playback.

And the other thing to notice is, because this switch down here is turned on






image.png


When you go online again, you may need to make a statement, or there is a great possibility of being hit back by Apple. Recently, Apple has been more strict about the opening of such permissions. If you do not have similar functions, you also opened such permissions, may be dry back. If there is a good method as explained by Apple, please popularize it.

Finally put up the relevant Demo address, if you have better suggestions welcome to leave a message, if there is not correct, welcome to spray.

You can use my Demo to debug directly, pay attention to modify the bundleId during debugging, and then use your own developer account to configure the relevant push certificate





image.png





image.png