Categories:
Search articles

Search for articles

Sorry, but we couldn't find any matches...

But perhaps we can interest you in one of our more popular articles?

Android app performance: Animation and Media (part 2)

Nov 18, 2020

Codemagic builds and tests your app after every commit, notifies selected team members and releases to the end user. Automatically. Get started
How to build native Android apps on Codemagic

How to build native Android apps on Codemagic

Use codemagic.yaml file to keep your build configurations more organized and manage all your workflows
Read more

Written by Sneh Pandya

Human brains are naturally wired to process visual information faster and more precisely than text-based information. In the previous article, we talked about the app size and Gradle/YAML optimizations for Android apps. In this article, we will see how to improve performance and optimize your apps for animations and media playback.

Animations

Animations improve the visual appearance and experience for your end-users. Animations become useful when you want to display UI changes, transitions, or a specific state of your app.

Types of Animations on Android

Transition animations

The Transitions API framework allows layout changes within an activity. Introduced in Android 4.0, they animate transitions of a view, an Activity, or a Fragment.

Property animations

This is the most popular type of animation, introduced in Android 3.0. It is used to change the properties of an object. Property Animations can change the state as well as behavior.

View animations

These are used to perform simple animations, like changing the size, position, and rotation of the view. They are easy to build but are slower and less flexible than Property Animations. The problem with View Animations is that though the View state changes, its property still remains in the original position.

Best Practices for Animations on Android

1. Avoid the use of multiple independent animations

We can perform multiple animations on a single view using the animator set, but this comes with performance overhead, including the processing overhead of setting up the AnimatorSet and running two Animators in parallel. A better approach is to use ViewPropertyAnimator.

2. Make use of new Motion System Guidelines

The container transform pattern is used when the transition includes a persistent container (buttons, lists, or cards) that transitions into a detailed view. Similarly, fade through, fade, shared axis, and other patterns that are included in the new Motion System Guidelines will make your life easier!

3. Retain item position for SharedElementTransition

When working with RecyclerView, it’s not enough to simply add a listener for images. An item position of RecyclerView where the transition starts from is also needed. When the user goes back to the previous screen, compare the loaded image position with the retained position at the listener, and start the transition only when they are matched.

4. Understand image loading properly

When working with SharedElementTransitions, Glide tries to optimize image loading and resizes and trims images to match the target view. This introduces a glitch while the transition is in progress. To remove this glitch, apply dontTransform() like this:

Glide.with(target).load(url).apply(RequestOptions().dontTransform())

5. Use fragments appropriately

When using SharedElementTransition, always specify a parent fragment that will call the transition methods for all the rest of the fragments. If you directly use the fragment specified in the container and specify postponeEnterTransition() or startPostponedEnterTransition(), it may not work.

6. Design your own animations

Created by Alex Lockwood, ShapeShifter is a great tool for designing your own animations and using them in Android. The basics are easy, and you can find them here.

7. Strike a balance between text and animations

Do not go overkill on your app by adding too many animations or a particular screen. This distracts users and might not be suitable for a seamless user flow. Strike a balance between hints, animation, and text wherever needed. Users need to understand which actions they can perform by looking at the animations.

8. Create a design system

It is always a best practice to define the visual hierarchy for your entire app. Users will have an unpleasant experience if every other screen has different animations or transitions. Ideally, the transitions should be kept the same throughout the app for the same components, i.e., all the activity transitions should provide the same transition experience throughout the app.

9. Use the latest image formats

Using the latest image formats, like WebP, for static images and drawables converted from SVG for vector animations, etc., will save a lot of space and resources, as they are smaller in size, adaptable, backward compatible, and optimized.

10. Test your apps thoroughly

Android devices vary a lot in screen size, resolution, screen ratio, pixel density, frame rate, and so on. It is important to test your animations, transitions, and other visual components across devices and API versions supported by your app to identify pitfalls, glitches, ANRs, and any other unpleasant experiences before you publish your app for your end-users with a bunch of animations and transitions. Remember, seamless experience becomes crucial when working with visual animations and transitions.

11. Learn from the best

The Android Framework Team makes consistent efforts to update the developer documentation and samples on their GitHub repository, which you can take a look at and learn from. They implement the projects with best practices, specifying methods and implementations that make the animations robust and beautiful at the same time. You can explore the repository here, which includes multiple samples for all types of animations.

Media

Providing a seamless media playback experience for your users is crucial. Media playback on Android consumes system resources, such as memory, audio/media controls, codecs, and more. This can degrade the performance of your app and possibly the entire device if not handled correctly. Below are the performance strategies and steps that will help you build robust and more beautiful experiences for your users.

The 4-Step Process to Show Media Control Notifications

  1. Create a media session for your service.
val mediaSession = MediaSessionCompat(this, MyAppMediaPlayerService);
  1. Declare a media style for your media notification.
val mediaStyle = Notification.MediaStyle().setMediaSession(mediaSession.sessionToken)
  1. Build a notification and display your media player controls.
val notification = Notification.Builder(this@MyAppMediaPlayerService, YOUR_CHANNEL_ID).setStyle(mediaStyle).build()
  1. Add user actions for your media player notification.
val pauseAction: Notification.Action = Notification.Action.Builder(pauseIcon, Pause, pauseIntent).Build()

notification.addAction(pauseAction)

Manage Audio Focus Automatically

More than one Android app can play audio to the same output stream simultaneously. In this case, the Android framework mixes everything together—giving users an unpleasant experience.

When your app needs to play audio, it should request audio focus. However, after the app acquires audio focus, it may not be able to keep the audio focus until it is done playing the audio. Another app can request focus, which preempts your hold on the audio focus. If that happens, your app should pause playing or lower its volume to let users hear the new audio source more easily.

Making use of this new feature is very simple with SimpleExoPlayer and can be done in just three steps!

  1. First, create an instance of AudioAttributes for your use case. For example, if you’re playing a movie:
// class com.google.android.exoplayer2.audio.AudioAttributes

AudioAttributes audioAttributes = new AudioAttributes.Builder()
 .setUsage(C.USAGE_MEDIA)
 .setContentType(C.CONTENT_TYPE_MOVIE)
 .build();
  1. Call setAudioAttributes with the second parameter set to true.
simpleExoPlayer.setAudioAttributes(audioAttributes, /* handleAudioFocus= */ true);
  1. SimpleExoPlayer will automatically manage audio focus for you. Your app does not need to include any code for requesting or responding to audio focus changes!

If your app is playing a podcast or an audiobook, it would be better to pause it than to continue playing it more softly, which could be distracting. For that, setContentType to CONTENT_TYPE_SPEECH, and SimpleExoPlayer will pause while the notification is playing and will automatically resume afterwards.

Best Practices for Media Playback on Android

Here’s a summary of key learnings and best practices for building products and apps that focus heavily on media streaming and media playback:

1. Keep screen on

It might sound obvious that notifying the Android system about media playback, especially video playback, is a vital step. When the video playback begins, specify setKeepScreenOn(true), and specify setKeepScreenOn(false) either when the user leaves the screen or when the playback has completed.

2. Add picture-in-picture mode

Android Oreo (8.0) and above support picture-in-picture mode, where two apps can run side by side or one over the other when video playback is in progress. It lets the user watch a video in a small window pinned to a corner of the screen while navigating between apps or browsing content on the main screen.

3. Sense and switch orientation

If your app allows the user to switch between landscape and portrait modes, make sure you use sensor orientation instead of the hardcoded regular orientation. For example, in SCREEN_ORIENTATION_SENSOR_LANDSCAPE mode, the screen will rotate to adjust the orientation according to how the users are holding the device. This is extremely useful and seamless for users watching videos or charging their device or who just prefer to hold the phone in a certain manner.

4. Pause on headphones removal

When headphones are unplugged, the Android framework publishes an ACTION_AUDIO_BECOMING_NOISY broadcast. Make your app listen to this broadcast when your audio/video playback is ongoing, and take appropriate action, like pausing the playback, so as not to surprise the user with audio from the speaker.

5. Support device, peripheral, or system volume keys

Users are habituated to using the volume keys provided by the device manufacturer and Android framework to control the volume of audio/video playback. Don’t swim the wave and create your own volume controls. Most headphones/earphones have volume and media control keys. Users naturally interact with these keys, and they expect the keys and peripherals to work seamlessly with your app. Create a MediaSession to export your media information and media state, like play, pause, skip, volume controls, etc., which then can be consumed by not only headphones but also devices like Google Assistant, Google Home, Android Auto, Android Wear, external Bluetooth speakers, etc.

6. Support adaptive streaming and playback

If you are providing functionalities like media streaming over the network and/or offline downloads, the best thing you can ever do is provide an adaptive stream of your audio/video, with which your end-users can switch the quality or resolution of playback. Ideally, low-, medium-, and high- or HD-quality options for playback or offline downloads are a good feature, especially for mobile devices. Remember, not everyone has stable or high-speed connectivity. Your user retention will grow, and your users will thank you for this!

Conclusion

Building media-rich experiences has become one of the core elements of mobile app development. Animation and media are both powerful and provide excellent user experiences when implemented properly. The information in this article should help you build such experiences for your end-users, ultimately growing your retention and ratings.


Sneh is a Senior Product Manager based in Baroda. He is a community organizer at Google Developers Group and co-host of NinjaTalks podcast. His passion for building meaningful products inspires him to write blogs, speak at conferences and mentor different talents. You can reach out to him over Twitter (@SnehPandya18) or via email (sneh.pandya1@gmail.com).

How did you like this article?

Oops, your feedback wasn't sent

Latest articles

Show more posts