I am accessing user contacts in iOS.I have called a function which access the user contacts.An alert dialog is shown when this function is called & asking to user allow access to contacts or not.My code works fine if user allow the access.If user don't allow access then i want to again show that dialog of asking permission to user for accessing contacts.I am using following code for accessing the user contacts.Please tel me what to do.
code:
ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, NULL);
if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined)
{
ABAddressBookRequestAccessWithCompletion(addressBookRef, ^(bool granted, CFErrorRef error)
{
NSLog(#"acess:first block");
// First time access has been granted, add the contact
access=[NSUserDefaults standardUserDefaults];
[access setObject:#"false" forKey:#"contact_access"];
[access synchronize];
});
}
else if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized)
{
NSLog(#"acess:second block");
// The user has previously given access, add the contact
access=[NSUserDefaults standardUserDefaults];
[access setObject:#"true" forKey:#"contact_access"];
[access synchronize];
}
else
{
NSLog(#"acess:third block");
// The user has previously denied access
// Send an alert telling user to change privacy setting in settings appa
access=[NSUserDefaults standardUserDefaults];
[access setObject:#"false" forKey:#"contact_access"];
[access synchronize];
UIAlertView *alert=[[UIAlertView alloc]initWithTitle:#"Warning" message:#"Please allow access to contacts to use rolodex feature" delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[alert show];
}
Unfortunately it's not possible to show the permission popup twice in an iOS application. It's the same strategy for Location, Calendar, Photos, etc.
The possibility you've got is:
on iOS8 and later: Redirect the user on the application setting page, using the deep link provided by UIApplicationOpenSettingsURLString
UIApplication.sharedApplication().openURL(NSURL(string: UIApplicationOpenSettingsURLString)!)
on previous iOS version: Create a popup to warn the user that the application has no access to the contact list, and describe the way to grant access (Go to Setting-> Your App -> Contact ...)
The "allow contacts access" alert that is being shown to user in your app is managed by the system. It's shown once when you initially request access to contacts, user can either permit or deny the access. This alert will never be shown again once user has made a choice. If contacts access has been denied once, the only way to permit access to the contacts then is to go to Settings app and enable access using a switch manually via Contacts section in Privacy tab.
Kindly call this below code in your viewDidLoad method or wherever you want apply this below coding
ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(nil, nil);
if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined)
{
ABAddressBookRequestAccessWithCompletion(addressBookRef, ^(bool granted, CFErrorRef error) {
if (granted) {
// If the app is authorized to access the first time then add the contact
}
else
{
// Show an alert here if user denies access telling that the contact cannot be added because you didn't allow it to access the contacts
}
});
}
else if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized)
{
// If the user user has earlier provided the access, then add the contact
}
else
{
// If the user user has NOT earlier provided the access, create an alert to tell the user to go to Settings app and allow access
}
Related
To request facebook publish_actions permission during login in android I do
loginButton = (LoginButton) view.findViewById(R.id.login_button);
loginButton.setPublishPermissions(“publish_actions”);
loginButton.setUserInfoChangedCallback(new LoginButton.UserInfoChangedCallback() {
#Override
public void onUserInfoFetched(GraphUser user) {
FacebookOptInFragment.this.user = user;
updateUI();
}
});
That’s all I need to do and I am done. User will first login and then get prompted to grant publishing permission. How do I do the exact same thing in iOS?
Note that I just now downloaded the Facebook SDK, which means I have the latest and greatest (in case that is relevant).
Some documentation first
Requesting publishing permissions with publish_actions during login
creates a second step in the login UI. So you should request minimum
read permissions during login then request any additional or publish
permissions when someone actually needs them. To optimize your
permission requests, see Optimizing Permissions.
So If all you need is to authorize your iOS app and grant publish_actions permission and if you really want integrate with iOS Facebook account, you have to ask for reading permission before you ask for the publishing permission. See the Request at Login portion of the page link above for getting read permissions.
Then you can request additional permissions for publish_actions like
// Request publish_actions
[FBSession.activeSession requestNewPublishPermissions:[NSArray arrayWithObject:#"publish_actions"]
defaultAudience:FBSessionDefaultAudienceFriends
completionHandler:^(FBSession *session, NSError *error) {
__block NSString *alertText;
__block NSString *alertTitle;
if (!error) {
if ([FBSession.activeSession.permissions
indexOfObject:#"publish_actions"] == NSNotFound){
// Permission not granted, tell the user we will not publish
alertTitle = #"Permission not granted";
alertText = #"Your action will not be published to Facebook.";
[[[UIAlertView alloc] initWithTitle:alertTitle
message:alertText
delegate:self
cancelButtonTitle:#"OK!"
otherButtonTitles:nil] show];
} else {
// Permission granted, publish the OG story
[self publishStory];
}
} else {
// There was an error, handle it
// See https://developers.facebook.com/docs/ios/errors/
}
}];
Check this portion of the docs for permission management as well
I am trying to get a JSON (NSString *) of the address book , in async task , however I want it to be asynchronously and with a completion block .
I have managed to retrieve that easy without the completion block , however when I am adding the completion block I have the following compiler error :
Incompatible block pointer types passing NSString *(^)(bool, CFErrorRef)' to parameter of type 'ABAddressBookRequestAccessCompletionHandler' (aka 'void (^)(bool, CFErrorRef)')
here is my code
+ (NSString *) getAddressBook:(id (^)())block {
ABAuthorizationStatus status = ABAddressBookGetAuthorizationStatus();
if (status == kABAuthorizationStatusDenied)
{
// if you got here, user had previously denied/revoked permission for your
// app to access the contacts, and all you can do is handle this gracefully,
// perhaps telling the user that they have to go to settings to grant access
// to contacts
[[[UIAlertView alloc] initWithTitle:nil message:#"This app requires access to your contacts to function properly. Please visit to the \"Privacy\" section in the iPhone Settings app." delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil] show];
return nil;
}
CFErrorRef error = NULL;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);
if (error)
{
NSLog(#"ABAddressBookCreateWithOptions error: %#", CFBridgingRelease(error));
if (addressBook) CFRelease(addressBook);
return nil;
}
if (status == kABAuthorizationStatusNotDetermined)
{
// present the user the UI that requests permission to contacts ...
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) -> THE ERROR OCCURS HERE !
{...
I think the problem is within my completion blocks , but I can't find some good example/tutorial for my specific issue I would be really glad if some 1 could help me please.
Your problem is that you are declaring getAddressBook like this(if we strip block)
-(id)block
And you are trying to pass it as a function of type:
-(void)block:(BOOL)aBool error:(CFErrorRef*)error
Blocks are quite hard to get used with syntax(which is improved in swift) however I'm always refering to this site when not sure:
block syntax reference
UPDATE:
You have to actually wait for your async method finish. You may also refer to official documentation
+ (void) getAddressBook:((^)(NSString* result))block {
ABAuthorizationStatus status = ABAddressBookGetAuthorizationStatus();
if (status == kABAuthorizationStatusDenied)
{
// if you got here, user had previously denied/revoked permission for your
// app to access the contacts, and all you can do is handle this gracefully,
// perhaps telling the user that they have to go to settings to grant access
// to contacts
[[[UIAlertView alloc] initWithTitle:nil message:#"This app requires access to your contacts to function properly. Please visit to the \"Privacy\" section in the iPhone Settings app." delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil] show];
block(nil);
}
CFErrorRef error = NULL;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);
if (error)
{
NSLog(#"ABAddressBookCreateWithOptions error: %#", CFBridgingRelease(error));
if (addressBook) CFRelease(addressBook);
block(nil);
}
if (status == kABAuthorizationStatusNotDetermined)
{
// present the user the UI that requests permission to contacts ...
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) -> THE ERROR OCCURS HERE !
{
NSString* result = whatever
block(result);
});
}
}
And use it like this:
[YourClass getAddressBook:^(NSString* result)
{
//now you really have result
}];
I am using below Code, My application don't ask permission on iOS 6 while on iOS 7 and above version it ask for Contact permission access. On iOS 6 it doesn't show app in privacy setting as well. I have read some other thread but not found any solutions.
App crashed in iOS 6 when user changes Contacts access permissions
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"6.0")) {
__block CDNDeviceContact *controller = self;
// Request authorization to Address Book
ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, NULL);
if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined) {
ABAddressBookRequestAccessWithCompletion(addressBookRef,
^(bool granted, CFErrorRef error) {
if (granted)
[controller loadContacts];
else [controller doAlertForContact];
});
} else if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized) {
// The user has previously given access, add the contact
[self loadContacts];
} else {
[controller doAlertForContact];
}
if (addressBookRef) CFRelease(addressBookRef);
}
If the user has previously been presented with the request to get permission, it will not show again. According to the documentation,
The user is only asked for permission the first time you request access. Later calls use the permission granted by the user.
If testing in the simulator, I recommend that you go to iOS Simulator -> Reset Content and Settings so that you are able to simulate the event.
You don't need SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO and you also don't need to create an ABAddressBookRef.
For me, this is works like a charm:
if (ABAddressBookGetAuthorizationStatus) {
switch (ABAddressBookGetAuthorizationStatus()) {
case kABAuthorizationStatusNotDetermined:{
ABAddressBookRequestAccessWithCompletion(self.addressBook, ^(bool granted, CFErrorRef error) {
self.addContactButton.enabled = granted;
if (granted) {
// granted
} else {
// User denied access
}});
} break;
case kABAuthorizationStatusDenied: break;
case kABAuthorizationStatusAuthorized: break;
default: break;
}
}
I am doing login functionality.
In which -
user will give twitter email id to login and if login gets succeeded, my app will navigate user to its inner screen of my app.
If user has configured twitter account from user's device ios settings. My app takes user's email id from there and it will navigate
into second screen of my app.
If user has not configured twitter account from ios settings then, if user tapps a button login with twitter from my app login screen, it
will navigate user to the twitter page from where user has to give
email id (twitter id) and password and if login is successful it
should back to my app's inner screen(same functionality as like login
with facebook).
how could I achieve this. Thanks in advance.
First of all, you can not get user email address from twitter's API either using iOS7 framework or Twitter's Native API.
If you want to get user email address you can ask user to enter it manually. That's what Twitter people say in their API Docs. For your Point 2 and 3 here is the sample code using iOS7 way
if ([SLComposeViewController isAvailableForServiceType:SLServiceTypeTwitter]) // check Twitter is configured in Settings or not
{
self.accountStore = [[ACAccountStore alloc] init]; // you have to retain ACAccountStore
ACAccountType *twitterAcc = [self.accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
[self.accountStore requestAccessToAccountsWithType:twitterAcc options:nil completion:^(BOOL granted, NSError *error)
{
if (granted)
{
self.twitterAccount = [[self.accountStore accountsWithAccountType:twitterAcc] lastObject];
NSLog(#"Twitter UserName: %#, FullName: %#", self.twitterAccount.username, self.twitterAccount.userFullName);
[self getTwitterEmail]; // here you can ask user to enter email address. Its up to you how you ask user about it. Either in alert View or in Text Field.
}
else
{
if (error == nil) {
NSLog(#"User Has disabled your app from settings...");
}
else
{
NSLog(#"Error in Login: %#", error);
}
}
}];
}
else
{
NSLog(#"Not Configured in Settings......"); // show user an alert view that Twitter is not configured in settings.
}
I request access to Twitter account by this code:
-(void)requestAccessToTwitterAccounts{
ACAccountStore *accountStore = [[ACAccountStore alloc] init];
ACAccountType *accountType = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
[accountStore requestAccessToAccountsWithType:accountType options:nil completion:^(BOOL granted, NSError *error) {
if (granted)
{
NSLog(#"Granted");
_twAccounts = [accountStore accountsWithAccountType:accountType];
if (_twAccounts.count > 0){
NSLog(#"%#",_twAccounts);
} else {
NSLog(#"No Accoutn");
}
} else{
NSLog(#"Not Grand");
}
}];
}
The problem is that I call this method again when user choose "Don't Allow" but it just work OK 1time.
1st time, it ask for permission, if user choose "Don't Allow", the asking alert view not display again. I just see the log "Not Grand".
How can we renew request access to twitter again so that the alertView for permission display again?
I think you only can say (message if there are no access) user to allow app to use twitter again in twitter section in settings app.
Go to settings and enable Allow these apps to use your account switch for respective application Manually. Once you tapped Don't allow then the switch become off. Make the user to enable the Switch.
As par My Knowledge this is Not Possible once use can select "Don't Allow" that not asking again. This is a same like Address-book Permission Alert or Location Permission.
So you can set Manually Alert Massage for allow Access From setting and that need Manually open Setting view and Logged in From there.