In Focus

Xamarin.Android - Upload Image To Blob Storage

In this article, you will learn how you can upload images to blob storage through Xamarin.Android. It’s pretty simple to build this app with a native Xamarin platform. I hope you will enjoy and learn something new in Xamarin with Azure.

Introduction


Today, I am super excited to share with you my new article “Upload Image to blob storage using Xamarin.Android”.
Blob Storage

So, the first question that arises in our minds is - what is this blob storage? Well, Blob stands for Binary Large Object. Azure Blob Storage is a service for storing large amounts of unstructured object data, such as text or binary data. You can use Blob Storage to bare the data publicly to the world or to store application data privately. Related uses of Blob Storage include:

  • Serving images or documents directly to a browser
  • Storing files for distributed access
  • Streaming video and audio
  • Storing data for backup and restore, disaster recovery, and archiving
  • Storing data for analysis by an on-premises or Azure-hosted service

Create a storage account

 
Prerequisites

If you don't have an Azure subscription, create a free account before you begin.

Log into the Azure portal.

Create a storage account

 
Now, you are ready to create your storage account. Every storage account must belong to an Azure resource group. A resource group is a logical container for grouping your Azure services. When you create a storage account, you have the option to either create a new resource group or use an existing resource group.

To create a general-purpose v2 storage account in the Azure portal, follow these steps,

  1. In the Azure portal, select all services. In the list of resources, type Storage Accounts. As you begin typing, the list filters based on your input. Select Storage Accounts.
  2. On the Storage Accounts window that appears, choose Add.
  3. Select the subscription in which to create the storage account.
  4. Under the Resource group field, select Create new. Enter a name for your new resource group, as shown in the following image.

  5. Next, enter a name for your storage account. The name you choose must be unique across Azure. The name also must be between 3 and 24 characters in length, and can include numbers and lowercase letters only.
  6. Select a location for your storage account, or use the default location.
  7. Leave these fields set to their default values,

    FieldValue
    Deployment modelResource Manager
    PerformanceStandard
    Account kindStorageV2 (general-purpose v2)
    ReplicationLocally redundant storage (LRS)
    Access tierHot

  8. Select Review + Create to review your storage account settings and create the account.
  9. Select Create.

Create a container

  • To create a container in the Azure portal, follow these steps:
  • Navigate to your new storage account in the Azure portal.
  • In the left menu for the storage account, scroll to the Blob service section, then select Blobs.
  • Select the + Container button.
  • Type a name for your new container. The container name must be lowercase, must start with a letter or number, and can include only letters, numbers, and the dash (-) character. For more information about container and blob names, see Naming and referencing containers, blobs, and metadata.
  • Set the level of public access to the container. The default level is Private (no anonymous access).
  • Select OK to create the container.

Let’s create a Xamarin.Forms project with .NET standard library.

First of all, add the required nuGet packages to your application.

  1. AppCompat
  2. WindowsAzure.Storage
User Interface of Application

Open Solution Explorer-> Project Name-> Resources-> Layout-> Main.axml. Open this main layout file and add the following code. In the layout we will need the three buttons, one picture placeholder and one text viewer.

(File Name: Main.axml , Folder Name: Layout)

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical"  
  4.     android:layout_width="match_parent"  
  5.     android:layout_height="match_parent"  
  6.     android:padding="10dp">  
  7.     <LinearLayout  
  8.         android:orientation="horizontal"  
  9.         android:layout_width="match_parent"  
  10.         android:layout_height="wrap_content"  
  11.         android:weightSum="2"  
  12.         android:id="@+id/btns">  
  13.         <Button  
  14.             android:id="@+id/btnChoose"  
  15.             android:text="Choose"  
  16.             android:layout_width="0dp"  
  17.             android:layout_weight="1"  
  18.             android:layout_height="wrap_content" />  
  19.         <Button  
  20.             android:id="@+id/btnCapture"  
  21.             android:text="Capture"  
  22.             android:layout_width="0dp"  
  23.             android:layout_weight="1"  
  24.             android:layout_height="wrap_content" />  
  25.     </LinearLayout>  
  26.     <LinearLayout  
  27.         android:orientation="vertical"  
  28.         android:layout_width="match_parent"  
  29.         android:layout_height="wrap_content"  
  30.         android:padding="8dp">  
  31.         <ImageView  
  32.             android:id="@+id/imgView"  
  33.             android:layout_width="350dp"  
  34.             android:layout_height="300dp" />  
  35.         <Button  
  36.             android:id="@+id/btnUpload"  
  37.             android:text="Upload"  
  38.             android:layout_width="match_parent"  
  39.             android:layout_height="wrap_content" />  
  40.         <EditText  
  41.             android:id="@+id/edtURL"  
  42.             android:text="URL:"  
  43.             android:layout_width="match_parent"  
  44.             android:layout_height="match_parent" />  
  45.         <ProgressBar  
  46.             android:layout_width="match_parent"  
  47.             android:layout_height="wrap_content"  
  48.             android:id="@+id/progressBar"  
  49.             android:visibility="invisible" />  
  50.     </LinearLayout>  
  51. </LinearLayout>  

Backend Code of Application

Now, go to Solution Explorer-> Project Name-> MainActivity and add the following code with appropriate namespaces.
 
Note
In the upload function, I am using my own blob storage connection string. But you will use your own blob storage connection string. Go to Access keys, and inside this tab you will get two keys (key1 and key2) also with connection strings. You can use either key1 or key2. In this demo we only need the connection string, so you will only copy the connection string.
  1. using Android.App;  
  2. using Android.Content;  
  3. using Android.Graphics;  
  4. using Android.OS;  
  5. using Android.Provider;  
  6. using Android.Runtime;  
  7. using Android.Support.V7.App;  
  8. using Android.Widget;  
  9. using Microsoft.WindowsAzure.Storage;  
  10. using System;  
  11. using System.IO;  
  12.   
  13. namespace UploadToBlob.Droid  
  14. {  
  15.     [Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true)]  
  16.     public class MainActivity : AppCompatActivity  
  17.     {  
  18.         private Button btnUpload, btnChoose, btnCapture;  
  19.         private ImageView imgView;  
  20.         public Bitmap mBitMap;  
  21.         private Android.Net.Uri filePath;  
  22.         private const int PICK_IMAGE_REQUSET = 71;  
  23.         private const int TAKE_IMAGE_REQUSET = 0;  
  24.         private EditText edtURL;  
  25.         private MemoryStream inputStream;  
  26.         private ProgressBar progressBar;  
  27.         public string URL { getprivate set; }  
  28.   
  29.         protected override void OnCreate(Bundle savedInstanceState)  
  30.         {  
  31.             base.OnCreate(savedInstanceState);  
  32.   
  33.             // Set our view from the "main" layout resource  
  34.             SetContentView(Resource.Layout.activity_main);  
  35.             btnChoose = FindViewById<Button>(Resource.Id.btnChoose);  
  36.             btnUpload = FindViewById<Button>(Resource.Id.btnUpload);  
  37.             btnCapture = FindViewById<Button>(Resource.Id.btnCapture);  
  38.             imgView = FindViewById<ImageView>(Resource.Id.imgView);  
  39.             edtURL = FindViewById<EditText>(Resource.Id.edtURL);  
  40.             progressBar = FindViewById<ProgressBar>(Resource.Id.progressBar);  
  41.   
  42.             //Events  
  43.             btnChoose.Click += delegate  
  44.             {  
  45.                 ChooseImage();  
  46.             };  
  47.   
  48.             btnCapture.Click += delegate  
  49.             {  
  50.                 CaptureImage();  
  51.             };  
  52.   
  53.             btnUpload.Click += delegate  
  54.             {  
  55.                 UploadImage();  
  56.                 Busy();  
  57.             };  
  58.         }  
  59.   
  60.         private void CaptureImage()  
  61.         {  
  62.             Intent intent = new Intent(MediaStore.ActionImageCapture);  
  63.             StartActivityForResult(intent, 0);  
  64.         }  
  65.   
  66.         private void UploadImage()  
  67.         {  
  68.             if (inputStream != null)  
  69.                 Upload(inputStream);  
  70.         }  
  71.   
  72.         private void ChooseImage()  
  73.         {  
  74.   
  75.             Intent intent = new Intent();  
  76.             intent.SetType("image/*");  
  77.             intent.SetAction(Intent.ActionGetContent);  
  78.             StartActivityForResult(Intent.CreateChooser(intent, "Select Picture"), PICK_IMAGE_REQUSET);  
  79.         }  
  80.         protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data)  
  81.         {  
  82.             base.OnActivityResult(requestCode, resultCode, data);  
  83.   
  84.             if (requestCode == PICK_IMAGE_REQUSET &&  
  85.                 resultCode == Result.Ok &&  
  86.                 data != null &&  
  87.                 data.Data != null)  
  88.             {  
  89.                 filePath = data.Data;  
  90.                 try  
  91.                 {  
  92.                     mBitMap = MediaStore.Images.Media.GetBitmap(ContentResolver, filePath);  
  93.                     imgView.SetImageBitmap(mBitMap);  
  94.                     byte[] bitmapData;  
  95.                     using (var stream = new MemoryStream())  
  96.                     {  
  97.                         mBitMap.Compress(Bitmap.CompressFormat.Jpeg, 100, stream);  
  98.                         bitmapData = stream.ToArray();  
  99.                     }  
  100.                     inputStream = new MemoryStream(bitmapData);  
  101.                 }  
  102.                 catch (IOException ex)  
  103.                 {  
  104.                     Console.WriteLine(ex);  
  105.                 }  
  106.             }  
  107.             else if (requestCode == 0 &&  
  108.                 resultCode == Result.Ok &&  
  109.                 data != null)  
  110.             {  
  111.                 try  
  112.                 {  
  113.                     mBitMap = (Bitmap)data.Extras.Get("data");  
  114.                     imgView.SetImageBitmap(mBitMap);  
  115.                     byte[] bitmapData;  
  116.                     using (var stream = new MemoryStream())  
  117.                     {  
  118.                         mBitMap.Compress(Bitmap.CompressFormat.Jpeg, 100, stream);  
  119.                         bitmapData = stream.ToArray();  
  120.                     }  
  121.                     inputStream = new MemoryStream(bitmapData);  
  122.                 }  
  123.                 catch (IOException ex)  
  124.                 {  
  125.                     Console.WriteLine(ex);  
  126.                 }  
  127.             }  
  128.         }  
  129.   
  130.         //Upload to blob function  
  131.         private async void Upload(Stream stream)  
  132.         {  
  133.             try  
  134.             {  
  135.                 var account = CloudStorageAccount.Parse("DefaultEndpointsProtocol=https;AccountName=blobacount;AccountKey=hMZuDKfdz1iGPVsV+W9V52YnsjD6F1tjdH89XIw0QM3J6FB+tdJ9IgQI+OAWHgCRKSYMK0EwGcpB0qCJI8kY+w==;x=core.windows.net");  
  136.                 var client = account.CreateCloudBlobClient();  
  137.                 var container = client.GetContainerReference("images");  
  138.                 await container.CreateIfNotExistsAsync();  
  139.                 var name = Guid.NewGuid().ToString();  
  140.                 var blockBlob = container.GetBlockBlobReference($"{name}.png");  
  141.                 await blockBlob.UploadFromStreamAsync(stream);  
  142.                 URL = blockBlob.Uri.OriginalString;  
  143.                 edtURL.Text = URL;  
  144.                 Toast.MakeText(this"Image uploaded to Blob Storage Successfully!", ToastLength.Short).Show();  
  145.                 NotBusy();  
  146.             }  
  147.             catch (Exception e)  
  148.             {  
  149.                 Toast.MakeText(this"" + e.ToString(), ToastLength.Short);  
  150.             }  
  151.         }  
  152.   
  153.         void Busy()  
  154.         {  
  155.             btnCapture.Enabled = false;  
  156.             btnChoose.Enabled = false;  
  157.             btnUpload.Enabled = false;  
  158.             progressBar.Visibility = Android.Views.ViewStates.Visible;  
  159.         }  
  160.         void NotBusy()  
  161.         {  
  162.             btnCapture.Enabled = true;  
  163.             btnChoose.Enabled = true;  
  164.             btnUpload.Enabled = true;  
  165.             progressBar.Visibility = Android.Views.ViewStates.Invisible;  
  166.         }  
  167.     }  
  168. }   
Choose From Moible and Upload
 
 
 
Capture From Camera and Upload