Dev Sahoo
Dev Sahoo

Reputation: 12101

How to load an Image from Assets in Xamarin.Forms on Android?

I am using the following code:

var baseUrl = DependencyService.Get<IBaseUrl> ().Get ();
var backgroundImage = new Image () {
    Source = FileImageSource.FromFile (
        System.IO.Path.Combine (baseUrl, "Content", "images", "background-2.jpg")
    )
};

Where the DependencyServices for iOS and Androids are as below:

// iOS
[assembly: Xamarin.Forms.Dependency (typeof (BaseUrl_iOS))]
namespace TuneProtectApp.iOS
{
    public class BaseUrl_iOS : IBaseUrl
    {
        public BaseUrl_iOS () { }
        public string Get ()
        {
            return NSBundle.MainBundle.BundlePath;
        }
    }
}

// Android
[assembly: Xamarin.Forms.Dependency (typeof (BaseUrl_Droid))]
namespace TuneProtectApp.Droid
{
    public class BaseUrl_Droid : IBaseUrl
    {
        public BaseUrl_Droid () {}
        public string Get ()
        {
            return "file:///android_asset/";
        }
    }
}

The backgroundImage loads fine on iOS but not on Android. How to load an Image from Assets in Xamarin.Forms on Android?

Upvotes: 1

Views: 3259

Answers (1)

FredyWenger
FredyWenger

Reputation: 2325

In my Xamarin.forms (shared) app I have a registration-page, where the user also have to select an image for his avatar. Based on the sex of the user, I show a male or a female symbol-image as default (the user then can select another, if he want to do).

I have implemented it as follows:

First created a sub-directory \Embedded for all projects (iOS, Android and WP) (directly in the project-root of each project-type).
Then added the two .jpg’s to the new directories in all projects.
In my app I have a global variable (GV.cEmbeddedAblage)
This is filled in startup-code:

string cNameSpace = "";
switch (Device.OS)
 {
   case TargetPlatform.WinPhone:
        cNameSpace = "MatrixGuide.WinPhone";
        break;
   case TargetPlatform.iOS:
        cNameSpace = "MatrixGuide.iOS";
   break;
        case TargetPlatform.Android:
        cNameSpace = "MatrixGuide.Droid";
   break;
//
}
GV.cEmbeddedAblage = cNameSpace + ".Embedded.";

Further, I create a global byte-array for the images (example to male):

 static Byte[] _SymbolMann;
 public static Byte[] ByteSymbolMann
 {
   get { return _SymbolMann; }
   set { _SymbolMann = value; }
  }

I then easily can access the images from shared code (on the registration-page) with (e.g.):
Generate the path, load image in byte-array (if not already loaded):

string cFilename = "";
if (GV.ByteSymbolMann == null) // not yet loaded - only load one time
 {
   cFilename = GV.cEmbeddedAblage + "SymbolMann.jpg";
   var assembly = this.GetType().GetTypeInfo().Assembly; 
   byte[] buffer;
   using (Stream s = assembly.GetManifestResourceStream(cFilename))
    {
       long length = s.Length;
       buffer = new byte[length];
       s.Read(buffer, 0, (int)length);
       GV.ByteSymbolMann = buffer;
     }
}

Fill another byte.array (with selected (loaded) male- / female- image):

  AvatarErfassung = GV.ByteSymbolMann;

create the image on the page:

var Avatar = new Image { HeightRequest = 70, WidthRequest = 70, HorizontalOptions = LayoutOptions.Start };

Overtake the selected image as Source to the Image:

Avatar.Source = ImageSource.FromStream(() => new MemoryStream(AvatarErfassung));

You should be able to do it similar...

Upvotes: 1

Related Questions