I´m trying to implement local notifications in a project made in QT, this is made through KNotifications, the current issue is with MACOS, the following code is the one being used:
UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
[center requestAuthorizationWithOptions: (UNAuthorizationOptionAlert) completionHandler:^(BOOL granted, NSError * _Nullable per_error) {
NSLog(#"PERMISSION: %d - %#", granted, per_error);
UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
content.title = #"TEST TITLE";
content.body = #"TEST BODY";
content.sound = UNNotificationSound.defaultSound;
NSUUID *uuid = [NSUUID UUID];
NSString *str = [uuid UUIDString];
UNNotificationTrigger* trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:1 repeats: NO];
UNNotificationRequest* request = [UNNotificationRequest requestWithIdentifier: str content:content trigger:trigger];
UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
[center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable req_error) {
NSLog(#"REQUEST LOG: %#", req_error);
}];
}];
When I run the code in an empty native XCode application, everything works fine, but when I run it on the QT / KNotifications project I get the following
Error Domain=UNErrorDomain Code=1 "Notifications are not allowed for this application"
I have checked and my test application appears right away on "Systems Preferences" but the other is not listed
Related
First of all i am using parse.com to store information.
This code simply opens the Maps app every time this method is run and saves the users location in a server.
MKDirectionsRequest *request = [[MKDirectionsRequest alloc] init];
[request setSource:[MKMapItem mapItemForCurrentLocation]];
[request setDestination:endingItem];
[request setTransportType:MKDirectionsTransportTypeAutomobile];
[request setRequestsAlternateRoutes:YES];
MKDirections *directions = [[MKDirections alloc] initWithRequest:request];
[directions calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse *response, NSError *error) {
if ( ! error && [response routes] > 0) {
MKRoute *route = [[response routes] objectAtIndex:0];
//route.distance = The distance
NSLog(#"total %f",route.expectedTravelTime );
int time = ceil(route.expectedTravelTime/60);
self.ETA = [#(time) stringValue];
NSLog(#"test %d",time);
NSLog(#"Total Distance (in Meters) :%0.1f",route.distance/1000);
self.distance = [#(route.distance*4899) stringValue];
// IF decline was pressed, need to fix if it's accepted
NSMutableDictionary *params = [[NSMutableDictionary alloc] init];
[params setObject:self.distance forKey:#"dist"];
[PFCloud callFunctionInBackground:#"sendAccepted" withParameters:params block:^(id object, NSError *error) {
if (!error) {
NSLog(#"Success answer sent");
} else {
NSLog(#"Failed to push");
}
}];
}
}];
[endingItem openInMapsWithLaunchOptions:launchOptions];
}
What i noticed is that if Maps application is already open when this method is run then it does not save the users data until i return to the applikation. HOWEVER if i close the Maps application before this method is run the it is always sent to the server.
Now the problem i think is that it obviously takes more time for Maps app to open if it was not opened before hence giving my applikation more time to complete the update. How can i solve this so it will still update the location even if my applikation goes to the background?
I'm trying to create an IPSEC VPN connection in my iOS app.
My code for setting up the configuration looks like this:
-(void)setUpConfig
NEVPNManager *manager = [NEVPNManager sharedManager];
int status = manager.connection.status;
if (status == NEVPNStatusConnected) {
manager.connection stopVPNTunnel];
} else {
[manager loadFromPreferencesWithCompletionHandler:^(NSError *error) {
NSError *startError;
if (error) {
NSLog(#"Load config failed [%#]", error.localizedDescription);
return;
}
NEVPNProtocolIPSec *p = (NEVPNProtocolIPSec *)self.manager.protocol;
if (!p) {
p = [[NEVPNProtocolIPSec alloc] init];
}
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"base64_encoded_cert" ofType:#"txt"];
NSString *certBase64String = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:NULL];
NSString *certPassword = #"cert_import_password";
NSString *vpnUsername = #"myUsername";
NSString *vpnPassword = #"myPassword";
NSString *url = #"my.server.address";
// This saves my credentials to the keychain and returns a persistent keychain reference
NSData *passRef = [self addVPNCredentialsToKeychain:vpnUsername withPassword:vpnPassword];
p.username = vpnUsername;
p.authenticationMethod = NEVPNIKEAuthenticationMethodCertificate;
p.serverAddress = url;
p.passwordReference = passRef;
p.identityData = [NSData dataWithBase64EncodedString:certBase64String];
p.identityDataPassword = certPassword;
p.disconnectOnSleep = NO;
p.useExtendedAuthentication = YES;
[manager setProtocol:p];
[manager setOnDemandEnabled:NO];
[manager setLocalizedDescription:#"My VPN"];
[manager saveToPreferencesWithCompletionHandler:^(NSError *error) {
if(error) {
NSLog(#"Save error: %#", error);
} else {
NSLog(#"Saved!");
}
}];
}];
}
}
-(NSData*)addVPNCredentialsToKeychain:(NSString*)username withPassword:(NSString*)password
{
NSMutableDictionary *keychainItem = [NSMutableDictionary dictionary];
NSData *encodedIdentifier = [username dataUsingEncoding:NSUTF8StringEncoding];
keychainItem[(__bridge id)kSecClass] = (__bridge id)kSecClassGenericPassword;
keychainItem[(__bridge id)kSecAttrDescription] = #"A password used to authenticate on a VPN server";
keychainItem[(__bridge id)kSecAttrGeneric] = encodedIdentifier;
keychainItem[(__bridge id)kSecAttrAccount] = encodedIdentifier;
keychainItem[(__bridge id)kSecAttrService] = [[NSBundle mainBundle] bundleIdentifier];
keychainItem[(__bridge id)kSecMatchLimit] = (__bridge id)kSecMatchLimitOne;
keychainItem[(__bridge id)kSecReturnPersistentRef] = #YES;
CFTypeRef typeResult = nil;
OSStatus sts = SecItemCopyMatching((__bridge CFDictionaryRef)keychainItem, &typeResult);
NSLog(#"Error Code: %d", (int)sts);
if(sts == noErr) {
NSData *theReference = (__bridge NSData *)typeResult;
return theReference;
} else {
keychainItem[(__bridge id)kSecValueData] = [password dataUsingEncoding:NSUTF8StringEncoding]; //Our password
OSStatus sts = SecItemAdd((__bridge CFDictionaryRef)keychainItem, &typeResult);
NSLog(#"Error Code: %d", (int)sts);
NSData *theReference = (__bridge NSData *)(typeResult);
return theReference;
}
return nil;
}
I then attempt to open a VPN connection like so:
-(void)connect
NEVPNManager *manager = [NEVPNManager sharedManager];
[manager loadFromPreferencesWithCompletionHandler:^(NSError *error) {
NSError *startError;
[manager.connection startVPNTunnelAndReturnError:&startError];
if(startError) {
NSLog(#"Start error: %#", startError.localizedDescription);
}
}];
}
And this does work under most conditions. The problem I am experiencing is that after factory restoring a device (on iOS 8, of course), and attempting to go through this setup and connection, my profile installs just fine, but the VPN fails to connect. In fact, my interpretation is that it is failing to attempt to connect.
After factory restoring a device and attempting to connect using my method, the following shows up in the device logs:
<Notice>: NESMLegacySession[MyVPN:BB73C098-B22E-46D3-9491-2A6D9F559F8F]: Received a start command from VPNApp[256], but start was rejected
Going into the Settings app and attempting to manually toggle the VPN using the switch under "Bluetooth" results in the switch turning on for a split second and then immediately going by to off. In this case, the following log is produced:
<Warning>: -[VPNBundleController _vpnNetworkingIsDisabled]: Airplane mode: 0, WiFi Enabled: 1
In both cases, no error dialog is produced when the VPN fails to start connecting - just the logs.
I can get around this problem by navigating to Settings > General > VPN. Once having just gone to that page (i.e. Not toggling VPN there), I can then control VPN just fine. Even going to that page before a VPN configuration is even installed results in me being able to connect just fine after installing a configuration.
My goal is to be able to start the VPN connection without having to first go to that VPN page in Settings. Can anyone shed some light on the situation? It seems to me like I'm missing something to first enable VPN connections.
This appears because VPN configuration stayed disabled by default for initial VPN connection.
You must enable VPN before saveToPreferencesWithCompletionHandler.
[[NEVPNManager sharedManager] setEnabled:YES];
Example:
[[NEVPNManager sharedManager] loadFromPreferencesWithCompletionHandler: ^(NSError *error) {
if (error) {
NSLog(#"Load error: %#", error);
}
else {
// No errors! The rest of your codes goes here...
NEVPNProtocolIPSec *p = [[NEVPNProtocolIPSec alloc] init];
p.serverAddress = #"VPN SERVER ADDRESS";
p.authenticationMethod = NEVPNIKEAuthenticationMethodCertificate;
p.localIdentifier = #"Local identifier";
p.remoteIdentifier = #"Remote identifier";
p.useExtendedAuthentication = YES;
p.identityData = [NSData dataWithBase64EncodedString:certBase64String];;
p.identityDataPassword = #"identity password";
p.disconnectOnSleep = NO;
// Set protocol
[[NEVPNManager sharedManager] setProtocol:p];
// Set on demand
NSMutableArray *rules = [[NSMutableArray alloc] init];
NEOnDemandRuleConnect *connectRule = [NEOnDemandRuleConnect new];
[rules addObject:connectRule];
[[NEVPNManager sharedManager] setOnDemandRules:rules];
// Set localized description
[[NEVPNManager sharedManager] setLocalizedDescription:#"Description"];
// Enable VPN
[[NEVPNManager sharedManager] setEnabled:YES];
// Save to preference
[[NEVPNManager sharedManager] saveToPreferencesWithCompletionHandler: ^(NSError *error) {
NSLog(#"Save VPN to preference complete");
if (error) {
NSLog(#"Save to preference error: %#", error);
}
}];
}
}];
Apple published with iOS 8 a new Framework "NetworkExtension".
I want to start a VPN Connection out of an app with the NEVPNManager, or has this Framework another use?
Has somebody information or an example about this Framework?
I can´t find information about it on the developer.apple.com website, only in the header files.
Thanks
The code would look something like this (exact implementation depends on the type of VPN):
NEVPNManager *manager = [NEVPNManager sharedManager];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(vpnConnectionStatusChanged) name:NEVPNStatusDidChangeNotification object:nil];
NEVPNProtocolIPSec *protocol = [[NEVPNProtocolIPSec alloc] init];
protocol.username = #“[Your username]”;
protocol.passwordReference = [KeyChainAccess loadDataForServiceNamed:#“[Your Service Name]"];
protocol.serverAddress = #“[Your Server Address]“;
protocol.authenticationMethod = NEVPNIKEAuthenticationMethodCertificate;
protocol.localIdentifier = #“[Your Local identifier]”;
protocol.remoteIdentifier = #“[Your Remote identifier]”;
protocol.useExtendedAuthentication = NO;
protocol.identityData = [Your VPN certification private key];
protocol.disconnectOnSleep = NO;
[manager setProtocol:protocol];
[manager setOnDemandEnabled:NO];
[manager setLocalizedDescription:#"VPN"];
NSArray *array = [NSArray new];
[manager setOnDemandRules: array];
NSLog(#"Connection desciption: %#", manager.localizedDescription);
NSLog(#"VPN status: %i", manager.connection.status);
[manager loadFromPreferencesWithCompletionHandler:^(NSError *error) {
// do config stuff
[manager saveToPreferencesWithCompletionHandler:^(NSError *error) {
}];
}];
NSError *startError;
[[NEVPNManager sharedManager].connection startVPNTunnelAndReturnError:&startError];
if(startError) {
NSLog(#"Start error: %#", startError.localizedDescription);
}
I am adding share functionalities on my facebook app.Like When a "saying" is selected there is a button for sharing that "saying" on facebook.And while clicking this button I can only see the shared saying on my facebook page,there isnt any information about my ios app.How can I make everyone knows that this saying is shared through my iOS app? Please help me....
I may be a little late. Hope this helps.
You have to use the Accounts framework and the Social framework to share with your app name.
First make sure you have set up your App on Facebook correctly. Then you can use the Facebook App ID to share your posts through your app.
Here is a sample code that shows you how to use the Accounts framework with the Social Framework :
ACAccountType * facebookAccountType = [self.accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
// At first, we only ask for the basic read permission
NSArray * permissions = #[#"email"];
NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithObjectsAndKeys:#"275485699289493", ACFacebookAppIdKey, permissions, ACFacebookPermissionsKey, ACFacebookAudienceOnlyMe, ACFacebookAudienceKey, nil];
NSArray *accounts = [self.accountStore accountsWithAccountType:facebookAccountType];
//it will always be the last object with single sign on
self.facebookAccount = [accounts lastObject];
[self.accountStore requestAccessToAccountsWithType:facebookAccountType options:dict completion:^(BOOL granted, NSError *error) {
if (granted && error == nil) {
/**
* The user granted us the basic read permission.
* Now we can ask for more permissions
**/
NSArray *readPermissions = #[ #"publish_actions"];
[dict setObject:readPermissions forKey: ACFacebookPermissionsKey];
[self.accountStore requestAccessToAccountsWithType:facebookAccountType options:dict completion:^(BOOL granted, NSError *error) {
if(granted && error == nil) {
NSDictionary *parameters = #{#"message": #"This Should Work Perfectly !! "};
NSURL *feedURL = [NSURL URLWithString:#"https://graph.facebook.com/me/feed"];
SLRequest *feedRequest = [SLRequest
requestForServiceType:SLServiceTypeFacebook
requestMethod:SLRequestMethodPOST
URL:feedURL
parameters:parameters];
feedRequest.account = self.facebookAccount;
[feedRequest performRequestWithHandler:^(NSData *responseData,
NSHTTPURLResponse *urlResponse, NSError *error)
{
// Handle response
}];
} else {
NSLog(#"error is: %#",[error description]);
}
}];
} else {
NSLog(#"error is: %#",[error description]);
}
}];
}
I am using the following code in an attempt to upload a video to YouTube from an iOS (installed) application via the v3.0 api:
...
NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:#"test" ofType:#"MOV"];
NSFileHandle *handle = [NSFileHandle fileHandleForReadingAtPath:path];
if (!handle)
{
NSLog(#"Failed to open file for reading");
return;
}
GTLServiceYouTube *service = [[GTLServiceYouTube alloc] init];
service.authorizer = auth;
GTLUploadParameters *params = [GTLUploadParameters uploadParametersWithFileHandle:handle MIMEType:#"application/octet-stream"];
GTLYouTubeVideoSnippet *snippet = [GTLYouTubeVideoSnippet object];
snippet.title = #"Test title";
snippet.descriptionProperty = #"Test description";
snippet.tags = #[ #"TestOne", #"TestTwo" ];
snippet.categoryId = #"17";
GTLYouTubeVideoStatus *status = [GTLYouTubeVideoStatus object];
status.privacyStatus = #"private";
GTLYouTubeVideo *video = [GTLYouTubeVideo object];
video.snippet = snippet;
video.status = status;
GTLQueryYouTube *query = [GTLQueryYouTube queryForVideosInsertWithObject:video part:#"snippet,status" uploadParameters:params];
// Perform the upload
GTLServiceTicket *ticket = [service executeQuery:query completionHandler:^(GTLServiceTicket *ticket, id object, NSError *error)
{
if (error)
{
NSLog(#"ERROR: %#", error);
return;
}
NSLog(#"SUCCESS! %#; %#;", ticket, object);
}];
ticket.uploadProgressBlock = ^(GTLServiceTicket *ticket, unsigned long long numberOfBytesRead, unsigned long long dataLength)
{
NSLog(#"%lld / %lld", numberOfBytesRead, dataLength);
};
...
All appears to be well until the upload finishes and I receive the following error:
Error Domain=com.google.GTLJSONRPCErrorDomain Code=-32602 "The operation couldn’t be completed. (Forbidden)" UserInfo=0x936ed70 {error=Forbidden, GTLStructuredError=GTLErrorObject 0x936e7f0: {message:"Forbidden" code:-32602 data:[1]}, NSLocalizedFailureReason=(Forbidden)}
I thought this may be an issue with authorization or my app settings; however, I am able to successfully fetch a video category list with the same credentials. I also verified that the app has been granted access to my Google account from my Google account's account page.
The scope used during auth is:
#"https://www.googleapis.com/auth/youtube https://www.googleapis.com/auth/youtube.upload"
I've been tweaking/searching for a few hours and can't seem to find anything about the error code I'm getting...