local notification plays only default sound after app update

The first load of an app with local notification custom sounds works correctly. When the app is updated (by Xcode, TestFlight or App Store) the app plays only the default sound. Behavior is the same with either new UNUserNotifications or deprecated UILocalNotifications. Behavior only occurs on iOS 10. The custom sound is a 2 second caf file in the application bundle (and it plays correctly multiple times until the app is updated). Notification permissions including Sounds are properly granted. Deleting the app and reloading causes the custom sound to play correctly again.


I've filed a RADAR but would appreciate any suggestions.


Test app:

@interface AppDelegate ()
@end

@implementation AppDelegate

BOOL soundsAllowed;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    NSLog(@"application didFinishLaunchingWithOptions");
    [self requestAuthorizationForNotifications];   
    return YES;
}

- (void)applicationWillResignActive:(UIApplication *)application {
    NSLog(@"applicationWillResignActive");
}

- (void)applicationDidEnterBackground:(UIApplication *)application {
    NSLog(@"applicationDidEnterBackground");
    [self scheduleLocalNotification];
}

- (void)applicationWillEnterForeground:(UIApplication *)application {
    NSLog(@"applicationWillEnterForeground");
    // check if we are still authorized
    [self requestAuthorizationForNotifications];
}

- (void)applicationDidBecomeActive:(UIApplication *)application {
    NSLog(@"applicationDidBecomeActive");
}

- (void)applicationWillTerminate:(UIApplication *)application {
    NSLog(@"applicationWillTerminate");
}

- (void)requestAuthorizationForNotifications {
    NSLog(@"requestAuthorizationForNotifications");
    soundsAllowed = NO;
    UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
    [center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert + UNAuthorizationOptionSound | UNAuthorizationOptionAlert)
                          completionHandler:^(BOOL granted, NSError * _Nullable error) {
                              if (error) {
                                  NSLog(@"request authorization error: %@", error);
                              } else {
                                  NSLog(@"request authorization no error");
                                  [self checkSoundsAllowed];
                              }
                          }];}

// examine notification settings to determine if sounds are allowed, save result
- (void)checkSoundsAllowed {
    UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
    [center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
        soundsAllowed = (settings.soundSetting == UNNotificationSettingEnabled);
        NSLog(@"soundsAllowed: %@", (soundsAllowed ? @"true" : @"false"));
        if (soundsAllowed) {
            // clear any existing notifications
            [center removeAllPendingNotificationRequests];
        }
    }];
}

- (void)scheduleLocalNotification {
    if (!soundsAllowed) {
        NSLog(@"scheduleLocalNotification soundsAllowed: false. return without scheduling");
        return;
    }
  
    // Set up the request content
    UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
    content.title = @"Title";
    content.body = @"Body";
    content.sound = [UNNotificationSound soundNamed:@"Test.caf"];
  
    // Deliver the notification in five seconds.
    UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger
                                                  triggerWithTimeInterval:5.f repeats:NO];
    UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:@"FiveSecond"
                                                                          content:content trigger:trigger];
    // Schedule the notification.
    UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
    [center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
        if (!error) {
            NSLog(@"addNotificationRequest succeeded! content.sound: %@ default sound: %@", content.sound, [UNNotificationSound defaultSound]);
        }
    }];
}

@end

"Engineering has determined that your bug report (28348721) is a duplicate of another issue (27968066) and will be closed."

Here's my shot at a workaround. Advising the user to reboot is not pretty, but I'm at a loss for what else to do while waiting for a fix from Apple.


// AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // give redownload warning if it's the first execution of a redownload on iOS 10
    _redownloadWarningRequired = NO;
    if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0")) {
        if ([prefs valueForKey:@"bundleVersionKey"] == nil) {
            // first execution of a virgin download
            [prefs setObject:[self currentDownloadDate] forKey:@"LastDownloadDateKey"];
        } else {
            NSDate *lastDownloadDate = [prefs objectForKey:@"LastDownloadDateKey"];
            if (![[self currentDownloadDate] isEqualToDate:lastDownloadDate]) {
                // it's the first execution of a redownload
                _redownloadWarningRequired = YES;
                [prefs setObject:[self currentDownloadDate] forKey:@"LastDownloadDateKey"];
            }
        }
    }
    // . . .
}

- (NSDate *)currentDownloadDate {
    NSString *bundleRoot = [[NSBundle mainBundle] bundlePath];
    NSFileManager *manager = [NSFileManager defaultManager];
    NSDictionary* attrs = [manager attributesOfItemAtPath:bundleRoot error:nil];
    return [attrs fileCreationDate];
}


// ViewController
- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    // if this is a redownload then alert - iOS 10 bug no custom notification sounds
    if (appDelegate.redownloadWarningRequired) {
        UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Action Required"
                                                                                 message:@""
                                              "An iOS 10 issue prevents UPDATED apps from delivering notifications with custom sounds. "
                                              "For this app to work correctly you must REBOOT your device once using \"Slide to power off\".\n\n"
                                              "Apple has been notified and is working on a fix."
                                                                          preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction *OKAction = [UIAlertAction actionWithTitle:@"I'll do that right now!"
                                                           style:UIAlertActionStyleDefault
                                                         handler:^(UIAlertAction * action) {
                                                             appDelegate.redownloadWarningRequired = NO;
                                                         }];
        [alertController addAction:OKAction];
        [self presentViewController:alertController animated:YES completion:nil];
    }
}

Does rebooting the device fix the issue at all? I'm experiencing similar issues (only in iOS10 though) and rebooting the device fixes the problem (which is still not satisfactory but better than a reinstall)

Rebooting does fix my issue. The issue only occurs on iOS 10.

If you hear of any other work arounds/fices, please post here. Unfortunately I can't release the new version of my app until I can resolve this issue without the user having to reboot/reinstall.

Stil seeing this in iOS 10.0.2 ;(

Fixed in iOS 10.1 beta 2.

What is the frequency of this issue. I have not seen it myself on my personal test accounts. I did have one of my external testflight users report this issue.

100% repeatable for me on two real apps and one test app, by reinstalling the app. Reinstall can be by Xcode, TestFlight or App Store. Only iOS 10.0.x. Workaround is to reboot the device after reinstalling the app.

I realized why I did not notice it. On I was running Ios 10.1 beta which seems to be ok. On iOS 10.0.2 I see this issue when Upgrading from store app to testflight app.


Doing a regular restart fixes the issue. My one question is, does this issue come back once the reboot has been done? It has not for me but I have not done had it installed long enough. Is there anything to do other than wait for iOS 10.1 to come out?

The issue does not come back, unless the user redownloads the app.


You can check if you are an update running 10.0.x and alert the user to reboot the device one time (or update iOS when 10.1+ is available). It's not a pretty workaround, especially if it takes an update to add. I'm holding off until 10.1 is released for my next update of the affected app just so I don't hurt users who are not experiencing the problem.

I think I am also going to do the same and wait it out since its up to Beta 5. Really lame since Its sitting in the store approved waiting to be submitted and this one issue is holding it back.

local notification plays only default sound after app update
 
 
Q