Cloudinary Blog

Addressing mobile challenges with the new Cloudinary SDK for Android

Address mobile challenges with the Cloudinary Android SDK

Developing applications for mobile consumption requires facing, and overcoming, some difficult challenges. Apps need to limit their RAM, CPU and battery usage while still performing the required tasks in a reasonable time frame. If too many background tasks are running, the mobile device can become sluggish, with the battery running out very quickly. Coordination with other apps is crucial to keep the device responsive and make the battery last longer.

Networks on mobile devices are also often unstable. Especially in some areas, disconnections are frequent and there are many switches between different network nodes, as well as slow network performance with a high percentage of packet loss. Apps need to be able to handle all the network issues, and if necessary, network activity needs to fail smoothly and resume when the network is available again, automatically if possible.

To support higher resolution mobile devices, the app backend needs to serve high-quality images and videos. Those resources take longer to download, and also consume more CPU and RAM to decode and then display on screen. On the other hand, for a low-resolution mobile device those are wasted resources, because you only need a low-quality resource. So you need to maintain a lot of different versions for each of your resources and then determine which one is most appropriate to serve to each mobile device.

With all that in mind, Cloudinary's latest version of the Android SDK lets you easily implement background upload functionality in your app to ensure the best user experience. If the user is doing something CPU, RAM or power intensive, the uploads can be paused so that the user experience doesn't suffer, and then continue when conditions are more favorable. And with Cloudinary's Dynamic URL feature, the delivered resource can be generated on the fly, eliminating the need to pre-generate all the various versions of your resources for different mobile devices.

The Cloudinary Android SDK v2.0

The Cloudinary SDK works on the principle that Android knows how to manage its own memory, CPU and power, and so relies on the operating system itself doing the prioritization of those limited hardware resources. All uploads are presented as requests to the operating system, which will schedule the uploads accordingly. The Cloudinary SDK hooks into Android's JobScheduler, which makes sure the mobile device works smoothly when running background uploads. If the mobile device is running an older version of Android that does not support the JobScheduler API, then the Cloudinary SDK transparently falls back to using the scheduling engine inside Google Play services.

All upload requests can be finely-tuned using the new policy mechanism, and the SDK can handle global callbacks, even when your app is down, or is running in the background.

Presenting the Cloudinary MediaManager

The Cloudinary Android SDK v2.0 provides you with the MediaManager class, with methods for configuring and handling all your media-related operations. Use the upload method to build your request, which is then dispatched to a background queue via the MediaManager's dispatch method.

MediaManager.get().upload(imageFile).dispatch();

The MediaManager's option method lets you include any upload parameters for Cloudinary, for example, adding the tag user_uploaded:

MediaManager.get().upload(imageFile)
   .option("tags", "user_uploaded")
   .dispatch();

While you are at it, you might want to specify some upload conditions in your request, such as how many times to retry after a recoverable error (e.g., network issues), to limit the upload to a wifi network, or only when the device is charging. The MediaManager's policy method lets you do just that, overriding the default values for that particular upload request:

MediaManager.get().upload(filePath)
   .policy(new UploadPolicy.Builder()
      .maxRetries(7)
      .requiresCharging(true)
      .networkPolicy(UploadPolicy.NetworkType.UNMETERED)
      .build())
   .dispatch();

Callbacks

Since all uploads are ultimately run asynchronously by the system, the MediaManager's callback method provides an easy way to hook into the upload's progress and provide specific code to run at each stage of the upload.

String requestId = MediaManager.get().upload(filePath)
   .callback(new UploadCallback() {
      @Override
      public void onProgress(String requestId, long bytes, long totalBytes) {
         Double progress = (double) bytes/totalBytes;
         // post progress to app UI (e.g. progress bar, notification)
      }
      @Override
      public void onSuccess(String requestId, Map resultData) {
      }
    ...
   })
   .dispatch();

This method of implementing callbacks won't suffice if your app is down or is running in the background. In this case, you would want to implement global callbacks for your app by registering a new service class that extends the provided ListenerService class. All upload request callbacks will be routed to your service, which implements the code to run at each stage of the upload.

public class MyClass extends ListenerService {
   @Override
   public void onProgress(String requestId, long bytes, long totalBytes) {
      Double progress = (double) bytes/totalBytes;
      // post progress to app UI (e.g. progress bar, notification)
   }
   @Override
   public void onSuccess(String requestId, Map resultData) {
   }
   ...
}

Not only upload

Once your media assets have been uploaded to Cloudinary, you can take advantage of Cloudinary's Dynamic URL feature to deliver your images and videos to your users. Dynamic URLs include instructions telling Cloudinary how to transform and optimize the asset on-the-fly, and then deliver it through a fast CDN to the end user for optimal user experience. There is no need to pre-generate all the different versions you may need for the various devices running your app.

Besides taking care of all your resource uploads directly to your Cloudinary account, the MediaManager class provides the url method to generate a URL string for accessing resources uploaded to your Cloudinary account:

MediaManager.get().url().generate("sample.jpg")
// returns: http://res.cloudinary.com/demo/image/upload/sample.jpg

You can also call the transformation method to include any transformation instructions in the generated URL:

Android:
MediaManager.get().url().transformation(new Transformation()
  .gravity("face").radius(75).border("10px_solid_grey").crop("crop").chain()
  .overlay(new Layer().publicId("couple")).width(170).height(150).radius("max").gravity("faces").border("3px_solid_black").crop("thumb").chain()
  .flags("layer_apply").gravity("north_east")).generate("woman2.jpg");
image cropped with face detection and given rounded corners and a grey border, with an overlay of the image of `couple` resized to an oval thumbnail with face detection and a black border added to the northeast corner

Summary

The new version of the Cloudinary SDK for Android is a major release that now makes it simple to include upload functionality in your mobile app, and let your users upload their media directly to your Cloudinary account. The SDK takes advantage of Android's built-in functionality when executing the uploads, to make sure that your users enjoy an uninterrupted experience while using your app. Integrating with Cloudinary to upload, manage, and deliver all your app resources is now easier than ever. Make sure you check out the Android integration documentation, and if you don't already have a Cloudinary account, you can sign up for free.

Recent Blog Posts

An Eye-Opening Talk: Building Apps for the Next Billion Users in Africa

William (iChuloo) Imoh, who hails from Lagos, Nigeria, recently embarked on a U.S. speaking tour, February 20-March 12, during which he powwowed with technical and product teams and communities at such renowned enterprises as Netlify, Pluralsight, Lucidchart, Twilio, and more in Salt Lake City, Dallas, Las Vegas, and San Francisco. On March 5, he gave an enlightening talk, entitled International Developers and Development: Building for the Next Billion Users at Cloudinary in Santa Clara, California. Below is a synopsis. For details, see the related slides.

Read more
The Debut of the Cloudinary Customer Advisory Board

Focus on customers has always been Cloudinary’s mantra. Because we owe them our success, we are constantly reaching out to our customers, not just for feedback on our offerings, but also for their vision, wish list, and buy-in of what Cloudinary can do to meet their needs and make them succeed. About six months ago, it occurred to us that it would be beneficial if we could meet regularly with those who are behind innovation at our key customers—executives, product gurus, developers, content managers—to swap strategies, product roadmaps, best practices, and such. In particular, we’d like to solicit actionable feedback as a foundation for our plans of product enhancements.

Read more
Media Management With the Cloudinary-Netlify CMS Integration

Static sites and the JAMstack are quickly becoming a standard for developing safe and performant websites with an optimal workflow for developers. Netlify CMS (not to be confused with the company that created it, Netlify) is an open source content management solution that works especially with static site generators such as Gatsby, Hugo, etc... enabling content storage in your Git repository along with your code for easier versioning, multichannel publishing, and direct content updates in Git.

Read more
Vitaly Friedman's Insights on Media Conferences

Vitaly Friedman is a die-hard devotee of beautiful content. Born in Minsk, Belarus, he studied Computer Science and Mathematics in Germany, unearthing in himself a passion for typography, writing, and design in the interim. After a six-year stint as a freelance designer and developer, he co-founded Smashing Magazine, a leading online publication on web design and development. You can follow SmashingMag on Twitter @SmashingMag.

Read more