Some platforms will require some sort of initialization or otherwise platform specific calls. This is the area they should be dealt with.
public static class Platform
{
internal static Activity CurrentActivity { get; }
internal static Context CurrentContext { get; }
// Should be called from the MainActivity in general
public static void Init (Activity activity, Bundle bundle);
// Should be called from the activity where permission requests occurred
public static void OnRequestPermissionsResult (int requestCode, string[] permissions, Permission[] grantResults);
}
Should this type be a static type? Or at least have a private constructor so that it cannot be instantiated?
Something that we should consider is to keep all the platform stuff together. One example that comes to mind is #28. The MapKey exists there, should it exist here rather?
We could also do something like this:
static class Platform {
// ANDROID
public static void Init (Activity activity, Bundle bundle);
// UWP
static class Geolocator {
static string MapKey;
}
// IOS
static class Email {
// something for iOS only
}
}
This way keeps all the Platform things in the Platform type, but grouped under a nested class that matches the API name. This may get messy, but keeps everything together.
This will also fit in with #14.
Another way would be to use a "settings" class:
static class Platform {
PlatformConfiguration Configuration { get; set; }
// OR
void SetConfiguration(PlatformConfiguration config);
}
class PlatformConfiguration {
#if ANDROID
// this could be used as part of the init...
Application CurrentApplication { get; set; }
#endif
#if UWP
static string MapKey { get; set; }
#endif
#if IOS
// something for iOS only
#endif
}
Here's another idea... What about a configuration file convention for these types of things? Can we have a Caboodle.config type file here?
That is a good idea, but we do need to support the case where the value is calculated or generated. Also, how are we could to build this in? As an embedded resource?
For an interim solution, we could create the configuration class - the type that will be used to deserialize the config. This way the user can configure the library from the platform projects as part of the Init (or a separate SetConfig method).
@jamesmontemagno had an idea:
static class Capabilities {
static bool HasTelephony { get; }
}
Usage:
if (Capabilities.HasTelephony) {
Dialer.Open(...);
}
This is a good idea, but the more I see all this (capabilities, platform-specifics, configuration), I am thinking this is going to make life complicated both for us and the users:
If I have to go to a Platform API to set the map key and then load the address from the Geocoder API, or, if I have to go to the Capabilities API to check if I can make a call, and then go to the Dialer API - I am all over the place, who is to say that HasTelephony goes with Dialer.Open.
I am beginning to think that we should stick to the old plan of Dialer.IsSupported and Dialer.Open, and, Geocoder.MapKey and Geocoder.GetAddressAsync.
But there is a flip side, what if two APIs need a MapKey, we now end up with two properties with the same value on two APIs.
There are advantages and disadvantages to both plans...
I think Capabilities is a great place to check what our device can do.
who is to say that HasTelephony goes with Dialer.Open
Yeah, that's tricky. I think it's very helpful to have IsSupported (if needed) for every API and handle it in this way:
class Dialer
{
bool IsSupported => Capabilities.HasTelephony;
}
So if user wants just to check for some capability - Capabilities is his choice.
I guess I'm thinking of how I would do it on Android. Which is to check capabilities. On iOS I guess it is more of the API knows or has a check.
I think having it in both places is fine - I think I like it more as the dev has the choice of code preferences.
;)
I'm still wary of two things:
IsSupported being a boolThe second one I am most unconvinced about. Having multiple ways to do the same thing in code is going to introduce more regression/failure points, complicate documentation, and raise the level of confusion for developers (I can already see code like this happening: if (Capabilities.HasTelephony && PhoneDialer.IsSupported) {). I think we should (at _least for now_) only have a single API for checking this functionality.
Most helpful comment
Here's another idea... What about a configuration file convention for these types of things? Can we have a Caboodle.config type file here?