How to access calendar in MacOS screensaver? - swift

Is it possible to access calendar events in screen saver? I am able to request permission in the application. But some API is not prompting in the case of the screensaver.
I didn't find any documentation around it.
I used the following code to requesting calendar events:
func requestPermissionForCalendar()
{
var eventStore = EKEventStore()
eventStore.requestAccess(to: EKEntityType.event) { granted, error in
if granted{
print("Permission granted")
}else{
print("The app is not permitted to access reminders, make sure to grant permission in the settings and try again")
}
}
}

Couple of things, first, a screen saver is completely passive in macOS. Any prompt for anything will be disregarded when it's running fullscreen, as a screensaver.
In general, the proper way to do this with a screensaver is to ask for permission in the configurationSheet (the screen saver options). The user will get prompted there, and can allow or deny you. I do use this for example to request the user location.
Once allowed in System Preferences, your screensaver when running in screensaver mode will get access. I suggest you test your code first in the configuration sheet as this is much easier.
Additional note, ScreenSavers on macOS since Catalina are sandboxed by an application extension provided by Apple, and that extension has a limited list of entitlements (see a list here https://github.com/glouel/ScreenSaverMinimal).
I'm not particularly familiar with EKEventStore, but if it requires a specific entitlement to make it work, you'll be stuck as you can't add any entitlement yourself, everything depends on legacyScreenSaver.appex.

Related

Hololens 2 / MRTK / Unity / Asking for permissions programmatically

Is it possible to check if app has permissions and if don't ask for permissions programmatically on Hololens 2?
In manifest permissions are already declared by sometimes if you miss the permission popup or click on NO by mistake the app doesn't ask for permission never again.
Unity 2020.3.13f1
MRTK 2.7.3
- Update -
I asked for this feature here:
https://github.com/microsoft/MixedRealityToolkit-Unity/issues/10675
Please support the request!
To check Microphone and Camera permissions on HoloLens 2, we can take advantage of WinRT API MediaCapture. If the app does not have Microphone and Camera permissions, when calling the InitializeAsync method, it will throw a UnauthorizedAccessException.
If we got this exception, there is no way to re-ask for permission programmatically. We should let the user to grant us the required permissions again in Settings with using the ms-settings:appsfeatures-app URI, which can open the advanced settings page for our app.
#if ENABLE_WINMD_SUPPORT
using (MediaCapture mediaCapture = new MediaCapture())
try
{
await mediaCapture.InitializeAsync();
}
catch (UnauthorizedAccessException)
{
await Windows.System.Launcher.LaunchUriAsync(new Uri("ms-settings:appsfeatures-app"));
}
#endif
Another way to check the permissions would be using AppCapability Class. CheckAccess method will return the access status. If the status is DeniedByUser, we will still need to open the advanced settings page for our app using the ms-settings:appsfeatures-app URI and let the user to grant us the required permissions.

How to solve Swift FileManager couldn’t open file because of permission and implement file access

I made a music app for macOS that need the access of the file on disk. I can get the proper url, but I can't access the file. To figure out that problem, here I create a concise code snippet to concentrate on the question itself.
.onAppear {
var url = FileManager.default.homeDirectoryForCurrentUser
url.appendPathComponent("Downloads/Test.txt")
var text: String = ""
do {
text = try String(contentsOf: url)
} catch {
print("ERROR: \(error.localizedDescription)")
}
}
The output would be like this
ERROR: The file “Test.txt” couldn’t be opened because you don’t have permission to view it.. So I noticed App Sandbox in Targets > Signing & Capabilities. But at the list of file access (as you can see in the following picture), there's only User Selected File, Downloads Folder, Pictures Folder, Music Folder and Movie Folder. So I come up with 3 questions:
What that User Selected File means? Is that means that the user can select some specific file for my app to access? If it is, how can user selects them?
How can I get access to other folders like Desktop Folder if I remain the App Sandbox capability here?
I also noticed the trash icon on right-upper corner. If I delete App Sandbox, I can access every folder I want with the user's agreement by a default system pop-up. But what the deletion of App Sandbox means? Does it make my app "untrusted" somehow when user install it or others? Does it cause any security problems?
And It couldn't be better if you can tell me the conventions major developers follow when meet this problem. I would highly appreciate your help.

Swift how to set manually photoLibrary and camera authorization?

When using my app, the user is asked permission to access camera and library one time (when needed), answering allow or not in the "apple alert" (requestAccess).
I need to add a view where the user can be able to change these authorizations afterwards if he wants. I added switch buttons so the user can make the choice to keep it authorized or not. But I can't find how to set the authorizationStatus.
Is there a way to change the authorizationStatus manually, from .authorized to .denied or opposite ?
I tried to prompt the apple alert using 'AVCaptureDevice.requestAccess()' but it doesn't show if the user already authorized before.
Any suggestion welcome :)
By security and privacy reasons developers have only one way - use system dialog for requesting authorization for access to protected system services.
But you can suggest for your users a short way to system settings. This code launches the Settings app and displays your app’s custom settings.
let settingUrl = URL(string: UIApplication.openSettingsURLString)
DispatchQueue.main.async {
UIApplication.shared.open(settingUrl!, options: [:], completionHandler: nil)
}

Checking for Privacy - Photo Library Additions Usage Description only in iOS

My app only needs the 'Privacy - Photo Library Additions Usage Description' property in the plist file (app writes to Photo library, but doesn't read).
I use this code to check for permissions:
PHPhotoLibrary.requestAuthorization { status in
if status == .authorized {
print("Permission granted")
} else {
print("Unavailable")
}
}
In the iOS Settings for my app, even though the plist only needs 'Add Photos Only', 'Read and Write' is also listed (??), and the above code only gets the authorised status if 'Read and Write' is ticked (ticking 'Add Photos Only' just causes the above code to go through to the else statement).
I'm a bit confused to why 'Read & Write' is even listed as a setting for my app, when my plist doesn't include "Privacy - Photo Library Usage Description".
Any ideas?
It's because you are calling PHPhotoLibrary.requestAuthorization.
If all you need is to write blindly into the user's camera roll, do not call PHPhotoLibrary.requestAuthorization. Just go ahead and write, e.g. by calling UIImageWriteToSavedPhotosAlbum or UISaveVideoAtPathToSavedPhotosAlbum. The runtime will request authorization on your behalf.
But if you want to interact with the photo library itself, i.e. thru the Photos framework, then you need authorization and an entry under Privacy - Photo Library Usage Description, even if all you intend to do is write.
Judging by your comments, you may be confused about what requestAuthorization does. It tries to obtain permission. If all you want to know is what the current authorization status actually is, call authorizationStatus instead.
However, even then, we're talking about the photo library itself, and thus the value referred to as Read & Write in Settings.
If you want to know whether you have permission to do UIImageWriteToSavedPhotosAlbum or UISaveVideoAtPathToSavedPhotosAlbum, just go ahead and call it. If there's a permissions problem, you'll hear about it in the completion handler.

Azure mobile facebook authentication with iPhone HTML5 in app (full screen) mode

I have an HTML5 application that uses Azure mobile services authentication to login (straight from the example code...provided below). It works fine in all desktop browsers and iPhone 5 in Safari. But from app / full screen mode, it does nothing (doesn't ask for permission to show a popup window like it does in safari and no popup windows shows up) and I can wait forever and nothing happens. If I invoke it a second time, it gives an error saying "Error: Unexpected failure"...perhaps because the 1st attempt is still running? Any help/insight is appreciated.
client.login ("facebook").done(function (results) {
alert("You are now logged in as: " + results.userId);
}, function (err) {
alert("Error: " + err);
});
edited update with more info and 2 potential ideas*
I did some more research and found a site that uses an approach that overcomes this problem and also solves two other side effects with the current Azure mobile approach to authentication. I think the Azure mobile team might be looking to do something similar because there are some hints of other authentication options in the code (although difficult to read and be sure because the minimized code is obsfucated). It might be just a matter of activating these in the code...
The "solution":
Go to http://m.bcwars.com/ and click on the Facebook login. You'll see it works perfectly in iPhone Safari in "app mode" becuase instead of doing a popup, it simply stays in the current browser window.
This approach solves two other problems with the current Azure mobile approach. First, the popup gets interpreted by most browsers as a potential ad and is either blocked automatically (desktop Chrome) ... and the user doesn't know why it's not working...or gives a warning which the user has to approve (iPhone Safari in "browser mode") which is a hassle. And if the user has a popup blocker, it gets more difficult and even more potential for the user not getting it to work properly. The bcwars.com method doesn't have this problem.
Second, in iPhone Safari, when the popup window auto closes, the original page doesn't get focus if there are other browser windows open in Safari. Instead, it's in the smaller/slide mode so they can choose which one to show. If this happens, the user has to go through one more sttep...click on the browser window to activate it and give it focus..again more of a pain and more potential for them to mess up and not do it correctly and need help. The m.bcwars.com doesn't have this problem.
Azure options:
Looking at the Azure mobile code it looks like may already have the solution. I can't read it easliy becuase it's minified/obsfucated, but it seems to have 4 options (including iFrame, etc.) for invoking the authentication, and only 1 (the "less ideal one" of a popup) is being used. An easy solution would be to set a property to allow one of the alternate authentications to work. But I can't read it well enough to figure it out. Another would be to hack the code (temporarily until a fix is put up by Microsoft).
Could I get some help there perhaps?
You can implement an authentication flow with Facebook that doesn't use a popup. The basic idea is to use the 'Web Flow' for doing the login, and once the window return from the login, use the access token to login the user in to Azure Mobile Services.
The Facebook documentation for doing this is here:
https://developers.facebook.com/docs/facebook-login/login-flow-for-web-no-jssdk/#step2
Some code samples to make it easier for you.
You would start by something like this:
(Remember to replace YOUR_APP_ID and YOUR_URL with something relevant to your site.
function logIn() {
window.location.replace('https://www.facebook.com/dialog/oauth?client_id=YOUR_APP_ID&redirect_uri=http%3A%2F%2FYOUR_URL&response_type=token')
}
This redirects the window to the Facebook page for the user to log in and authorize your app. When the user is done, Facebook will redirect the user back to YOUR_URL given above.
There you can handle the redirect and do the Mobile Services Login with something like this:
function handleLoginResponse() {
var frag = $.deparam.fragment();
if (frag.hasOwnProperty("access_token")) {
client.login("facebook", { access_token: frag.access_token }).then(function () {
// you're logged in
}, function (error) {
alert(error);
});
}
}
In here you parse the access token you get as a URL fragment and pass it as argument to the login call you make to Azure Mobile Services.
This code depends on the jquery BBQ plugin to handle the URL fragment easily.
Hope this solves your problem!