I've read "Service Implementation Guide" from developer.apple.com and a question here from stackoverflow (on how to create a cocoa service), and followed this tutorial: http://www.cocoadev.com/index.pl?MakingServices and read http://homepage.mac.com/simx/technonova/tips/creating_a_service_for_mac_os_x.html
However, I don't seem to be able to get it working. Here's my info.plist addition:
<key>NSServices</key>
<array>
<dict>
<key>NSKeyEquivalent</key>
<dict>
<key>default</key>
<string>L</string>
</dict>
<key>NSMenuItem</key>
<dict>
<key>default</key>
<string>TESTSERVICE</string>
</dict>
<key>NSMessage</key>
<string>doCapitalizeService</string>
<key>NSPortName</key>
<string>app name</string>
<key>NSSendTypes</key>
<array>
<string>NSStringPBoardType</string>
</array>
</dict>
</array>
Where "app name" is the project and app name.
I've added an interface for handling service calls as such:
#interface my_appService : NSObject
- (void)doCapitalizeService:(NSPasteboard *)pboard
userData:(NSString *)data
error:(NSString **)error;
#end
I've registered my service as such:
my_appService *serviceObject = [[my_appService alloc] init];
[NSApp setServicesProvider:serviceObject];
In applicationDidFinishLaunching (BUT!) for the main app interface, as per the cocoadev tutorial.
I can not find my service anywhere (re)log in did not help. Am I missing something obvious here? Any tips are greatly appreciated; oh, and happy easter, everyone :)
Related
I am trying to use this example: https://github.com/Azure-Samples/active-directory-b2c-xamarin-native
It have went through the tutorial 5 times and it worked with the existing fabrikamb2c but when I try to use my own b2c tenant I get errors when clicking sign in on both iOS (Safari cannot open the page because the address in invalid) and Android (blank screen) when it calls IPublicClientApplication.AcquireTokenInteractive()
For iOS - From the PublicClientApplicationBuilder logging, it's trying to go to this url:
https://mycompany.b2clogin.com/tfp/mycompany.onmicrosoft.com/b2c_1_results_mobile_app_staging/oauth2/v2.0/authorize?scope=user.read+openid+profile+offline_access&response_type=code&client_id=xxxxxxxx-yyyy-40c1-804e-13190d66ccc6&redirect_uri=msalxxxxxxxx-yyyy-40c1-804e-13190d66ccc6:%2F%2Fauth&client-request-id=ef26ee69-9f31-4b22-943b-3d497a54e580&x-client-SKU=MSAL.Xamarin.iOS&x-client-Ver=4.25.0.0&x-client-OS=14.4&x-client-DM=iPhone&prompt=select_account&code_challenge=DfZ3m6w1WX5hE4SfzlugJNMggJrAZY3H8t288cBybk8&code_challenge_method=S256&state=cf886b1c-3353-4b05-b300-bb6e1f040b672de723bb-634e-460f-bfc5-e79698061b48
but if I use this format (updated from https://learn.microsoft.com/en-us/azure/active-directory-b2c/user-flow-overview) it works
https://mycompany.b2clogin.com/mycompany.onmicrosoft.com/oauth2/v2.0/authorize?client_id=xxxxxxxx-yyyy-40c1-804e-13190d66ccc6&redirect_uri=https%3A%2F%2Fjwt.ms&response_mode=form_post&response_type=id_token&scope=openid&nonce=dummy&state=12345&p=B2C_1_results_mobile_app_staging
I don't understand why AcquireTokenInteractive() in code is putting the userflow name (B2C_1_results_mobile_app_staging) in the path part of the url while the other one puts it as querystring parameter for p...
I have the iOS Redirect URL set up in the app registration's authentication:
and here is the userflow:
Here is my pinfo.list
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>com.yourcompany.UserDetailsClient</string>
<key>CFBundleURLSchemes</key>
<array>
<string>msalxxxxxxxx-yyyy-40c1-804e-13190d66ccc6</string>
</array>
</dict>
</array>
anyway, any guidance would be appreciated I am quite confused by all this.. been reading docs for a few days it's not "clicking" for me. thank you.
actually it was my configuration on the authentication settings on azure - I didn't have it checked. Sheesh. I knew it was something easy. I was out in the weeds with having other redirect URIs in the Android and iOS sections ...
I have created an XPC Service .
the server side code briefly is
NSXPCListener *listener = [[NSXPCListener alloc] initWithMachServiceName:#"test.xpcserver"];
listener.delegate = delegate;
[listener resume];
this is installed as a Launch Agent using info.plist as
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>TestServer</string>
<key>MachServices</key>
<dict>
<key>test.xpcserver</key>
<true/>
</dict>
<key>ProgramArguments</key>
<array>
<string>/Applications/test.app/Contents/XPCServices/xpcserver.xpc/Contents/MacOS/xpcserver</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
The server is running fine and i can see it running with launchctl list
The client side code is in another app and the code for connect is:
connection = [[NSXPCConnection alloc] initWithMachServiceName:#“test.xpcserver” options:0];
connection.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:#protocol(xpcserverprotocol)];
[connection resume];
service = [connection remoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) { }];
[service ServerFunc:#“howdy” withReply:^(NSString *result) {
NSLog(#"%#",result);
}];
but not able to connect to server .
any pointers as to what going wrong ?
It's hard to tell from what you've posted. Things to check:
ensure your listener delegate is implementing right function signature for shouldAcceptNewConnection(). If it's not right, you will not get any error. It should be
- (BOOL)listener:(NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConnection *)conn { your code here }
Use System Logging (NSLog) or add logging of stdout and stderr for your service. See the launch.sh in this hello_world_xpc example, which generates the plist based on local paths. That example is using the C API, so not exactly what you are looking for.
See old Objective-C hello.tar.gz example here : afewguyscoding.com/2012/07/ipc-easy-introducing-xpc-nsxpcconnection/
(Posting this for future readers, I imagine OP solved their problem by now :) )
Some other things to check:
Make sure your launch agent/deamon is using the -[NSXPCListener initWithMachServiceName], and not +[NSXPCListener serviceListener].
The latter is only useful for regular XPC service (which would be stored in the App's bundle, not in /Library/.... If you mix it up, you'll get a crash report in Console.app that will say:
Configuration error: Couldn't retrieve XPCService dictionary from service bundle.
In your agent/daemon, don't forget to start the main run loop after [listener resume]; with [[NSRunLoop currentRunLoop] run];
In your agent/daemon, make sure there's a strong reference to keep your listener's delegate alive. The -[NSXPCListener delegate] property is declared weak, so it's possible that your listener deallocates immediately after you set it. I would put an NSLog statement in the deinit of your delegate's class, just to be sure.
I've written a Macintosh app that handles a custom protocol:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>My Cool Handler</string>
<key>CFBundleURLSchemes</key>
<array>
<string>coolhandler</string>
</array>
</dict>
</array>
All well and good. It launches. However, I'm clicking on a link like this:
coolhandler://Iwant/toparse/this
In Windows, the registry entry is simple and this work just fine. When my Windows app launches, the whole url is passed as an argument and I can parse it.
protected override void OnStartup(StartupEventArgs e)
{
_url = !e.Args.Any()?"":e.Args[0];
//parse the url
}
Where, in my pList or in the app do I handle this? i.e, how do I pass the url argument to the app?
You'll need to do something like this in C# likely:
Accessing command line arguments in Objective-C
Which would look something like:
string[] args = NSProcessInfo.ProcessInfo.Arguments;
I’m playing with Wi-Fi Positioning system (WPS) on the Mac.
Attempting to specify the most exact positioning possible. I’ve noticed that apps such as Maps register in the Location notification of the OS
Yet my code does not seem to generate this effect,
- (void)startStandardUpdates
{
// Create the location manager if this object does not
// already have one.
if (nil == locationManager)
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
// Set a movement threshold for new events.
locationManager.distanceFilter = 1; // meters
[locationManager startUpdatingLocation];
}
Am I missing something?
Is your app sandboxed?
If it is, you need to enable the "App Data" -> "Location" entitlement in the "Capabilities" tab of your target.
Otherwise the CLLocationManager silently fails to start.
Another interesting point is, that your app only shows up in this list when the CLLocationManager is actually running. Calling stopUpdatingLocation deregisters your app from the location agent.
A minimal entitlement file for a OS X app using Core Location looks like:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.personal-information.location</key>
<true/>
</dict>
</plist>
I'm working on an Cocoa app which is launched/activated using URLs with a custom scheme which is registered in the Info.plist file like so:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>Open myscheme:// URLs</string>
<key>CFBundleURLSchemes</key>
<array>
<string>myscheme</string>
</array>
</dict>
</array>
My question is, once the app is launched or activated, how do I tell what the URL was that launched the app? On iOS, this is easy with the -application:openURL:sourceApplication:annotation: method on the UIApplicationDelegate since it is passed an NSURL instance.
I want to be able to pass in data into my app with URLs like myscheme://do/something/awesome
In your app delegate's -applicationWillFinishLaunching:, do:
[[NSAppleEventManager sharedAppleEventManager] setEventHandler:self andSelector:#selector(handleAppleEvent:withReplyEvent:) forEventClass:kInternetEventClass andEventID:kAEGetURL];
And handleAppleEvent:withReplyEvent: should look something like:
- (void)handleAppleEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent {
NSString *urlString = [[event paramDescriptorForKeyword:keyDirectObject] stringValue];
// do something with the URL string
}