Tag Archives: Developer Story

Bringing modern storage to Viber’s users

This blogpost is a collaboration between Google and Viber. Authored by Kseniia Shumelchyk from Google and Anton Novikov, Sergey Kozlov from Viber.

As a messaging app, Viber needs to store, process and share a significant amount of data. Viber aims to give its users an easy, fast, reliable and secure communication platform by providing an intuitive interface and operating with files in a privacy-preserving way. We believe the modern scoped storage paradigm provides this foundation for app developers and users.

Scoped storage was introduced in Android 10 with further improvements in Android 11 to provide better protection to app and user data on a platform level. Due to Viber's complexity, the team opted to incrementally implement the changes that were required to comply with scoped storage.

In this article, we’ll share how Viber handled the migration to scoped storage, focusing on what they did to optimize working with media files and other data in the app.

Managing storage across Android versions

Android’s storage model has evolved to adapt to changing privacy considerations, leading to the changes in the storage system APIs. Let’s take a look at key platform changes that affected the legacy Viber implementation.

Media directories

Scoped storage changes the way that apps store and access files on a device's external storage. Viber needed to evaluate the differences between the existing app's storage model and updated platform guidelines, followed by gradual application changes to work with files in scoped storage. Therefore Viber invoked the requestLegacyExternalStorage flag to temporarily opt-out of scoped storage on Android 10 until the app was fully compatible.

In order to adjust their app experience to scoped storage, Viber now contributes public media files to well-defined media collections using the MediaStore API. This way, the files are accessible in a device gallery, and can be read by other apps with the storage permission. Private media files are stored in the app-specific directory on external storage and are accessed via the internal ContentProvider.

Storage permissions

The other notable update is related to changes in the storage permissions model: Apps in scoped storage have unrestricted access to their app-specific directories on external storage and can contribute to well-defined media collections without requesting a runtime permission. This change will help Viber provide more granular control to their users:

“This addition supports our efforts to provide our users with the best security and privacy solutions we can provide supported by the Android OS, users will benefit from this added security later without needing to opt-in. We also added a new ‘Save to gallery’ option allowing users to choose to make their photos readable by other apps or not. Because chats may contain private images or videos, it’s important to give users the ability to hide these files from the gallery. This change gives users additional control over the content included in their Viber messages.“ said Anton Novikov and Sergey Kozlov from Viber.

Accessing files outside of app-specific directory

Previously, Viber created and consumed files in a custom top level directory and depended on file path access. With scoped storage, saving app files to a top level directory became an anti-pattern, so Viber has followed best practices to update their implementation to store media files from the chats only in locations that are accessible in scoped storage.

However, to reduce the complexity of migration, Viber decided to keep their own top level directory for Android 10 and below, storing only the media files that are not exposed to the device’s Gallery app, while for Android 11 and above this directory is used in read-only mode to provide backward compatibility.

Another use case that Viber has been refining is sharing files in the chats. The updated storage runtime permission gives read access only to the images, videos and audio files that are available through MediaProvider. Starting from Android 11, the only way for Viber to access non-media files created by other apps is by using the Storage Access Framework document picker, which they had already utilized in a different part of their app.

App-specific files within external storage

In the scoped storage environment, app-specific directories on external storage are becoming private from other apps. This change has helped Viber leverage its use of external storage for storing private user files:

”We find change to app-specific directories to be useful, because it will help to ensure that personal chats are protected and backed with platform security.” said Anton Novikov from Viber. Learn more about how to access app-specific files.

Single interface to access storage

Because Viber targets a large audience running on Android 4.2 and above, they introduced an abstraction layer that aids them in managing storage access efficiently across all supported Android versions and with their use cases in mind.

Previously, Viber heavily used File API to access files, including files in legacy storage locations. Further, they stored absolute file paths for entries in the local database to keep the user's conversation history.

To standardize access to this conversation history and thus ensure that users don’t lose access to their files, Viber replaced absolute file paths with content URIs. In the new implementation, the app is accessing files only via content providers:

  • Internal FileProvider for Viber app-specific directories.
  • External file providers available in the Android framework, such as MediaStore or Storage Access Framework, or those belong to another app that shares files with Viber through Intent.ACTION_SEND.

By using a consistent ContentProvider layer, the ContentResolver gives the app a unified interface to access the file content.

This approach has also helped Viber optimize the network layer and define a universal Loader abstraction to upload/fetch and to read/store different types of media files like voice messages, chat images and stickers.


Android 11 further enhances scoped storage, which provides better protection of app and user data and makes the transition easier for developers. It’s amazing to see many apps like Viber are migrating to take advantage of scoped storage since Android 10.

We hope Viber’s story is useful and will inspire you to modernize your Android apps as well. Learn more about Android storage use cases and best practices.

Notifications from the Twitter app are easier on your battery

This blogpost is a collaboration between Google and Twitter. Authored by Jingwei Hao with support from César Puerta, Fred Lohner from Twitter, and developed with Jingyu Shi from Google.

Push notifications are an important way to keep Twitter users informed about what's happening. However, they can be a significant and often overlooked source of battery drain. For example: high priority notifications can wake a phone from Doze, and fetching data upon push notification delivery via the network can drain the battery quickly.
As app developers at Twitter, we know that battery life is an important aspect of the mobile experience for our users. Over time we've taken several steps to optimize our app to work with the power saving features, particularly around push notifications. In this article, we'll share what we did to save battery life on our users' devices in the hope this will help other developers optimize their apps as well.

Firebase Cloud Messaging migration

Earlier this year, we upgraded our notifications messaging library to the next evolution of GCM: Firebase Cloud Messaging (FCM). This gave us the ability to use the latest APIs and get access to the additional features Firebase has to offer.
This was a very unique migration for us for multiple reasons:
  • Push notifications are an important part of Twitter's mobile engagement strategy. Notifications help our users stay informed and connected with the world, and helped a man get his nuggs. Therefore, we couldn't afford having unreliable delivery of notifications during and after the migration, which would negatively impact the platform.
  • Since it's not possible to support both GCM and FCM in the application, we were not able to use typical A/B testing techniques during the migration.
We mitigated the risks by thoroughly testing across dogfood, alpha, and beta users for both migration and rollback paths, with real time metrics monitoring, and a staged app roll out. During the migration, we were pleased to find that replacing GCM with FCM worked smoothly in all our use cases.
Migrating to FCM proved valuable to us when testing against the power saving features on Android. With APIs like: getPriority() and getOriginalPriority(), FCM gave us insight into if the priority of FCM messages are downgraded.

Set the right FCM message priority

On the backend at Twitter, we always try to make sure that notifications are assigned with the appropriate priority, making sure that high priority FCM messages are only used to generate a user visible notification. In fact, a very small fraction of notifications we send are classified as high priority.
App Standby Buckets was introduced in Android 9 Pie, this feature impose restrictions on the number of high priority messages the app will receive based on which bucket the app belongs to. As a result, high priority messages should be reserved for the notifications users are more likely to interact with. Using high priority FCM messages for actions which do not involve user interactions can lead to negative consequences, for example: once an app exhausts its app standby bucket quota, the following genuinely urgent FCM messages will be downgraded to normal priority and delayed when device is in Doze.
To understand how our app performs with App Standby Buckets, we gathered statistics on the notification priorities at both send and delivery time for the Twitter App:
  • During our test, we observed that none of the high priority FCM messages were downgraded, especially for the 2% of devices which are bucketed in the frequent or lower bucket when the notifications are delivered. This is particularly worth noting since the system could potentially impose restrictions on high priority FCM messages for devices in low active buckets.
  • 86% of the devices were bucketed in the active bucket when high priority FCM messages are delivered. This is another positive signal that our priority assignment of the messages is consistent with the use pattern from the users.
This was very encouraging to see, as it means all users would receive the important notifications without any delay, and this is true no matter the app is considered active or not by the Android system. This also confirms that we are correctly categorizing high priority FCM messages based on our users usage engagement patterns.

Avoid follow-up data prefetch for notifications

Prefetching data is a popular practice to enrich the user experience around notifications. This entails including a piece of metadata within the payload of a notification. When the notification is delivered, the app leverages the payload data to start one or multiple network calls to download more data before the rendering of the notification. FCM payload has a 4KB max limit, and when more data is needed to create rich notifications, this prefetch practice is used. But doing this has a trade-off, and will increase both device power consumption and notification latency. At Twitter, among all the types of notifications we push to our users, there's only one type which does prefetching which makes up to less than 1% of the volume. In addition, in the cases where data prefetching for notification is unavoidable, it should be scheduled with JobScheduler or WorkManager tasks in order to avoid issues with the background execution limits in Oreo+.

Create notification channels

In addition, Notification Channels were introduced in the Android 8 Oreo release. We designed the importance level of the channels with multiple factors in mind, user experience being the most important and power-saving being another. Currently, Twitter for Android has nine notification channels, among which only direct messaging, emergency, and security are designed as high importance, leaving most of the channels with a lower importance level, making it less intrusive.


We set out to improve our user experience by migrating to FCM, prioritizing notifications cautiously, limiting prefetching, and carefully designing notification channels. We were glad to find that these changes had a positive impact on battery performance and enabled our app to take advantage of the power-saving features introduced in recent versions of Android.
Designing for power optimization in a large evolving application is a complex and ongoing process, particularly as the Android platform grows and provides more granular controls. At Twitter we strongly believe in continuous refinement to improve application performance and resource consumption. We hope this discussion is useful in your own quest to optimize your app's performance and use of resources ?

Android Developer Story: Papumba grows revenue globally by localising its family titles on Google Play

Posted by Lily Sheringham, Google Play team

Papumba is an educational games developer based in Argentina, with a core team of four people and a vision to grow a global business.

Watch Gonzalo Rodriguez, CEO, and Andres Ballone, CFO, explain how working with a team of experts from across the world and adapting their games to local markets helped them find success globally.

Learn more about localized pricing and translation services to grow your app or game business globally on Google Play. Also, get the Playbook for Developers app to stay up-to-date on new features and learn best practices that will help you grow a successful business on Google Play.