以编程方式请求访问媒体库的授权失败

8

iOS 10现在要求用户授权才能访问媒体库。我们在使用媒体库之前会检查是否有访问权限,如果没有,则使用[MPMediaLibrary requestAuthorization:再次向用户请求授权。

我期望这将显示与应用程序启动时获取的访问媒体库的弹出请求相同的内容,但是什么也没有发生。它只是返回以前的MPMediaLibraryAuthorizationStatusDenied状态。

requestAuthorization的文档目前不完整,因此我无法确定我是否使用不正确,或者还有其他问题。

    if ( MPMediaLibrary.authorizationStatus == MPMediaLibraryAuthorizationStatusAuthorized)
    {
        // we already have access to the Media Library - use it here...
    }
    else
    {
        // We expect this to show a popup so the user can grant access, but does not work
        [MPMediaLibrary requestAuthorization:^(MPMediaLibraryAuthorizationStatus authorizationStatus)
         {
             if ( authorizationStatus == MPMediaLibraryAuthorizationStatusAuthorized )
             {
                 // success: the user authorized - use it here...
             }
             else
             {
                 // user did not authorize - tell user why here...
             }
         }];
    }

更新

显然没有办法使原始对话框重新出现(请参见下面的评论)。我现在使用这段代码,至少可以带我到正确的设置位置,以便用户可以进行更改。(适用于iOS8及以上版本)

NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
[[UIApplication sharedApplication] openURL:url];

拒绝通常与“未确定”不同,您应该得到后者。您第一次运行应用程序时没有拒绝访问吗?如果是这种情况,您将不得不重置它(在设置中或通过删除然后重新安装应用程序)。 - jcaron
是的,当应用程序最初启动时呈现初始对话框时,我们拒绝了访问。但是,如果“MPMediaLibrary requestAuthorization”调用不导致此提示再次出现,那么这样做有什么意义呢?否则,它与仅执行“MPMediaLibrary.authorizationStatus”并报告现有状态相同。这不是我们所需要的。 - Jim Leask
我所知道的所有iOS授权对话框都是相同的:它们只询问一次,并记住用户的选择。除非卸载应用程序,否则不会再次显示给定应用程序的授权对话框。之后更改选择的唯一方法是通过“设置”应用程序。调用这个对话框的目的是在第一次显示它。 - jcaron
好的。我们找到了调用设置的方法,所以至少我们可以将用户带到正确的位置进行更改。然而,初始对话框会在没有我们交互的情况下出现,所以我仍然不清楚他们为什么要使用“requestAuthorization”API,因为它与查询现有状态的简单查询没有任何区别。我将更新问题并附上调用设置的代码。 - Jim Leask
这可能是因为您在明确请求授权之前访问了媒体库。这因框架而异:某些框架只会返回错误,但其他框架会提示用户。您可以避免任何访问,并在适当的时间(例如在初始“引导之旅”中)调用requestAuthorization。 - jcaron
啊,这是可能的。感谢你的提示。如果你把它放在答案里,我会标记为已解决,因为我认为你是正确的。我们正在编写代码以期望这种行为,我也会添加一个答案作为参考。 - Jim Leask
1个回答

8
MPMediaLibrary 只会自动提示用户一次。如果在用户授权或拒绝之前询问,状态为 MPMediaLibraryAuthorizationStatusNotDetermined。如果用户以前已经拒绝了访问权限,则需要将用户发送到系统设置中以手动为您的应用程序打开它。
以下代码是我们如何实现的。
+ (void) validateMediaLibraryForMinimumIosAndAboveWithViewController:(UIViewController *)viewController
                                                        ifAuthorized:(void(^)())authorizedBlock
                                                     ifNotAuthorized:(void(^)())notAuthorizedBlock
{
    MPMediaLibraryAuthorizationStatus authorizationStatus = MPMediaLibrary.authorizationStatus;

    switch (authorizationStatus)
    {
        case MPMediaLibraryAuthorizationStatusAuthorized:
        {
            // We are already authorized - proceed
            if( authorizedBlock )
            {
                authorizedBlock();
            }
            break;
        }
        case MPMediaLibraryAuthorizationStatusNotDetermined:
        {
            // Not yet authorized - request it from the system
            [MPMediaLibrary requestAuthorization:^(MPMediaLibraryAuthorizationStatus authorizationStatus)
             {
                 if ( authorizationStatus == MPMediaLibraryAuthorizationStatusAuthorized )
                 {
                     if( authorizedBlock )
                     {
                         authorizedBlock();
                     }
                 }
                 else
                 {
                     PLog(@"The Media Library was not authorized by the user");
                     if( notAuthorizedBlock )
                     {
                         notAuthorizedBlock();
                     }
                 }
             }];
            break;
        }

        case MPMediaLibraryAuthorizationStatusRestricted:
        case MPMediaLibraryAuthorizationStatusDenied:
        {
            // user has previously denied access. Ask again with our own alert that is similar to the system alert
            // then take them to the System Settings so they can turn it on for the app
            NSString *titleString  = NSLocalizedStringWithDefaultValue(@"Media Library Privacy Alert Title",
                                                                       @"Localizable",
                                                                       [NSBundle mainBundle],
                                                                       @"Would Like to Access Apple Music And Your Media Library",
                                                                       @"Title for dialog requesting media library access");

            [self displayPermissionAlertFromViewController:viewController
                                                 withTitle:titleString];
            if( notAuthorizedBlock )
            {
                notAuthorizedBlock();
            }
            break;
        }
    }
}

+ (void)displayPermissionAlertFromViewController:(UIViewController *)viewController withTitle:(NSString *)title
{
    NSString* appName = [[NSProcessInfo processInfo] processName];

    NSString *titleString = [NSString stringWithFormat:@"\"%@\" %@",appName, title];

    NSString *cancelString = NSLocalizedStringWithDefaultValue(@"Don't Allow",
                                                               @"Localizable",
                                                               [NSBundle mainBundle],
                                                               @"Don't Allow",
                                                               @"Don't allow button");

    NSString *settingsString = NSLocalizedStringWithDefaultValue( @"Settings",
                                                                 @"Localizable",
                                                                 [NSBundle mainBundle],
                                                                 @"Settings",
                                                                 @"Settings button label");

    UIAlertController *alertController = [UIAlertController
                                          alertControllerWithTitle:titleString
                                          message:nil
                                          preferredStyle:UIAlertControllerStyleAlert];

    [alertController addAction:[UIAlertAction actionWithTitle:cancelString
                                                        style:UIAlertActionStyleDefault
                                                      handler:nil]];

    [alertController addAction:[UIAlertAction actionWithTitle:settingsString
                                                        style:UIAlertActionStyleDefault
                                                      handler:
                                ^(UIAlertAction * _Nonnull action)
                                {
                                    NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
                                    [[UIApplication sharedApplication] openURL:url];
                                }]];

    [viewController presentViewController:alertController animated:true completion:nil];
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接