iOS - Getting Callback On Media Library Access Alert By System - ios

I need to reload the music list in my app when the user allows the access to media library, and I would like to show a notification when the user disallows the access. How can I get the two callbacks?
For requesting access, I just added this line into the info.plist NSAppleMusicUsageDescription

You need to ask for the permission for accessing MPMediaLibrary, this is how you can request for it
Objective-C
[MPMediaLibrary requestAuthorization:^(MPMediaLibraryAuthorizationStatus authorizationStatus) {
if ( authorizationStatus == MPMediaLibraryAuthorizationStatusAuthorized ) {
// Reload your list here
} else {
// user did not authorize
} }];
Swift
MPMediaLibrary.requestAuthorization { (status) in
if status == .authorized {
// Reload your list here
} else {
// user did not authorize
}
}

Related

Requesting music library permissions swift or obj-c

I want to request music library permissions right when my application opens the first time.
The privacy in my info.plist are:
Privacy - Media library usage description
and
Privacy - music usage description
I would prefer this to be in my app delegate did finish launching with options but it is okay if it is in my viewDidLoad of the first viewController of my app.
You can request for permission like
let status = MPMediaLibrary.authorizationStatus()
switch status {
case .authorized:
// Get Media
case .notDetermined:
MPMediaLibrary.requestAuthorization() { status in
if status == .authorized {
DispatchQueue.main.async {
// // Get Media
}
}
}
}

Detect permission of media library ios

In my app, I want to detect that if user give the permission to his media library or not. User may denied media library permission when system popup ask or later from setting. Is there any way to detect the status of media library permission?
Here is my code that access list of songs.
MPMediaQuery *everything = [MPMediaQuery songsQuery];
NSArray *songArray = [everything items];
Please see below screenshot where user can change Media Library permissions.
-(void) checkMediaLibraryPermissions {
[MPMediaLibrary requestAuthorization:^(MPMediaLibraryAuthorizationStatus status){
switch (status) {
case MPMediaLibraryAuthorizationStatusNotDetermined: {
// not determined
break;
}
case MPMediaLibraryAuthorizationStatusRestricted: {
// restricted
break;
}
case MPMediaLibraryAuthorizationStatusDenied: {
// denied
break;
}
case MPMediaLibraryAuthorizationStatusAuthorized: {
// authorized
break;
}
default: {
break;
}
}
}];
}
Temporarily, i solved my problem by checking songArray object in below code
MPMediaQuery *everything = [MPMediaQuery songsQuery];
NSArray *songArray = [everything items];
If, user denied permission then songArray object is always nil, but if user allows permission to access to Media Library then songArray object have array of songs. Even if there will be no songs in device but user give permission to access Media Library then there will be array with 0 count.
Swift 4 access check. The simple solution is as follows, and you can alter to include the other alternatives however in my case it was all access or nothing.
private func checkPermissionForMusic() -> Bool {
switch MPMediaLibrary.authorizationStatus() {
case .authorized:
return true
default:
return false
}
}
Caution about using the above solutions - they do perform as a block statement and do not return a value (return true or return "authorised") on the same thread; the result is handled on a background thread. If you decide to use the suggestions above, use a handler (call another function) to handle the result you're expecting. This solution on the other hand tells you immediately if you have access or not. No waiting required.
More info is available in the Apple Docs

Is there a way to check push notification setting is ever requested?

Is there a way to check app has ever acquired push notification permission by system alert?
UIApplication.sharedApplication().currentUserNotificationSettings()?.types.rawValue
It returns 0 both when app never requested push notification permission and when user declined permission.
I want to show the system alert popup when app never requested permission. Also I want to let user go to setting to control permission setting if user ever declined permission.
For example:
let pushNotificationPermissionNeverAcquired: Bool = ???
if (pushNotificationPermissionNeverAcquired) {
// show system popup to acquire push notification permission
UIApplication.sharedApplication.registerForRemoteNotificationTypes([ * some types ])
} else if (UIApplication.sharedApplication().currentUserNotificationSettings()?.types.rawValue == 0) {
// user declined push notification permission, so let user go to setting and change the permission
UIApplication.sharedApplication().openURL(NSURL(string: UIApplicationOpenSettingsURLString))
} else {
// push notification is allowed
}
How can I check pushNotificationPermissionNeverAcquired?
This is how I am doing it right now.
if NSUserDefaults.standardUserDefaults().stringForKey(NOTIFICATION_PERMISSIONS_ASKED) == nil
{
NSUserDefaults.standardUserDefaults().setObject("true", forKey: NOTIFICATION_PERMISSIONS_ASKED)
// Request permissions
}
else
{
// Show your own alert
}
You could save a Boolean too if you want and access it with 'boolForKey', it returns false if no key was found.
Forgot this as well.
if let enabledTypes = UIApplication.sharedApplication().currentUserNotificationSettings()?.types {
switch enabledTypes
{
case UIUserNotificationType.None:
// Denied permissions or never given
default:
// Accepted
}
}

Permission alert to access user's address book does not halt execution

I have a button to import contacts from the user's address book. When they tap the button for the first time, my code returns a bool indicating whether user has granted permission or not. If permission is granted, then the contacts are imported and I perform a segue to a table view. If permission is not granted then the contacts are not imported and I perform the same segue to an empty table view. Here's what I have:
func myImportThenSegueFunction() {
if userHasAuthorizedAddressBookAccess() == true {
// Import contacts and perform segue
} else {
// Just perform segue
}
}
func userHasAuthorizedAddressBookAccess() -> Bool {
switch ABAddressBookGetAuthorizationStatus() {
case .Authorized:
return true
case .NotDetermined:
var userDidAuthorize: Bool!
ABAddressBookRequestAccessWithCompletion(nil) { (granted: Bool, error: CFError!) in
if granted {
userDidAuthorize = true
} else {
userDidAuthorize = false
}
}
return userDidAuthorize
case .Restricted:
return false
case .Denied:
return false
}
}
The problem is that when the button is tapped, the permission to access settings alert is briefly displayed while in the background the view performs the segue before the user has either granted or denied access in the alert prompt. Then the app immediately crashes saying that .NotDetermined returned nil meaning the variable userDidAuthorize returned before the user could even make a selection to set userDidAuthorize in the if/else block in ABAddressBookRequestAccessWithCompletion(nil).
My question is why does the code execute return in the case .NotDetermined before the user sets the variable userDidAuthorize to return the proper bool via the alert prompt? I've seen some hacks to wrap the execution in a time delay and I know this functionality is deprecated. How would I get this to work properly?
Because ABAddressBookRequestAccessWithCompletion is asynchronous and returns immediately. It needs to be like this as it's usually used from the main thread and can't block while the user is asked for permission.
You need to change the way you use it to embrace this, by calling a completion block with the status once you know it rather than returning the status immediately.

How may I check if my app has access to phone gallery

I have an app in which I take a picture with the camera and store that image into the native gallery. But if the app doesn't have permission for that, I want the user to know that. So how do I check it?
By the way: I store the image into the gallery with:
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
You need to check the status of ALAssetLibrary
make sure you have AssetsLibrary/AssetsLibrary.h included in your file
ALAuthorizationStatus status = [ALAssetsLibrary authorizationStatus];
// check the status for ALAuthorizationStatusAuthorized or ALAuthorizationStatusDenied e.g
if (status != ALAuthorizationStatusAuthorized) {
//show alert for asking the user to give permission
}
Swift 3
import photos
PHPhotoLibrary.requestAuthorization { status in
switch status {
case .authorized:
self.processSnapShotPhotos()
case .restricted:
print("handle restricted")
case .denied:
print("handle denied")
default:
// place for .notDetermined - in this callback status is already determined so should never get here
break
}
}
If you are using photos framework since ALAsset libraries are deprecated from ios 9 you can use PHAuthorizationStatus to check gallery access. You need to import photos framework as well.
#import <Photos/Photos.h>
- (BOOL)hasGalleryPermission
{
BOOL hasGalleryPermission = NO;
PHAuthorizationStatus authorizationStatus = [PHPhotoLibrary authorizationStatus];
if (authorizationStatus == PHAuthorizationStatusAuthorized) {
hasGalleryPermission = YES;
}
return hasGalleryPermission;
}
Note: iOS 6 Only
Is this what you are looking for
[ALAssetsLibrary authorizationStatus] == ALAuthorizationStatusAuthorized;
Other values of authorizationStatus are
ALAuthorizationStatusRestricted, // This application is not authorized to access photo data.
// The user cannot change this application’s status, possibly due to active restrictions
// such as parental controls being in place.
ALAuthorizationStatusDenied, // User has explicitly denied this application access to photos data.
ALAuthorizationStatusAuthorized // User has authorized this application to access photos data.

Resources