DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Low-Code Development: Leverage low and no code to streamline your workflow so that you can focus on higher priorities.

DZone Security Research: Tell us your top security strategies in 2024, influence our research, and enter for a chance to win $!

Launch your software development career: Dive head first into the SDLC and learn how to build high-quality software and teams.

Open Source Migration Practices and Patterns: Explore key traits of migrating open-source software and its impact on software development.

Related

  • Microsoft Azure Service Fabric
  • Keep Your Application Secrets Secret
  • Delivering Your Code to the Cloud With JFrog Artifactory and GitHub Actions
  • Reference Architecture: Deploying WSO2 API Manager on Microsoft Azure

Trending

  • Microservices Design Patterns for Highly Resilient Architecture
  • Test Smells: Cleaning up Unit Tests
  • Data Governance – Data Privacy and Security – Part 1
  • How To Remove Excel Worksheets Using APIs in Java
  1. DZone
  2. Software Design and Architecture
  3. Cloud Architecture
  4. Android Cloud Apps with Azure

Android Cloud Apps with Azure

By 
Tony Siciliani user avatar
Tony Siciliani
·
Updated Oct. 11, 22 · Interview
Like (1)
Save
Tweet
Share
14.9K Views

Join the DZone community and get the full member experience.

Join For Free

a  recent study by gartner  predicts a very significant increase in cloud usage by consumers in a few years, due in great part to the ever growing use of smartphone cameras by the average household. in this context, it could be useful to have a smartphone application that is able to upload / download digital content from a cloud provider.

in this article, we will construct a basic android prototype that will allow us to plug in the  windows azure  cloud provider, and use the  windows azure toolkit for android (  available at  github  ) to do all of the  basic cloud operations  :  upload  content to cloud storage,  browse  the storage,  download  or  delete  files in cloud storage. once those operations are implemented, we will see how to enable our android application to receive server  push notifications  .

first things first, we need to set up a storage account in the azure cloud:

a storage account comes with several options as for  data management  : we can keep data in blob, table or queue storage. in this article, we will use the blob storage to work with images. the storage account has a  primary  and  secondary access key  , either one of the two can be used to execute operations on the storage account. any of those keys can be regenerated if compromised.

1. preliminaries

first, the prerequisites:

  •  eclipse ide for java 
  • android plugin for eclipse (  adt  )
  •  windows azure toolkit  for android
  • windows azure subscription (you can get a 90-day  free trial  )

a  getting-started document  on windows azure toolkit’s github page covers the installation procedure of all the the required software in detail.

this whole project (  cloid  ) is freely available at  github  . so here we’ll limit ourselves to presenting the most relevant code sections along with the corresponding screens.

the user interface is composed of a few basic activity screens, spawned from the main screen (top center):

since we use a technology not for its own sake but according to our needs, let’s start by specifying what we want:

public abstract class storage {

    /** all providers will have accesss to context*/
    protected context context;

    /** all providers will have accesss to sharedpreferences */
    protected cloudpreferences prefs;

    /** all downloads from providers will be saved on sd card */
    protected string download_path = "/sdcard/dcim/camera/";

    /**
     * @throws operationexception
     * */
    public storage(context ctx) throws operationexception {
        context = ctx;
        prefs = new cloudpreferences(ctx);
    }

    /**
     * @throws operationexception
     * */
    public abstract void uploadtostorage(string file_path) throws operationexception;

    /**
     * @throws operationexception
     * */
    public abstract void downloadfromstorage(string file_name) throws operationexception;

    /**
     * @throws operationexception
     * */
    public abstract void browsestorage() throws operationexception;

    /**
     * @throws operationexception
     * */
    public abstract void deleteinstorage(string file_name) throws operationexception;

}

the above is the  contract  that our cloud storage provider will satisfy. we’ll provide a mockstorage implementation that will pretend to carry out a command in order to test our ui (i.e. our scrollable items list, progress bar, exception messages, etc.), so that we can later just plug in azure storage operations. note from our activities screen above, that we can switch anytime between azure storage and mock storage with the press of the toggle button “cloud on/off” in the settings screen, saving the preferences afterward.

public class mockstorage extends storage {

    // code here...
    @override
    public void uploadtostorage(string file_path) throws operationexception {

        donothingbutsleep();
        //throw new operationexception( "test error message",
        //                          new throwable("reason: upload test") );
    }

    // other methods will also do nothing but sleep...

    /***/
    private void donothingbutsleep(){

         try{ thread.sleep(5000l); }
         catch (interruptedexception iex){ return; }
    }

2. the azure toolkit

the toolkit comes with a sample application called “simple”, and two library jars:

  1.  access control for android.jar  in the  wa-toolkit-android\library\accesscontrol\bin  folder
  2.  azure storage for android.jar  in the  wa-toolkit-android\library\storage\bin  folder

here we will only use the latter, since we will access  directly  azure’s blob storage. needless to say,  this is not the recommended way  , since our credentials will be stored on the handset. a better approach security-wise would be to access azure storage through web services hosted on either azure or other public/private clouds.

once the toolkit is ready for use, we need to think a bit about  settings  . using an azure blob storage only requires 3 fields:  an  account name  , an  access key  , and a  container  for our images. the access key is quite a long string (88 characters) and is kind of a pain to type, so one way to do the setup is to configure the android  res/values/strings.xml  file to set the default values:

...
<!-- azure configuration direct -->
<string name="azure_direct_account_name">cloid</string>
<string name="azure_direct_access_key">insert-access-key-here</string>
<string name="azure_container">pictures</string>
...

however, because we may want to overwrite the default values above (e.g. create another container), we will also save the values on the settings screen in android’s  sharedpreferences  .

and now, let’s implement the  azurestorage  class.

3. azure blob storage operations

3.1. storage initialization

the azurestorage constructor gets its data from android preferences (from its superclass), then constructs a connection string used to access the storage account, creates a blob client and retrieves a reference to the container of images. if the user changed the default container “pictures” in settings, then a new (empty) one will be created with that new name. a container is any grouping of blobs under a name. no blob exists outside of a container.

// package here
// other imports
import com.windowsazure.samples.android.storageclient.blobproperties;
import com.windowsazure.samples.android.storageclient.cloudblob;
import com.windowsazure.samples.android.storageclient.cloudblobclient;
import com.windowsazure.samples.android.storageclient.cloudblobcontainer;
import com.windowsazure.samples.android.storageclient.cloudblockblob;
import com.windowsazure.samples.android.storageclient.cloudstorageaccount;

public class azurestorage extends storage {

private cloudblobcontainer container;

/ * @throws operationexception
* */
public azurestorage(context ctx) throws operationexception {
  super(ctx);

  // set from prefs
  string acct_name = prefs.getaccountname();
  string access_key = prefs.getaccesskey();

  // get connection string
  string storageconn = "defaultendpointsprotocol=http;" +
  "accountname=" + acct_name +
  ";accountkey=" + access_key;

  // get cloudblobcontainer
  try {
     // retrieve storage account from storageconn
     cloudstorageaccount storageaccount = cloudstorageaccount.parse(conn);

     // create the blob client
     // to get reference objects for containers and blobs
     cloudblobclient blobclient = storageaccount.createcloudblobclient();

    // retrieve reference to a previously created container
    container = blobclient.getcontainerreference( prefs.getcontainer() );
    container.createifnotexist();
  }
  catch (exception e) {
    throw new operationexception("error from initblob: " + e.getmessage(), e);
  }
 }
// code...

we will use that container reference  cloudblobcontainer  throughout our upcoming cloud operations.

3.2. uploading images

we will upload a file from android’s gallery to the cloud, keeping the same filename. “screener” is just a utilities class (see github repository) that does a number of useful things, e.g. extracting a file name from its path and setting the right mime type (“image/jpeg”, “image/png”, etc.).

the two kinds of blobs are  page blobs  and  block blobs  .  the (very) short story is that page blobs are optimized for read & write operations, while block blobs let us upload large files efficiently. in particular we can upload multiple blocks in parallel to decrease upload time.  here we are uploading a blob (gallery image) as a set of blocks.

/**
 * @throws operationexception */
 @override
 public void uploadtostorage(string file_path) throws operationexception {

     try {
	   // create or overwrite blob with contents from a local file
	   // use same name than in local storage
	   cloudblockblob blob = container.getblockblobreference(
	    			       screener.getnamefrompath(file_path) );
	   file source = new file(file_path);
	   blob.upload( new fileinputstream(source), source.length() );
	   blob.getproperties().contenttype = screener.getimagemimetype(file_path);
	   blob.uploadproperties();
     }
     catch (exception e) {
	   throw new operationexception("error from uploadtostorage: "
                                          + e.getmessage(), e);
     }
 }

bear in mind that we are not checking if the file already exists in cloud storage. therefore we will overwrite any existing file with the same name as the one we are uploading. that is usually not desirable in production code. here’s the screen flow of the upload operation:

3.3. browsing the cloud

for browsing, we store all our blobs in our container into a list of items that we will display in android as a scrollable list of image names in a subclass of  android.app.listactivity  . once one item in the list is clicked (“touched”) by the user, we want to display some image properties such as the image size (important when deciding to download), its mime type, and the date it was last operated upon.

/**
  * @throws operationexception
 * */
 @override
 public void browsestorage() throws operationexception{

    // reset uri list for refresh - no caching
    item.itemlist.clear();

    // loop over blobs within the container
    try {
	for (cloudblob blob : container.listblobs()) {
	    blob.downloadattributes();
	    blobproperties props = blob.getproperties();
	    long ksize =  props.length/1024;
	    string type = props.contenttype;
	    date lastmodified = props.lastmodified;

	    item item = new item(blob.geturi(), blob.getname(), ksize, type, lastmodified);
	    item.itemlist.add(item);
	} // end loop
    }
    catch (exception e) {
	 throw new operationexception("error from browsestorage: " + e.getmessage(), e);
    }
 }

here’s the screen flow of the browse operation. pressing on an item on the list displays its details and operations on the image, which we will look at next:

3.4. downloading images

our download method is pretty straightforward. note that we are downloading to the android handset’s sd card by using download_path from the superclass.

/**
 * @throws operationexception
 * */
 @override
 public void downloadfromstorage(string file_name) throws operationexception{

     try {
	    for (cloudblob blob : container.listblobs()) {
	    // download the item and save it to a file with the same name as arg
		if(blob.getname().equals(file_name)){
	             blob.download( new fileoutputstream(download_path
                                   + blob.getname()) );
		     break;
		}
	    }
    }
    catch (exception e) {
	throw new operationexception("error from downloadfromstorage: "
                        + e.getmessage(), e);
    }
}

and the corresponding ui flow. instead of displaying the image right after the download, we chose to include a link to the gallery (bottom of the screen) where the freshly retrieved image appears on top of the gallery’s stack of pictures:

3.5. deleting images

the delete operation performed on a blob up in the cloud is also rather simple:

/**
 * @throws operationexception */
 @override
 public void deleteinstorage(string file_name) throws operationexception{

    try {
   // retrieve reference to a blob named file_name
   cloudblockblob blob = container.getblockblobreference(file_name);
   // delete the blob
   blob.delete();
    }
    catch (exception e) {
throw new operationexception("error from deleteinstorage: "
                     + e.getmessage(), e);
    }
  }

and its associated ui screens series. note that after confirming the operation, and when deletion completes, the browsing list of items is automatically refreshed, and we can see that the image is no longer on the list of blobs in our storage container.

3.6. wrapping up

the azurestorage methods are called inside a basic work thread, which will take care of all cloud operations:

// called inside a thread
try {
      // get storage instance from factory
      storage store = storagefactory.getstorageinstance(this,
                          storagefactory.provider.azure_storage);
      // for the progress bar
      incrementworkcount();

      // do ops
       switch(operation){

            case upload :   store.uploadtostorage(path);
                            break;
            case browse :   store.browsestorage();
                            break;
            case download : store.downloadfromstorage(path);
                            // refresh gallery
                            sendbroadcast( new intent( intent.action_media_mounted,
                                uri.parse("file://"+ environment.getexternalstoragedirectory()) ) );
                            break;
             case delete :  store.deleteinstorage(path);
                            break;
       } // end switch
 }
 catch (operationexception e) {
     recorderror(e);
 }

notice how we are telling the android image gallery to refresh by issuing a broadcast once a new file is downloaded from the cloud to the sd card. there are different ways to do this, but without that call, the gallery won’t show the new image before the next system scheduled media scan. again, for the full code, refer to this project on github.

we are done with the basic cloud operations. all we had to do was plug in our  azurestorage  implementation class and get an instance of it through a factory, with minimal impact on preexisting code.

4. push notifications

up to this point we have demonstrated  device-initiated  communication with the cloud. for  cloud-initiated  or push communication, the android platform uses  google cloud messaging  (gcm).

in a previous article , i wrote about how to integrate gcm into an existing android application. here we will add a second set of settings for server push. our client code will connect with any gcm server and it will set the status on our main activity (last screen shot on the right) once the information in push preferences is correctly set.

5. conclusions

the toolkit documentation is kind of sparse (which is why the community needs more articles like this). also, the sample application doesn’t cover much (maybe the reason why it’s called “simple”), and it has room for improvement. however, the library itself is fully functional, and once we figure out the api, it all works quite nicely. of course, this application is itself pretty basic and doesn’t cover lots of other features, like access control, permissions, metadata, and snapshots. but it is a start.


Cloud azure Android (robot) Database application app Container

Opinions expressed by DZone contributors are their own.

Related

  • Microsoft Azure Service Fabric
  • Keep Your Application Secrets Secret
  • Delivering Your Code to the Cloud With JFrog Artifactory and GitHub Actions
  • Reference Architecture: Deploying WSO2 API Manager on Microsoft Azure

Partner Resources


Comments

ABOUT US

  • About DZone
  • Send feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends: