There are some patterns in several API's that we might want to have some common exception types for.
Things like GPS, Cameras, Phone, SMS, etc are not always available on a given device. When a method is called which tries to make use of such a device, we should throw a consistent exception to let the developer know the feature is unsupported on the current device:
NotSupportedOnDeviceException : NotSupportedException
There may also be the case where a feature is technically supported by the device, but not enabled:
NotEnabledOnDeviceException : InvalidOperationException
Open to ideas on naming, and other common exceptions we may require...
What if you use the system exceptions as the base types:
NotSupportedOnDeviceException : NotSupportedExceptionNotEnabledOnDeviceException : InvalidOperationExceptionThe benefit of this is that it allows for some "typical" usage as well as using what the user already knows:
try {
var result = await api.DoSomethingAsync();
} catch (NotSupportedException) {
ShowAlert("This device does not do that.");
}
There is no need to force the user to use the custom exceptions, when the base, existing exception may cover more cases in one.
Yes!
I think we also need to investigate the name of the exceptions: NotSupportedOnDevice vs DeviceNotSupported vs FeatureNotSupported.
We might use capability prefix for that exceptions:
CapabilityNotSupportedException and CapabilityNotEnabledException.
@jamesmontemagno @Redth we need to properly decide what exceptions we throw in cases, and when we just do nothing.
We currently have different ways of indicating that nothing can be done:
FeatureNotSupportedExceptionPlatformNotSupportedExceptionFeatureNotEnabledExceptionOne case where we do nothing is in Android's energy saver API: if we are not Lollipop, then we just fall through:
https://github.com/xamarin/Essentials/blob/1.0.0/Xamarin.Essentials/Battery/Battery.android.cs#L12-L48
One case where we throw FeatureNotSupportedException is with the sensors: if there is no sensor X, then we throw.
One case (and the only case so far) where we throw PlatformNotSupportedException is in Android's text-to-speech API: if we try and speak, but we couldn't initialize, then we throw.
So far, I was able to determine that we throw FeatureNotSupportedException for:
message/rfc822 intent handlermailto: doesn't have an app, or if trying to send HTML over the mailto: protocolEmailManager is not available, or if trying to send HTMLtel: protocolPhoneCallManager is missingsmsto: intent handlerChatMessageManager is not availableVibrationDevice is not available or if no hardware was foundWe throw a PlatformNotSupportedException for:
We throw a FeatureNotEnabledException for:
We do "nothing":
FeatureNotEnabledException if there was no way to get the hardwareI am currently working on #178 where a variety of things can go wrong depending on the Platform. I would love to have a general PlatformException or similar to be able to throw a consistent Exception across Platforms with a corresponding inner exception for certain failures. This may be due to exceeding the recording limit on uwp or the failure to set a category for an iOS audio stream. I would love some input into what exception throwing strategy to follow there.
Most helpful comment
What if you use the system exceptions as the base types:
NotSupportedOnDeviceException : NotSupportedExceptionNotEnabledOnDeviceException : InvalidOperationExceptionThe benefit of this is that it allows for some "typical" usage as well as using what the user already knows:
There is no need to force the user to use the custom exceptions, when the base, existing exception may cover more cases in one.