This is the fourth day of my participation in the November Gwen Challenge. Check out the details: The last Gwen Challenge 2021.

The introduction

Fans welfare: search # small program: iOS reverse, pay attention to the public number: iOS reverse welfare [digging gold booklet 50% discount code]

The annual iOS API adaptation is in place. Starting September 14, App Store Connect opened up iOS 15 and iPadOS 15 App submissions, and Apple announced that starting in April 2022, All iOS and iPadOS apps submitted to the App Store must be built using Xcode 13 and the iOS 15 SDK.

The official version of Xcode 13 includes iOS 15, iPadOS 15, tvOS 15, watchOS 8, and the macOS Big Sur 11.3 SDK. Xcode 13 must run on macOS 11.3 or later and supports iOS 9, tvOS 9, watchOS 2 or later.

Vim is also officially supported.

Xcode 13 Release Notes: Developer.apple.com/documentati…

I Message Push

Voice broadcast in iOS15 before the implementation of the idea:

  1. Split the audio you want to play and put it in the main package
  2. With Service Extension, local notifications are sent sequentially when a push is received from the server
  3. The sound of the local notification is the corresponding audio split
  4. Set sound to nil for received pushes to avoid interrupting the voice broadcast of local pushes.
  5. Set up a queue to process push messages to avoid problems caused by receiving multiple push messages in a short time.
  6. Set local notifications not to pop up banners (iOS15 has failed to set)

The title and body are set to null, or when the registration is not enabled UNAuthorizationOptionAlert, also note that the expand inside need to set the localization. But in iOS15, if the body is empty, you can’t play the sound.

	<key>CFBundleDevelopmentRegion</key>
	<string>$(DEVELOPMENT_LANGUAGE)</string>

Copy the code

1.1 Local Push Adaptation

Push new features: iOS15 above new attributes interruptionLevel for UNNotificationInterruptionLevel

Requirement: Use local push to implement voice broadcast message (send local notification in the extension, the last recipient is the main application)

When the extension receives a notification -> Compose audio -> store it to the appropriate path of the extension -> the extension sends itself a local notification whose sound is set to a compose file

IOS15 before the implementation of the idea:

  1. Split the audio you want to play and put it in the main package
  2. With Service Extension, local notifications are sent sequentially when a push is received from the server
  3. The sound of the local notification is the corresponding audio split

Problem: after iOS12.1, local push is used to implement voice announcement of messages. In iOS15, there is no sound. Kunnan.blog.csdn.net/article/det…

Cause: iOS15 has added interruptionLevel, which classifies notifications. And the content of the notice cannot be empty.

Solution: Use the non-passive interrupt level for the local notification, and the local notification must contain content, that is, the body cannot be empty. Content.body = @” cannot be empty “;

        UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
        UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
        content.title = @ "";
        content.subtitle = @ "";
        content.sound = [UNNotificationSound soundNamed:fileName];
        content.badge = @(1);
        
        if (@available(iOS 15.0, *)) {
            content.interruptionLevel = UNNotificationInterruptionLevelTimeSensitive;// The phone will light up and play a sound; May be displayed in do not Disturb mode (focus mode)
// @"{\"aps\":{\"interruption-level\":\"time-sensitive\"}}";
// @"{\"aps\":{\"interruption-level\":\"active\"}}";
            content.body = @" ";// The local push must have content, i.e. the body cannot be empty.
            
        }else{
            
            content.body = @ "";

        }
        
        UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:0.001 repeats:NO];
        // Add a notification identifier that can be used to remove, update, etc
        NSString *identifier = [NSString stringWithFormat:@"localPushId%lld", (long long) [[NSDate date] timeIntervalSince1970]];
        UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:identifier content:content trigger:trigger];
        [center addNotificationRequest:request withCompletionHandler:^(NSError *_Nullable error) {
            CGFloat waitTime = [self timeForAudioFileWithFileName:fileName];
// CGFloat waitTime = 0.3;
            
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(waitTime * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                [self localNotificationPushNextFile];
            });
        }];

Copy the code

There are currently four interrupt levels:

typedef NS_ENUM(NSUInteger, UNNotificationInterruptionLevel) {
    // Added to the notification list; does not light up screen or play sound
    UNNotificationInterruptionLevelPassive,
    
    // Presented immediately; Lights up screen and may play a sound
    UNNotificationInterruptionLevelActive,
    
    // Presented immediately; Lights up screen and may play a sound; May be presented during Do Not Disturb
    UNNotificationInterruptionLevelTimeSensitive,
    
    // Presented immediately; Lights up screen and plays sound; Always presented during Do Not Disturb; Bypasses mute switch; Includes default critical alert sound if no sound provided
    UNNotificationInterruptionLevelCritical,

} API_AVAILABLE(macos(12.0), ios(15.0), watchos(8.0), tvos(15.0));

Copy the code
  1. Passive notification does not light up the phone screen and does not play sound.
  2. Active: The default notification type is Active, which lights up the screen and plays a sound.
  3. Time Sensitive: Lights up and plays sound. May be displayed in do not Disturb mode (focus mode).

Set the push notification data: The time-sensitive interruption level can use the “interrupt-level” payload key :{” aps”:{” interrupt-level “:”time-sensitive”}}

You need to configure the following permissions: a. Xcode Enables the corresponding permissions

B. Developer background configuration appID support this permission (Xcode will automatically add the corresponding ability)

  1. Critical: Displays immediately, lights up, plays sound, invalid DND mode, bypassing mute, and uses a default sound if no sound is set.

Suitable for emergency situations such as earthquake, special application is required.

@property(Readonly, nonatomic) UNNotificationSetting timeSensitiveSetting; If no, prompt the user to enable it.

UNNotificationSetting

typedef NS_ENUM(NSInteger, UNNotificationSetting) {
    // The application does not support this notification type
    UNNotificationSettingNotSupported  = 0.// The notification setting is turned off.
    UNNotificationSettingDisabled,
    
    // The notification setting is turned on.
    UNNotificationSettingEnabled,
} API_AVAILABLE(macos(10.14), ios(10.0), watchos(3.0), tvos(10.0));

Copy the code

1.2 test

Developers who want to play AD HOT need a distribution certificate that has access to cloud management.

You can use the Aurora web side or interface for testing, or you can use smart Push.

1.3 Upgrading the JPush iOS SDK

V4.4.0: Pod ‘JPush’, ‘4.4.0’

Docs. Jiguang. Cn/changelog/j…

Update at 2021-10-28

Change Log:

The SDK ADAPTS to the local notification function of ios15

Rich media horizontal screen compatibility exception Handling

Ld: library not found for-ljcore-ios-2.3.4

Cause: Other Linker Flags information is not automatically updated

Solution: Delete jcore information from Other Linker Flags

II fixes a new issue: iOS15 uses local notifications to display banners

In order to avoid banners in iOS15 using local notifications, a new playback scheme is adopted. After receiving the Notification, Notification Service Extension parses the downloaded audio and modifies the sound field to be broadcast by the system.

2.1 Implementation Roadmap before replacement

After iOS15, the system modifies the push sounds field through Notification Service Extension to broadcast customized sounds.

+ (instancetype)soundNamed:(UNNotificationSoundName)name;

Copy the code

This method searches for sound files in the following locations, in order:

The <app_container>/Library/Sounds directory, where <app_container> is the app’s container directory.

The <group_container>/Library/Sounds directory, where <group_container> is one of the app’s shared group container directories. For information about how to configure group containers for your app, see Configure app groups.

The main bundle of the current executable.

In addition to playing the main bundle and Library/Sounds, we can also play the Library/Sounds audio in the AppGroup, so we can synthesize it in the background. Then download it to AppGroup and modify the sound field to play it.

Call self.contenthandler (self.beStatTemptContent) when the audio download process is complete; Pop up the top banner and start broadcasting, the audio will stop when the banner disappears, the audio needs to be controlled within 6s; Download failed to play the default voice.

If multiple pushes arrive at the same time, call self.contentHandler(self.bestAttemptContent); After that, the thread can be actively blocked for a certain length of time (audio duration).

2.2 Precautions

  1. Audio format: AIFF, CAF, WAV, MP3

  2. If the server does not cooperate and does not provide a download address for the synthesized voice fragment, the synthesized voice needs to be synthesized locally.

2.3 Core code implementation

@implementation NotificationService

- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
    self.contentHandler = contentHandler;
    self.bestAttemptContent = [request.content mutableCopy];

        self.bestAttemptContent.sound = [UNNotificationSound soundNamed:@"sound.wav"];
   
    self.contentHandler(self.bestAttemptContent);


}
Copy the code

see also

For more, check out # Applets: iOS Reverse, which presents valuable information only for you, focusing on the mobile technology research field.