macOS Accessibility Inspector does not work with Slack - macos

When I'm using macOS's Accessibility Inspector on apps like notes and Apple mail, I get all the window's children elements. If I use the Inspector on Slack, though, I only get the window and nothing of the content.
Is there a way to force slack to expose its children to the inspector somehow?
Same goes for WhatsApp Web and the Apple Pages Canvas.

Found the answer here https://www.electronjs.org/docs/latest/tutorial/accessibility#macos
The AXManualAccessibility Attribute of the App must be set to kCFBooleanTrue.
This is how it's done:
Get the process ID of the current app
Create an AXUIElement from the app using the process ID
Set the AXManualAccessibility of the newly created AXUIElement to kCFBooleanTrue
Now all elements of the App are inspectable using the Accessibility manager. This not only works for all electron apps, but also apps like Pages or MS Word.
Swift
let kAXManualAccessibility: CFString = "AXManualAccessibility" as CFString;
private func enableAccessibility() {
guard let processIdentifier = NSWorkspace.shared.frontmostApplication?.processIdentifier else { return }
let appRef = AXUIElementCreateApplication(processIdentifier)
AXUIElementSetAttributeValue(appRef, kAXManualAccessibility, kCFBooleanTrue)
}
Objective C
CFStringRef kAXManualAccessibility = CFSTR("AXManualAccessibility");
+ (void)enableAccessibility:(BOOL)enable inElectronApplication:(NSRunningApplication *)app
{
AXUIElementRef appRef = AXUIElementCreateApplication(app.processIdentifier);
if (appRef == nil) return;
CFBooleanRef value = enable ? kCFBooleanTrue : kCFBooleanFalse;
AXUIElementSetAttributeValue(appRef, kAXManualAccessibility, value);
CFRelease(appRef);
}

Related

Properly implement In-App Updates in App Center?

I am reading this documentation/article from Microsoft on how to Distribute Mobile apps with app center. The problem is I really don't understand how to implement this. I have a app on app center (Android) I want to implement mandatory update so that I can eliminate the bugs of the previous version. I tried to distribute the app with mandatory update enabled and it is not working. How can I fix this?
https://learn.microsoft.com/en-us/appcenter/distribution/
Here is what I did I added this code on my App.xaml.cs (XAMARIN FORMS PROJECT):
protected override void OnStart ()
{
AppCenter.Start("android={Secret Code};", typeof(Analytics), typeof(Crashes), typeof(Distribute));
Analytics.SetEnabledAsync(true);
Distribute.SetEnabledAsync(true);
Distribute.ReleaseAvailable = OnReleaseAvailable;
}
bool OnReleaseAvailable(ReleaseDetails releaseDetails)
{
string versionName = releaseDetails.ShortVersion;
string versionCodeOrBuildNumber = releaseDetails.Version;
string releaseNotes = releaseDetails.ReleaseNotes;
Uri releaseNotesUrl = releaseDetails.ReleaseNotesUrl;
var title = "Version " + versionName + " available!";
Task answer;
if (releaseDetails.MandatoryUpdate)
{
answer = Current.MainPage.DisplayAlert(title, releaseNotes, "Download and Install");
}
else
{
answer = Current.MainPage.DisplayAlert(title, releaseNotes, "Download and Install", "Ask Later");
}
answer.ContinueWith((task) =>
{
if (releaseDetails.MandatoryUpdate || (task as Task<bool>).Result)
{
Distribute.NotifyUpdateAction(UpdateAction.Update);
}
else
{
Distribute.NotifyUpdateAction(UpdateAction.Postpone);
}
});
return true;
}
And here is what I added on my MainActivity.cs(ANDROID PROJECT):
AppCenter.Start("{Secret Code}", typeof(Analytics), typeof(Crashes), typeof(Distribute));
Looking at this App Center documentation here for Xamarin Forms -
You can customize the default update dialog's appearance by implementing the ReleaseAvailable callback. You need to register the callback before calling AppCenter.Start
It looks like you need to swap your current ordering to get in-app updates working.
There could be a lot of different reasons as to why they are not working. As you can see in the Notes here and here,
Did your testers download the app from the default browser?
Are cookies enabled for the browser in their settings?
Another important point you'll read in the links, is that the feature is only available for listed distribution group users. It is not for all your members. You could use a simple version checker for your purpose instead or you could use a plugin.

Is it possible to launch native apps using Microsoft bot framework?

I am creating a Cortana skill on the Cortana canvas, I have a button.
I wanted to know if it possible to have an 'imback' type of button to open a webpage.
Ye, for example
var message = context.MakeMessage() as IMessageActivity;
message.ChannelData = JObject.FromObject(new
{
action = new { type = "LaunchUri", uri = "skype:echo123?call" }
});
await context.PostAsync(message);
this code will start a call with echo123 user on skype
Reference: https://learn.microsoft.com/en-us/cortana/tutorials/bot-skills/bot-entity-channel-data
You can supply an openUrl to a card action, or even use ChannelData to send a LaunchUri command, deep linking to an application. (I haven't tried this, but I assume 'http://websitename.com' will launch in the Cortana host platform's default browser.)
activity.ChannelData = new {
action = new { type = "LaunchUri", uri = "http://websitename.com"}
};

xamarin ios 10 open app store application programmatically in my app

i'm trying to open app store application programmatically in my app.
what i'm trying to do is that i'm calling a service to check at the current app version and if it needs update i should open app store application to let the user update the my app.
note: the app not published yet to the store, i'm still in coding phase.
i tried to use the following code in ViewDidLoad method, but it's not working (nothing happened):
var nsurl = new NSUrl("itms://itunes.apple.com");
UIApplication.SharedApplication.OpenUrl(nsurl);
A direct link via itms: will only work in an actual device, if you are testing on a simulator, use https://itunes.apple.com/us/genre/ios/id36?mt=8 instead.
I would recommend using itms:// link on the actual device as it prevents the redirects that user sees when using a https:// link to open iTunes.
bool isSimulator = Runtime.Arch == Arch.SIMULATOR;
NSUrl itunesLink;
if (isSimulator)
{
itunesLink = new NSUrl("https://itunes.apple.com/us/genre/ios/id36?mt=8");
}
else
{
itunesLink = new NSUrl("itms://itunes.apple.com");
}
UIApplication.SharedApplication.OpenUrl(itunesLink, new NSDictionary() { }, null);
Instead of opening the external Store app on the device, you might want to consider keeping the user inside of your app by using a SKStoreProductViewController:
bool isSimulator = Runtime.Arch == Arch.SIMULATOR;
if (!isSimulator)
{
var storeViewController = new SKStoreProductViewController();
storeViewController.Delegate = this;
var id = SKStoreProductParameterKey.ITunesItemIdentifier;
var productDictionaryKeys = new NSDictionary("SKStoreProductParameterITunesItemIdentifier", 123456789);
var parameters = new StoreProductParameters(productDictionaryKeys);
storeViewController.LoadProduct(parameters, (bool loaded, NSError error) =>
{
if ((error == null) && loaded)
{
this.PresentViewController(storeViewController, true, () =>
{
Console.WriteLine("SKStoreProductViewController Completed");
});
}
if (error != null)
{
throw new NSErrorException(error);
}
});
}
else
{
var itunesLink = new NSUrl("https://itunes.apple.com/us/genre/ios/id36?mt=8");
UIApplication.SharedApplication.OpenUrl(itunesLink, new NSDictionary() { }, null);
}
NSBundle.MainBundle.InfoDictionary["CFBundleVersion"]
Returns you the current app version.
To open the Apple Appstore just let the user navigate to the appstore link, Apple will automaticly detect that the user is using an iPhone and will open the Appstore for them.
Test yourself:
Open the following link in safari: Whatsapp in the Appstore
It will automatically open the appstore.
When you create app on iTunesConnect you can get url to your future app in AppStore even if you didn't release it yet. You can find it under App Information tab:
In your app you can just open it:
var nsurl = new NSUrl("https://itunes.apple.com/us/app/mygreatapp/id123456789");
UIApplication.SharedApplication.OpenUrl(nsurl);

Facebook SDK inside iOS app extension cannot find logged in user?

I've created a sample app Share extension. Followed the Apple guides, which means my project consists of a main app and a "share extension" target.
I've setup my Facebook SDK inside the main app, since the app's settings has some FB login/status functionality. It works well according to expectation: users can login and do some shares.
But I also want the logged-in user to be available to the extension target itself. When my extension comes up (in any app), I check Facebook's login status in viewDidLoad:, and it outputs "not logged in":
if ([FBSDKAccessToken currentAccessToken]) {
NSLog(#"logged in");
} else {
NSLog(#"not logged in");
}
The same code outputs "logged in" if called from within the main app. I suspect it has something to do with the fact that the extension target has a different bundle ID that looks like this: .suffix and I guess FB SDK is trying to read the user ID off the keychain cache, but maybe it's reading it off the wrong keychain due to the different bundle IDs... But it could be other reasons as well I guess.
Any idea how to keep Facebook SDK "logged in" inside the extension after the login itself occurred in the containing main app?
I have the exact same problem, as I develop a Message Extension App with a Facebook Login.
To solve the problem, I put the Login Button in the App and use the shared UserDefaults (with a group name) to store a property :
/*
* Get / sets if is FB connected (because we can't use FB SDK in Extension)
*/
public var isFacebookConnected : Bool {
get {
// Getting Bool from Shared UserDefaults
let defaults : NSUserDefaults = NSUserDefaults.init(suiteName: "MY_GROUP_NAME")!
let isFBConnected : Bool? = defaults.boolForKey("IsFacebookConnected")
if isFBConnected == nil {
return false
} else {
return isFBConnected!
}
}
set {
// Setting in UserDefaults
let defaults : NSUserDefaults = NSUserDefaults.init(suiteName: "MY_GROUP_NAME")!
defaults.setBool(newValue, forKey: "IsFacebookConnected")
defaults.synchronize()
}
}
This property is accessed from the App or from the Extension.
Then, in my Login / Logout methods I add :
//FBLogin
func loginButton(loginButton: FBSDKLoginButton!, didCompleteWithResult result: FBSDKLoginManagerLoginResult!, error: NSError!) {
if let error = error {
print(error.localizedDescription)
return
}
if result.isCancelled
{
return
}
// Set in Shared UserDefaults if connected / not connected
ConfigManager.sharedInstance.isFacebookConnected = true
...
}
func loginButtonDidLogOut(loginButton: FBSDKLoginButton!) {
// OK, keeping track
ConfigManager.sharedInstance.isFacebookConnected = false
}
Then, I keep track of my flag when login / logout.
Warning : this method is not bullet proof as I can't know if Facebook has been uninstalled, but it is robust enough for me.
I believe you'll need to take advantage of Keychain sharing capability in the app and extension to solve this.
https://developer.apple.com/documentation/security/keychain_services/keychain_items/sharing_access_to_keychain_items_among_a_collection_of_apps

How to start the app that is associated to the IBackgroundTask I've created in UWP Windows 10

I implemented an IBackgroundTask on Universal Windows 10 and it works like a charm but the problem is that i want to start the app that is associated to that background task if some action occurs. The code is simple:
public sealed class AdvertisementWatcherTask : IBackgroundTask
{
private IBackgroundTaskInstance backgroundTaskInstance;
public void Run(IBackgroundTaskInstance taskInstance)
{
backgroundTaskInstance = taskInstance;
var details = taskInstance.TriggerDetails as BluetoothLEAdvertisementWatcherTriggerDetails;
if (details != null)
{
//Do things
}
}
}
I've seen that you can create a ToastNotification like that:
Windows.Data.Xml.Dom.XmlDocument toastXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText01);
Windows.Data.Xml.Dom.XmlNodeList elements = toastXml.GetElementsByTagName("text");
foreach (IXmlNode node in elements)
{
node.InnerText = taskInstance.Task.Name+ " remember to uninstall task if not debugging";
}
ToastNotification notification = new ToastNotification(toastXml);
ToastNotificationManager.CreateToastNotifier().Show(notification);
The notification toast works good. It creates and prompts a notification and if you click it, the app that created this background task starts. This is the behaviour that I want but I want to start the app without having to click any notification. Is there any way to achieve this? Thank you.
TL;DR: I want to start the app that created the background task at some point of the code.
You can not programmatically launch URI or open app from background task. You can however display a reminder or toast notification to let user open your app.

Resources