AXUIElementCopyAttributeNames returns cannotComplete in Cocoa App but works well in playground - xcode

I'm trying to build an utility in navigating to any visible & enabled ui-element without mouse or trackpad, so I have to enumerate those elements first.
I did some research and found maybe Accessibility APIs would help me to reach my goal. Then I tried them in playground as below :
//...
let key: String = kAXTrustedCheckOptionPrompt.takeUnretainedValue() as String
let options = [key: true]
let enabled = AXIsProcessTrustedWithOptions(options as CFDictionary)
if !enabled {
print("Not permitted")
NSApp.terminate(nil)
}
//...
let element = AXUIElementCreateApplication(pid as! pid_t)
var ans : CFArray?
let e = AXUIElementCopyAttributeNames(element, &ans)
if e == .success, let names = ans as? [String] {
print(names)
}
//...
It works well in playground. Then I created a new Cocoa App, copied codes above into it, ran it in debug mode, and AXUIElementCopyAttributeNames return an AXError - cannotComplete.
It's very sure Xcode is enabled in System Preferences > Security and Privacy > Privacy > Accessibility. AXIsProcessTrustedWithOptions always returns true seems that it's not an issue of permission.
How can I make it works? Did I miss any necessary setting?
I'm not good in English, sorry about that.

I've solved this issue by turning off App Sandbox. I'm still curious why there is not accessibility entitlement in sandbox. Given that I have no plan to put my app in Mac App Store, to turn off App Sandbox is a solution for me.
Thanks everyone.

"With App Sandbox, you can and should enable your app for accessibility, as described in Accessibility Programming Guide for OS X. However, you cannot sandbox an assistive app such as a screen reader, and you cannot sandbox an app that controls another app."
Excerpt from https://developer.apple.com/library/archive/documentation/Security/Conceptual/AppSandboxDesignGuide/DesigningYourSandbox/DesigningYourSandbox.html
Playgrounds are not sandboxed and that is why it worked there.

Related

MacOS - requesting audio/camera permission - wrong app title shown?

We are asking for permission to use audio and camera in our Mac app. In general this works OK.
But there is one quirk. If we launch our app from another app, such as from Terminal -
When the permission prompt comes up, the app that is identifed as requesting access is the top level application ie. Terminal, not our app name.
If our app is run independently from finder (etc), the correct title shows up in the permission prompt.
I thought it might be a missing CFBundleDisplayName, but that doesn't help.
void PERMISSIONS::checkAudioPermission() const
{
if (#available(macOS 10.14, *))
{
AVAuthorizationStatus audioAuthStatus =
[AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio];
if (audioAuthStatus != AVAuthorizationStatusAuthorized)
{
// If the user has not definitively said Yes or No, ask them to do so.
if (audioAuthStatus == AVAuthorizationStatusNotDetermined)
{
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeAudio
completionHandler:^(BOOL granted)
{
if (granted)
Unfortunately, this is actually a vulnerability that Apple has never fixed, which could be exploited by malware. This is discussed by Patrick Wardle at his site:
https://objective-see.com/blog/blog_0x2F.html
Therefore, I highly encourage you to file a bug, so that this can be fixed.

AXIsProcessTrustedWithOptions doesn't return true even when the app is ticked in accessibility

As this question answered, I use AXIsProcessTrustedWithOptions with no option to test if my app has been enabled in the accessibility panel. If not, prompt the window to let users to enable it. There is button bound to this test call as well, so users don't need to close the UI and reopen it.
But sometimes, even after a user enables the app, AXIsProcessTrustedWithOptions still returns false. When I check the sqlite database, it shows my app as "kTCCServiceAccessibility|com.abc.def|0|1|1||". The first 1 digit indicates it has been allowed apparently. But the api call still returns false. At this point, if I close the UI, the app is unticked in the accessibility panel which causes a loop so users can never pass this step.
Another thing is this app is actually a version 2 of the previous app. But the user did replace the bundle with the v2 one. Not sure if this is related.
Any idea why this would happen?
NSDictionary *options = #{(id)kAXTrustedCheckOptionPrompt: #NO};
BOOL accessibilityEnabled = AXIsProcessTrustedWithOptions((CFDictionaryRef)options);
if (!accessibilityEnabled) {
NSString *urlString = #"x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility";
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:urlString]];
}
Update: In Xcode, Signing & Capabilities, make sure you have selected a Team and Signing Certificate.
Original answer:
I experienced this when developing an app on macOS 10.14.5 in Xcode trying both AXIsProcessTrusted and AXIsProcessTrustedWithOptions .
After wasting a lot of time trying all sorts of things, including different options for AXIsProcessTrustedWithOptions, logging out/in, rebooting, praying, and crying, I eventually shut down my machine and powered it back on in frustration. Then it worked. Hopefully nobody else has this same experience.

Custom URL Scheme for Settings on iOS 10?

Any Idea what happened to the Setting's Custom URL Scheme on iOS 10?
Is Apple still giving acess to third-pary apps to launch iOS Settings from the app via URL Scheme on iOS10? The Old URL scheme are not working anymore!
None of the previous methods for launching the root "Settings" app on iOS 8+ were officially supported by Apple, so unfortunately we can't rely on them. It's also possible that apps that relied on the undocumented behaviors could be rejected during App Store review, even if others have been approved--even if the same app had been previously approved!
I've been unable to discover any workaround either, so it seems your choices are:
Open the app-specific URL (as detailed in many places, including #alvin-varghese 's answer above), and then ask the user to navigate backwards. (A terrible user experience, since it involves the user knowing to scroll up from the app list into the main settings sections.)
Use an instructional screen or alert in your app to educate users on how to find it themselves. (Not much better, but at least aren't dropped into an unfamiliar context with no waypoints.)
There doesn't seem to be an officially supported way of making this happen in iOS 10, and as you pointed out, it seems like the old ways (adding prefs scheme to your Info.plist file and using openURL(_:)) do not work any more.
From iOS 10 some of the things are changed,
So, for something like bluetooth you need to write below lines of code,
Swift 3.0 :
func openBluetoothSettings(){
let urlBTSet = URL(string: "App-Prefs:root=Bluetooth")
let objApp = UIApplication.shared
objApp.openURL(urlBTSet!)
}
Objective-c
-(void) openBluetoothSettings{
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"App-Prefs:root=Bluetooth"]];
}
So, In above code what they have changed is string need to add "App-Prefs:root=Bluetooth" (This the example of opening bluetooth settings)
Don't forgot : 'Goto taget -> info -> URL Types -> Add "prefs" in URL Schemes'
Use this one, it works.
if let url = URL(string: UIApplicationOpenSettingsURLString) {
UIApplication.shared().open(url, options: [:], completionHandler: nil)
}

Lock macbook screen from a sandboxed app

I'm building a mac app that I want to distribute in the mac app store. I need this app to have a lock screen feature.
I have 2 different approaches working, the problem is, as soon as I enable sandboxing for the app (which is required for the mac app store), neither of those approaches will work.
Do you know which entitlement I need to request? Or do you know of a third approach that will work with sandboxing?
Thanks
Approach 1, using CGSession (swift):
var arguments = ["-suspend"]
var task = NSTask()
task.arguments = arguments
task.launchPath = "/System/Library/CoreServices/Menu Extras/User.menu/Contents/Resources/CGSession"
task.launch()
Approach 2, using IORequestIdle (swift):
var r = IORegistryEntryFromPath(kIOMasterPortDefault, "IOService:/IOResources/IODisplayWrangler")
if (r > 0) {
IORegistryEntrySetCFProperty(r, "IORequestIdle", kCFBooleanTrue)
IOObjectRelease(r)
}
Sorry to say it can't be done. the purpose of sandboxing is to prevent an app can take the whole computer.
You might try to get a temporary exception thru the channels documented in the sandboxing guide.

How to enable Pseudo-language on Windows Phone 8 emulator

I can't seem to enable Pseudo-language on the WP8 emulator. Most tutorials suggest to set the localization via the development operating system, and that these settings somehow "trickle down" into the emulator, but this doesn't seem to work for me -- the emulator just defaults to English no matter how I have my OS language/keyboard set (Control Panel -> Language -> Move Up <language> to top -> restart emulator).
I can change localization settings within the phone's "Settings", and although other languages successfully translate within my app, Pseudo is not an option.
I have Googled lots of MSDN information (including documentation on how to troubleshoot this specific issue) and I have seemingly exhausted my options.
tl;dr Has anyone had trouble with the "trickle down" of localization settings into the Windows Phone emulator? How do you fix it?
Here is the solution recommended by Microsoft
Thread.CurrentThread.CurrentCulture = new CultureInfo("qps-ploc");
Thread.CurrentThread.CurrentUICulture = new CultureInfo("qps-ploc");
See http://msdn.microsoft.com/en-us/library/windows/apps/jj569303.aspx
When I want to run my WP8 app in pseudo-loc, I add the following line to the beginning of App constructor:
Thread.CurrentThread.CurrentUICulture = new CultureInfo("qps-ploc");

Resources