Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
972 views
in Technique[技术] by (71.8m points)

ios - Finding out if the device is locked, from a Notification Widget

I'd like to know if the device is locked when I'm loading my Notification/Today widget, so I can show the widget appropriately. (it's financial, and we don't want to show balances on a locked phone)

On devices with TouchID, I can just try to access the Keychain, and if I get

errSecInteractionNotAllowed

back, it's locked. All good. This doesn't work on devices without touchID (but with a PIN). I've found a few things, which recommend using

[[UIApplication sharedApplication] protectedDataAvailable]

However I don't have [UIApplication sharedApplication] in a widget.

Any ideas where and how to do this? I just need a yes/no: is the device locked.

Thanks

[UPDATE: here's the code I have]

Getting the filename:

+ (NSString *)lockedDeviceFilename {
    NSURL *directoryUrl = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:USER_DEFAULTS_GROUP_NAME];
   return [directoryUrl.path stringByAppendingPathComponent:@"security.dummy"];
}

Writing / creating the file (in the app, not the extension:

NSError *error = nil;

NSString *documentPath = [FOOStorageGatekeeper lockedDeviceFilename];

[[NSFileManager defaultManager] removeItemAtPath:documentPath error:&error];

BOOL created = [[NSFileManager defaultManager] createFileAtPath:documentPath
                                                       contents:[@"super secret file contents. we only care about the permissions" dataUsingEncoding:NSUTF8StringEncoding]
                                                     attributes:@{NSFileProtectionKey : NSFileProtectionComplete}];

Reading:

 BOOL isReadable = [[NSFileManager defaultManager] fileExistsAtPath:[FOOStorageGatekeeper lockedDeviceFilename]];

  NSLog(@"isReadable? %@", isReadable ? @"YES" : @"NO");

It's always able to read the file, even on a TouchID device with the screen locked. If I look at the attributes, it shows the NSFileProtectionKey is set to NSFileProtectionComplete... but I can STILL READ IT :(

Update: found it. Marking Ian's answer as correct

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Create a file with NSFileProtectionComplete while your app is running and then attempt to access it from your extension. If you can't access it, the screen is locked.

[[NSFileManager defaultManager] createFileAtPath:someFilePath
                                        contents:[@"Lock screen test." dataUsingEncoding:NSUTF8StringEncoding]
                                      attributes:@{NSFileProtectionKey: NSFileProtectionComplete}];

EDIT: Final steps included to complete solution and consolidate answers. (Remaining work provided by Nic Wise.)

NSData *data = [NSData dataWithContentsOfURL:[FOOStorageGatekeeper lockedDeviceUrl] options: NSDataReadingMappedIfSafe error:&error];

if (error != nil && error.code == 257) {
    NSLog(@"**** the keychain appears to be locked, using the file method");
    return YES;
}

The other method, using errSecInteractionNotAllowed also works, but only for TouchID devices.

I found the answer (indirectly) here (rego with the iOS dev program most likely needed)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...