I have a page where I display all sorts of info and I would like to display either the android Sdk used or the iOS version used
How can I retrieve those in xamarin forms? Looked at xamarin essentials but cannot find it.
Result wanted
Android Sdk
29 (10)
ioS
14
Hope makes sense
thanks
You can get via Dependency Service. Create Interface in shared project and then implement this interface in platform specific projects.
Shared Project
public interface IDeviceInfo
{
string GetOSVersion();
}
iOS Project
[assembly: Dependency(typeof(DeviceInfo_iOS))]
namespace App1.iOS
{
public class DeviceInfo_iOS : IDeviceInfo
{
public string GetOSVersion()
{
return UIDevice.CurrentDevice.SystemVersion;
}
}
}
Android Project
[assembly: Dependency(typeof(DeviceInfo_Android))]
namespace App1.Droid
{
public class DeviceInfo_Android : IDeviceInfo
{
public string GetOSVersion()
{
return "Android Sdk " + (int)Build.VERSION.SdkInt +" (" + Build.VERSION.Release +")";
}
}
}
Call the DependencyService in Shared Project
var version = DependencyService.Get<IDeviceInfo>().GetOSVersion();
Related
I am trying to create a plugin using .Net Maui class libraries that use native Android and iOS code. I tried using the Dependency Service using the Interface, but I get a null point when I try to Register the Interface.
Shared code
public class MyPlugin
{
public static DisplayModel()
{
IDeviceOrientationService service =
DependencyService.Get<IMyPlugin>();
var model = service.GetDeviceName();
}
}
public Interface IMyPlugin
{
string GetDeviceName();
}
Android platform
[assembly: Dependency(typeof(MyPlugin))]
public class MyPlugin:IMyPlugin
{
public string GetDeviceName
{
return "From Android";
}
}
This is just an example. Please help me understand if I am not going about this the correct way and any suggestion would be appreciated.
Within my Blazor app, I am trying to determine the amount of available storage of the Android or iOS device.
I have found an answer here that is relevant:
Can I check available storage in the Device on Xamarin Forms?
As per the accepted answer, I have implemented the following:
Defined the Interface in the Blazor project
public interface IStorage
{
double GetRemainingStorage();
}
Created a class in the Android project
[assembly: Xamarin.Forms.Dependency(typeof(AndroidStorageManager))]
namespace MyApp.Android
{
public class AndroidStorageManager : IStorage
{
public double GetRemainingStorage()
{
var freeSpace = Android.OS.Environment.ExternalStorageDirectory.UsableSpace;
return freeSpace;
}
}
}
Created a class in the iOS project
[assembly: Xamarin.Forms.Dependency(typeof(iOSStorageManager))]
namespace MyApp.iOS
{
public class iOSStorageManager : IStorage
{
public double GetRemainingStorage()
{
var freeSpace = NSFileManager.DefaultManager.GetFileSystemAttributes(Environment.GetFolderPath(Environment.SpecialFolder.Personal)).FreeSize;
return freeSpace;
}
}
}
The Issue
Despite the definition of the dependencies with the [assembly: attribute, when my Blazor app tries to inject an instance of IStorage, it throws an exception:
Unable to resolve service for type 'IStorage' ...
Of course, I'm not able to define the dependency injection for IService in the Blazor app on startup, since the AndroidStorageManager and iOSStorageManager are defined in the device-specific projects which are already referencing the Blazor app.
I suspect I need some other way of defining the DI for IService in the Android and iOS apps, but can't see how to do it.
Can anyone offer any advice?
I seem to have found a workaround for my immediate issue, but I'm sure there must be a more elegant solution.
The exception was being generated when trying to inject an instance of the class associated with the IStorage interface.
public class MyManager {
private IStorage _storage;
public MyManager(IStorage storage) {
_storage = storage;
}
...
}
Rather then relying on the Blazor DI to resolve this dependency, I was able to use Xamarin.Forms DI to inject an instance manually, as follows:
public class MyManager {
private IStorage _storage;
public MyManager() {
_storage = DependencyService.Get<IStorage>();
}
...
}
I'm assuming that my original code wasn't working because Xamarin.Forms and Blazor are not sharing the same DI container. I'm not sure.
I'd be interested in anyone that can suggest a more elegant solution.
I created a cross platform application using Xamarin. I need to call native functions of iOS and Android platform in my project. Here is the code:
private static Func<IDownloadFile, string> _downloadPath = new Func<IDownloadFile, string>(file =>
{
if (Device.RuntimePlatform == Device.iOS)
{
string fileName = (new NSUrl(file.Url, false)).LastPathComponent;
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), fileName);
}
else if (Device.RuntimePlatform == Device.Android)
{
string fileName = Android.Net.Uri.Parse(file.Url).Path.Split('/').Last();
return Path.Combine(Android.App.Application.Context.GetExternalFilesDir(Android.OS.Environment.DirectoryDownloads).AbsolutePath, fileName);
}
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "");
});
This is the code from notification plugin https://github.com/thudugala/Plugin.LocalNotification.
The problem is when I use that code the Mono.Android and Xamarin.iOS references are being added to my shared project in Dependencies/Assemblies and then when I try to run application in the release mode there is a reference error - I noticed that in my Android project in bin/Release there is Xamarin.iOS reference but there is no reference in Android project. When I remove that reference from Dependencies/Assemblies and comment native calls in my code everything compiles correctly. I am confused because of this. Is my above code correctly or I need to call native functions in another way?
When using .net Standard the approach taken is using an interface that defines the functionality you want to expose then implement in each platform.
In Shared:
public interface IMyInterface
{
string GetUrlPath(string fileUrl);
}
iOS Implementation:
public class MyClass : IMyInterface
{
public string GetUrlPath(string fileUrl)
{
string fileName = (new NSUrl(file.Url, false)).LastPathComponent;
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), fileName);
}
}
Android Implementation:
public class MyClass : IMyInterface
{
public string GetUrlPath(string fileUrl)
{
string fileName = (new NSUrl(file.Url, false)).LastPathComponent;
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), fileName);
}
}
Then using either Xamarin.Forms DependencyService or any other IoC container you can match the Interface with the correct implementation.
In your shared code you will use the Interface and the implementation picked will be transparent.
This post shows a very complete example of how to do it.
I'm working on a Xamarin Forms app and am trying to open the the default mail client directly to the Inbox.
I'm able to open and pass data through to compose a message using XF Essentials
Email.ComposeAsync(message);
But I would like the app to open the default mail app's Inbox on a button press. Is this possible in Xamarin Forms?
I think Dependency Service is what you need.
Create an interface in your Forms project:
public interface IOpenManager
{
void openMail();
}
Then implement it on each platform, for iOS:
[assembly: Dependency(typeof(OpenImplementation))]
namespace Demo.iOS
{
public class OpenImplementation : IOpenManager
{
public void openMail()
{
NSUrl mailUrl = new NSUrl("message://");
if (UIApplication.SharedApplication.CanOpenUrl(mailUrl))
{
UIApplication.SharedApplication.OpenUrl(mailUrl);
}
}
}
}
For Android:
[assembly: Dependency(typeof(OpenImplementation))]
namespace Demo.Droid
{
public class OpenImplementation : IOpenManager
{
public void openMail()
{
Intent intent = new Intent(Intent.ActionMain);
intent.AddCategory(Intent.CategoryAppEmail);
Android.App.Application.Context.StartActivity(intent);
}
}
}
At last, call this dependcy via: DependencyService.Get<IOpenManager>().openMail();
Everyone.
I am using SqLite in Xamarin Forms. For that I am using SqLite - PCL nuget. Now the problem is, It works fine in Android. But in UWP I can't Access database file.
I am using Common code for both Platforms. It is as below :
database = new SQLiteConnection(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "mydb.db"));
database.CreateTable<Item>();
The error I am getting in UWP app only.
Thank You.
the docs contain clear instructions on how to do this in UWP
using Windows.Storage;
...
[assembly: Dependency(typeof(FileHelper))]
namespace Todo.UWP
{
public class FileHelper : IFileHelper
{
public string GetLocalFilePath(string filename)
{
return Path.Combine(ApplicationData.Current.LocalFolder.Path, filename);
}
}
}