I have this peace of code to get device id :
-(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
NSString *devicetokenRN = [NSString stringWithFormat:#"%#", deviceToken];
devicetokenRN = [devicetokenRN stringByReplacingOccurrencesOfString:#" " withString:#""];
devicetokenRN = [devicetokenRN stringByReplacingOccurrencesOfString:#"<" withString:#""];
devicetokenRN = [devicetokenRN stringByReplacingOccurrencesOfString:#">" withString:#""];
// send device token for APNS without spaces or <>
DeviceID *DeviceIdentifier = [[DeviceID alloc ] init];
// sending it to the Device.h
[DeviceIdentifier setDeviceID:devicetokenRN];
}
I need to retrieve this DeviceID as the first thing on my ViewController. As it doesn't do this function before it runs the view controller, because if I use NSlog in the ViewController it is NULL as it hasn't run this first. I need to get some variable like this first before it runs the UITableView. Any ideas would be brilliant thanks.
In AppDelegate, you can save the deviceToken value in NSUserDefaults like
put these line in didRegisterForRemoteNotificationsWithDeviceToken method in appdelegate.m like this
-(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
[[NSUserDefaults standardUserDefaults] setObject:deviceToken forKey:#"DeviceToken"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
also put this line of code in your view Controller.m and In ViewDidLoad method
and Retrieve that value.
[[NSUserDefaults standardUserDefaults] objectForKey:#"DeviceToken"];
You can get and store your deviceId in NSUserDefaults
-(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
NSUUID *identifierForVendor = [[UIDevice currentDevice] identifierForVendor];
NSString *deviceId = [identifierForVendor UUIDString];
NSUserDefaults *userRegistrarionDetails = [NSUserDefaults standardUserDefaults];
[userRegistrarionDetails setObject:deviceId forKey:#"deviceID"];
[userRegistrarionDetails synchronize];
}
And you can get anywhere in your whole project by
NSUserDefaults *userRegistrarionDetails = [NSUserDefaults standardUserDefaults];
NSString * deviceId = [userRegistrarionDetails objectForKey:#"deviceID"];
NSLog(#"%#", deviceId);
Related
I have an existing app in ios now I want to integrate some code to check whether the app is first install or updated or same version. but the problem is that if an old user update the app the first launch is working while the app is updated.Can anybody tell me how to handle it ?
You could save a version number to NSUserDefaults, and update it accordingly.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// ...
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *currentAppVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:#"CFBundleShortVersionString"];
NSString *previousVersion = [defaults objectForKey:#"appVersion"];
if (!previousVersion) {
// first launch
// ...
[defaults setObject:currentAppVersion forKey:#"appVersion"];
[defaults synchronize];
} else if ([previousVersion isEqualToString:currentAppVersion]) {
// same version
} else {
// other version
// ...
[defaults setObject:currentAppVersion forKey:#"appVersion"];
[defaults synchronize];
}
return YES;
}
I've tried Googling, and keep hitting the same sorts of answers, ie.
- (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
NSString *token = [[deviceToken description] stringByTrimmingCharactersInSet: [NSCharacterSet characterSetWithCharactersInString:#"<>"]];
token = [token stringByReplacingOccurrencesOfString:#" " withString:#""];
NSLog(#"content---%#", token);
}
However, I'm struggling to see how I might call/invoke this method in my App Delegate at a given event.
In my app, the first screen they see is login/signup. So on success of signup, I'd like to grab the device token and send it to my server to save against that new user. How exactly can I invoke this method from within a View Controller (or wherever) at a given time/event of my choosing, (and not just when the app first boots up)?
Hi try to use NSUserDefaults to store this data.
[[NSUserDefaults standardUserDefaults] setValue:deviceTokenString forKey:#"deviceToken"];
And to get this data use:
NSUserDefaults *data = [NSUserDefaults standardUserDefaults];
NSString *string = [data objectForKey:#"deviceToken"];
I want to open a ViewController only once when the app start for the very first time. Below is my code. The problem is when I am writing YES to NSUserdefaults , doing a synchronise , and then closing the app. in Xcode using simulator , the value is not updated to Yes.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"isFirstLaunch"])
{
// app already launched
[[NSUserDefaults standardUserDefaults] registerDefaults:[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:NO],#"isFirstLaunch", nil]];
[[NSUserDefaults standardUserDefaults]synchronize];
}
else
{
[[NSUserDefaults standardUserDefaults] registerDefaults:[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES],#"isFirstLaunch", nil]];
[[NSUserDefaults standardUserDefaults]synchronize];
}
return YES;
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"isFirstLaunch"])
{
NSLog(#"first time");
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
LASplashUserSettingViewController *splash = [storyboard instantiateViewControllerWithIdentifier:#"splash"];
[self.window.rootViewController presentViewController:splash animated:NO completion:nil];//
}
}
Why is NSUserDefaults not saving my values?
Have followed above and many other links. what am i missing here?
Thanks,
what am i missing here?
-registerDefaults: doesn't do what you think it does. Use -setBool:forKey: instead.
-registerDefaults: is used to ensure that values exist for certain keys in the defaults system. There's no need to call -synchronize after that method because the values in the registration domain are never saved. You probably meant to use that method to set up the default value YES for isFirstLaunch, but your code checks the value for the key before you register the default value! which defeats the purpose of the method. Proper use would be to call -registerDefaults: first, and then check the value associated with the key, and if the value is YES then call -setBool:forKey: to save the value NO.
A simpler option to detect the first launch would be to invert the question. Skip the -registerDefaults: call altogether and change the key to appHasRunPreviously. If no value is stored for a given key, -boolForKey: will return NO. If that happens, you know that this is the first time the app is running, and you should save YES for that key using -setBool:forKey:.
This is how you use NSUserDefaults in AppDelegate.m
+ (void)initialize
{
// Register defaults for first time
NSMutableDictionary *defs = [NSMutableDictionary dictionary];
[defs setObject:[NSNumber numberWithBool:YES] forKey:#"isFirstLaunch"];
[[NSUserDefaults standardUserDefaults] registerDefaults:defs];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if([defaults boolForKey:#"isFirstLaunch"])
{
// Do your stuff here
[defaults setBool:NO forKey:#"isFirstLaunch"];
[defaults synchronize];
}
}
Don't set isFirstLaunch back to YES in the else-condition if you only want the view to be shown once.
You can try this
[[NSUserDefaults standardUserDefaults]setBool:YES forKey:#"AlreadyLaunched"];
[[NSUserDefaults standardUserDefaults]boolForKey:#"AlreadyLaunched"]
Iam able to get and use device token fine here:
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)devToken {
// Prepare the Device Token for Registration (remove spaces and < >)
NSString *deviceToken = [[[[devToken description]
stringByReplacingOccurrencesOfString:#"<"withString:#""]
stringByReplacingOccurrencesOfString:#">" withString:#""]
stringByReplacingOccurrencesOfString: #" " withString: #""];
}
I would like to get/use the deviceToken within:
- (void)applicationDidBecomeActive:(UIApplication *)application
{
// How To GET/USE device Token Here?
}
You can store device token in NSUserDefaults , so when ever you want it you can easily get it,
-(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{
NSString *token = [[deviceToken description] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:#"<>"]];
token = [token stringByReplacingOccurrencesOfString:#" " withString:#""];
[[NSUserDefaults standardUserDefaults] setObject:token forKey:#"token"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
Now you can get it anywhere anytime till your app is not deleted.
- (void)applicationDidBecomeActive:(UIApplication *)application
{
NSString *token=[[NSUserDefaults standardUserDefaults]objectForKey:#"token"];
}
you can add a property in your appDelegate,like this:
then you can set the property in - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)devToken ,and get the property in - (void)applicationDidBecomeActive:(UIApplication *)application.
It's best practice to convert deviceToken into Base64 NSString, so you no need to parse description. You can store this value in private member of you AppDelegate (using category), or public property.
My published application makes use of the CFUUID and SSKeychain in order to identify the device (and to keep that ID unchanged even if the app is uninstalled and reinstalled)
I save those device ID in the server, and I recently noticed that some users have several of those IDs for the same real device. The only explanation I see is that the ID is not being saved or loaded from the Keychain and thus the device generates a new one. The strange thing is that it works fine on some other devices running the same iOS version.
Any ideas on what could be going on?
This is my related code in (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
NSString* identifier = #"appName";
NSString* serviceName = #"com.company.appName";
NSString *retrieveuuid = [SSKeychain passwordForService:serviceName account:identifier];
if (retrieveuuid == nil) {
CFUUIDRef theUUID = CFUUIDCreate(NULL);
CFStringRef string = CFUUIDCreateString(NULL, theUUID);
CFRelease(theUUID);
NSString *uuid = (NSString*) string;
[SSKeychain setPassword:uuid forService:serviceName account:identifier];
}
EDIT: My guess is that retrieveuuid == nil is not working as expected for some reason. Later in the app I register for push notifications and send the push token to the server together with this CFUUID that I read with the same exact line [SSKeychain passwordForService:serviceName account:identifier] but when it is sent to the server it is not nil (So I can see several CFUUIDs with the same push token).
EDIT 2 to attach more actual code.
AppDelegate.m
NSString* identifier = #"appName";
NSString* serviceName = #"com.company.appName";
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//Creating UUID
NSString *retrieveuuid = [AppDelegate getDeviceId];
if (retrieveuuid == nil) {
CFUUIDRef theUUID = CFUUIDCreate(NULL);
CFStringRef string = CFUUIDCreateString(NULL, theUUID);
CFRelease(theUUID);
NSString *uuid = (NSString*) string;
[SSKeychain setPassword:uuid forService:serviceName account:identifier];
}
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:
(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
}
+ (NSString*) getDeviceId {
return [SSKeychain passwordForService:serviceName account:identifier];
}
- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken
{
NSString *newToken = [deviceToken description];
newToken = [newToken stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:#"<>"]];
newToken = [newToken stringByReplacingOccurrencesOfString:#" " withString:#""];
_deviceToken = [[NSString alloc] initWithString:newToken];
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
NSString *user = [prefs objectForKey:#"appNameUsername"];
if(user && ![user isEqualToString:#""]){
RestClient *rest = [[RestClient alloc] init];
rest.delegate = self;
rest.tag = 2;
[rest updateToken:newToken ForUsername:user];
[rest release];
}
}
RestClient.m
-(void) updateToken:(NSString *)token ForUsername:(NSString *)userName{
NSArray* info = [NSArray arrayWithObject: [NSMutableDictionary dictionaryWithObjectsAndKeys:
userName, #"Username",
token, #"TokenNo",
[[UIDevice currentDevice].model hasPrefix:#"iPad"] ? #"iPad" : #"iPhone", #"Device",
[UIDevice currentDevice].systemVersion, #"OSVersion",
[AppDelegate getDeviceId], #"DeviceID",
#"updateToken", #"CMD",
nil]];
[self doAction:info];
}
The doAction method just sends the data to the server and then callback the delegate, that part works fine. I can see on the server the logs of receiving this command:
"JSONCMD":"[
{ "TokenNo" : "f0d3aa21758350333b7e6315c38_EDIT_257c1838f49c43049f8380ec1ff63",
"AppVersion" : "1.0.4",
"Username" : "user#server.com",
"CMD" : "updateToken",
"OSVersion" : "7.0.4",
"DeviceID" : "9B794E11-6EF7-470C-B319-5A9FCCDAFD2B",
"Device" : "iPhone"
}
]
I see 2 possible candidates causing the strange behaviour, the NSStrings in the controller body and the static getDevice method. However, I don't see how this could work in many devices but fail in others.
I've had the same problem and I've found the solution. The Problem occurs with devices where user has the passcode set to unlock the phone. On iOS7 some code can run in the background (push notifications, background fetch) and if you save something in the keychain with standard accessibility type, you cannot read it when the device is locked (and the app is running in the background). Try to set this:
[SSKeychain setAccessibilityType:kSecAttrAccessibleAlways];
before you read/write the keychain.
Hope it helps.
NSString *retrieveuuid = [SSKeychain passwordForService:serviceName
account:identifier];
The retrieveuuid depends with the service, witch is always the same thing, but it depends also with the account. I think your problem is that one user can have multiple accounts in the same device, then your code are generating a UUID for each account.