I am working on an app where I want users to get images from web service but don't want them to be stored locally in localdb or local files.
Is there a way to do it?
I am using Xamarin forms.But if it can be done natively it can also be done through xamarin forms.
You can always download the image as a file using a webclient and then an StreamImageSource.
First, you need an interface for a dependency service (I prefer to use WebClient than any third party library so I use these services, feel free to use anything else if you like it, just skip the service part) created on the Forms project:
public interface IDownloader
{
byte[] Download(string Url);
}
Then, you need a dependency service on the Android project:
[assembly: Dependency ( typeof (--yournamespace--.Downloader))]
public class Downloader : IDownloader
{
public byte[] Download(string Url)
{
//This code is synchronous, I would recommend to do it asynchronously
WebClient wc = new WebClient();
return wc.DownloadData(Url);
}
}
And then you can download the image and set it as source:
//I assume there exist an image control called img.
var dl = DependencyService.Get<IDownloader> ();
byte[] data = dl.Download(--url to the image--);
var ms = new MemoryStream(data);
img.Source = new StreamImageSource{ Source = (t) => ms };
You don't mention if you're online or not - if you're online you can just use a URL in the XAML for Xamarin forms, eg:
<Image HeightRequest="50" WidthRequest="50" HorizontalOptions="Center" VerticalOptions="Center" Source="{Binding UserAvatarURL}"/>
And Forms will handle it.
Related
I am trying to make an app that requires that I frequently send recorded data to a firebase. When network goes out or battery is about to die, I am saving all of the data that wasn't stored into firebase locally. However, to do this I require about 20 MB of data (my data is pretty big). That being said, I want to find a way to check the available storage (and the battery if possible) to give the user a warning. Is this possible using Xamarin Forms? Also, is there a way that I can make this solution universal (i.e. I don't need a separate piece of code for iOS vs. Android)? (I am new to Xamarin and C#)
Use the following code to check the free size of a device:
For iOS:
NSFileManager.DefaultManager.GetFileSystemAttributes (Environment.GetFolderPath (Environment.SpecialFolder.Personal)).FreeSize;
For Android:
var freeExternalStorage = Android.OS.Environment.ExternalStorageDirectory.UsableSpace;
There is no universal option, but you can wrap it an interface like so and implement it on each project:
public interface IStorage
{
double GetRemainingStorage();
}
It would be great if a feature like this could be added in Xamarin.Essentials - there was a request on GitHub but it never really made it.
If there are any issues with the code - please tell me.
Hope this helped,
Instructions
Create an interface in your shared project titled IStorage.
In your Android project create a class titled AndroidStorageManager (you can name it however you would like). Make it so it extends IStorage. The method GetRemainingStorage() should be of return type double.
public class AndroidStorageManager : IStorage
{
public double GetRemainingStorage()
{
var freeExternalStorage = Android.OS.Environment.ExternalStorageDirectory.UsableSpace;
return freeExternalStorage;
}
}
For iOS
Create a class in your iOS project titled iOSStorageManager which extends IStorage:
public class iOSStorageManager : IStorage
{
public double GetRemainingStorage()
{
return NSFileManager.DefaultManager.GetFileSystemAttributes(Environment.GetFolderPath(Environment.SpecialFolder.Personal)).FreeSize;
}
}
In your Android implementation - add the following code above the namespace:
[assembly: Xamarin.Forms.Dependency(
typeof(AndroidStorageManager))]
For iOS:
[assembly: Xamarin.Forms.Dependency(
typeof(iOSStorageManager))]
To get the storage:
IStorage storageManager = DependencyService.Get<IStorage>();
double remaining = storageManager.GetRemainingStorage();
Hope this clarified things.
I know this seems like a simple thing but I can't find any help online.
I want to include a file (.html) along with my Azure function when I publish it using Visual Studio. Then I want to be able to access this file in my Azure function.
Why? It seems like only the .dll gets sent to the server when I publish.
This file will be an .html file that will be an email template. I want to read it in my function and then send emails out.
Any help is much appreciated.
I see I can use [send grid in Azure functions][1], but it looks like I can only send out one email and not multiple emails, which is what I want.
First, you need to add the html file to your project, and in the properties, set Copy to Output Directory to "Copy if newer".
Then in your function code, take in an additional ExecutionContext context parameter (note that this is Microsoft.Azure.WebJobs.ExecutionContext and not System.Threading.ExecutionContext). And when you need to access your html file, you can then write:
string htmlFilePath = Path.Combine(context.FunctionAppDirectory, "test.html");
That's assuming you added the file at the root of your VS project. If you instead added it in some Data folder (better practice), you'd write:
string htmlFilePath = Path.Combine(context.FunctionAppDirectory, "Data", "test.html");
See here for full working sample.
I have the same scenario as you have. However, I cannot access ExecutionContext because it is only available in requests. My scenario needs to get the template included in AzFunc project but not in the context of AzFunc's functions. I got it null when I go with the interface - implementation class approach.
Thanks to this guy, I use IOptions<ExecutionContextOptions> in my class to get the root directory of the Azure Func.
My Azure Func project (NET 6, Azure Function v4)
using Microsoft.Extensions.Options;
using Microsoft.Azure.WebJobs.Host.Bindings;
namespace AzureFuncApi
{
public class TemplateHelper : ITemplateHelper
{
private readonly IOptions<ExecutionContextOptions> _executionContext;
public TemplateHelper (IOptions<ExecutionContextOptions> executionContext)
{
_executionContext = executionContext;
}
public string GetTemplate()
{
var context = _executionContext.Value;
var rootDir = context.AppDirectory; // <-- rootDir of AzFunc
var template = Path.Combine(rootDir, "test.html"); // <-- browse for your template. Here's an example if you place test.html right in the root of your project
// return your template here, raw, or after you do whatever you want with it...
}
}
}
My different project defines the interface and uses it there, independently of the real implementation
namespace DifferentProject
{
public interface ITemplateHelper
{
string GetTemplate(); // Use this to get the template
}
}
I am trying to upload an image inside the Shared project in my solution so that the Android and iOS project can use it normally via Xaml. Not working, I do not know why. Can anyone explain why it is not working?
Extension:
[ContentProperty("Source")]
public class ImageResourceExtension : IMarkupExtension
{
public string Source { get; set; }
public object ProvideValue(IServiceProvider serviceProvider)
{
if (Source == null)
{
return null;
}
// Do your translation lookup here, using whatever method you require
var imageSource = ImageSource.FromResource(Source);
return imageSource;
}
}
Xaml:
<Image Source="{extensions:ImageResource MyProject.Assets.fechar.png}" HorizontalOptions="Start" HeightRequest="16" Focused="Image_Focused" BackgroundColor="Red" WidthRequest="15" />
Putting a breakpoint in the Extension it usually goes there once for each item in my list.
I've also tried inserting a hardcoded binding by codebehind only for testing and it also does not work using ImageSource.FromResource.
The image file is as EmbbedResource as the documentation indicates.
Don't use extension. There is much easier way.
According to Xamarin "Currently there is no implicit conversion for resource identifiers, you must use ImageSource.FromResource" and "Because there is no built-in type converter from string to ResourceImageSource, these types of images cannot be natively loaded by Xaml". So you cannot specify in xaml that your image is shared but you can use code behind to bind a shared image.
In xaml:
<Image Source="{Binding Image}" HorizontalOptions="Start" WidthRequest="80"/>
Then in code behind
public ImageSource Image
{
get
{
return ImageSource.FromResource("ButtonRendererDemo.Resources.icon1.png"); //from PCL
}
}
below is the project structure
//////////////////////////////////////////////////////////////////
Tested with shared project. Below is the structure
The key is to add reference of your shared project to your PCL where you are calling FromResource. The shared project gets injected into PCL
Then in my project structure it is
public ImageSource Image
{
get
{
//return ImageSource.FromResource("ButtonRendererDemo.Resources.icon1.png"); //from PCL
return ImageSource.FromResource("ButtonRendererDemo.Pictures.icon1.png"); //from Shared
}
}
//////////////////////////////////////////////////////////////
If nothing works for you use the follow code to find your resource. In the file where you call FromResource add using System.Reflection; then add the follow code
var assembly = typeof(App).GetTypeInfo().Assembly;
foreach (var res in assembly.GetManifestResourceNames())
{
System.Diagnostics.Debug.WriteLine("found resource: " + res);
}
You should see in Output window something like
found resource: someNamespace.Pictures.icon1.png - That's your resource you need to use.
You didn't answer my question about your project structure. Then I could give you an exact answer. I suspect that your path to image is "MyProject.Droid.Assets.fechar.png"
FromResource is referring to the Android or iOS project not the shared one. The images need to be in the appropriate folder of the platform specific project.
I have a Xamarin based Visual Studio 2015 project that has the following structure.
MyApp (Portable)
MyApp.Droid
MyApp.iOS
Currently I include assets / resources in the MyApp.Droid project and the MyApp.iOS project.
So for example myhtml.html is duplicated as both MyApp.Droid/Asserts/myhtml.html and MyApp.iOS/Resources/myhtml.html
Are there any ways I can avoid this duplication?
Assuming you are using Xamarin Forms, yes, you can use .net resource files.
You can create a folder in the portable project, add there the content files and set the Compilation Action to Embedded Resource for all of those, then you can use the .net provided mechanism to acces the resources, per example (in this example I assume the code is being executed in a class contained in the portable project and the files are stored in a folder called ResourceFiles):
var htmlFile = this.GetType().GetTypeInfo().Assembly.GetManifestResourceStream("MyNamespace.ResourceFiles.myhtml.html");
In this way you have the stream with the file's content.
Also, as a hint, you can load these files from XAML using a custom markup extension, per example, here is a markup extension to load images from .net resources:
[ContentProperty ("Source")]
public class ImageResourceExtension : IMarkupExtension
{
public string Source { get; set; }
public object ProvideValue (IServiceProvider serviceProvider)
{
if (Source == null)
return null;
var imageSource = new StreamImageSource { Stream = async (ct) => this.GetType().GetTypeInfo().Assembly.GetManifestResourceStream(Source) };
return imageSource;
}
}
Then, to use this extension in XAML you will do (local is the XAML namespace definition of your own namespace):
<Image Source="{local:ImageResource MyNamespace.ResourceFiles.MyImage.png}" />
I want create a very simple HTML parser application. I read lots of tutorial and lots of developer use this class: HtmlDocument.
I want use this class in my app too but I am not able to add reference to System.Windows.Forms.
I try to add reference in Project > Reference but I can't find Windows.Forms.
How can I fix this problem and use HtmlDocument?
I use Visual Studio 2013.
Thank you.
This is my very simple code:
namespace ParseHTML
{
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
this.NavigationCacheMode = NavigationCacheMode.Required;
string url = "http://www.alvolante.it/";
download(url);
}
private async void download(string url)
{
HttpClient client = new HttpClient();
string risposta = await client.GetStringAsync(new Uri(url)); //download html della pagina web
HtmlDocument hc = new HtmlDocument(); //error here, missing reference or assembly?
}
You can't. WinForms is not supported nor even implemented on Windows Phone (Windows Mobile 6.5.3 released in early 2010 is the last "Windows" phone OS to support WinForms by way of the Compact Framework).
To process HTML in applications, I suggest HtmlAgilityPack instead, which provides a fault-tolerant DOM manipulation library: http://htmlagilitypack.codeplex.com