Task description
Being focused on automotive and mobility solutions, our Bamboo Apps team is constantly doing internal R&D projects intended for expertise growth. One of such projects called In-Vehicle Onboarding (IVO) allows users to get information about car capabilities and controls in a natural and convenient way. This product is being developed for Android Automotive OS.
The voice assistant feature is a key component of the project. It allows users to interact with the system using voice commands without having to physically touch the device and take their eyes off the road.
We planned to have an animation that would accompany the voice commands as part of the voice assistant feature. The task was to create a highly responsive and accurate voice-based animation that could be seamlessly integrated into Android and Android Automotive OS. It appeared quite comprehensive, and thus we separated it into a small sub-project.
Options to choose from
When it comes to adding frame-by-frame or tween animations to Android applications, developers have various options to choose from. With the rise of new animation libraries, such as Lottie, and the availability of tools like PaintCode, developers have more flexibility and creativity in designing and implementing animations in the code. Here, we will compare different approaches to using these new animation libraries and tools, as well as the existing GitHub libraries and custom views on Android Canvas.
Lottie Animation
Lottie is a library that allows developers to easily import Android animations into their apps. It uses vector graphics to create animations that are scalable and resolution-independent. Lottie animations are created using Adobe After Effects, which are then exported as JSON files and integrated into Android applications.
Lottie is a popular choice among developers, as it allows for high-quality animations to be created quickly and efficiently. But Lottie wasn’t the optimal choice in our case. The reason was, we wanted our Android audio animations to be tightly synced to the sound and make it obvious to the user what they represent. Lottie’s functionality wasn’t well suited for that.
Draw parameterized View
Another approach to creating animations is to use PaintCode. PaintCode is a tool that allows developers to create vector graphics and export them as code. Developers can use PaintCode to create custom views with animations that can be added to their Android application. But customization capabilities are quite limited especially in terms of the number of adjustable parameters, while the tool itself is paid.
An existing GitHub library
GitHub is an excellent resource for developers looking to add animations to their Android app. Numerous repositories on GitHub provide animations in various forms, including libraries, snippets, and templates. Developers can leverage these existing animations to add features to their applications quickly and efficiently.
Additionally, developers can use these repositories as a learning resource to understand how animations are implemented in Android applications. Unfortunately, after a certain time spent researching GitHub, no suitable third-party animation library has been found.
Custom view on Android Canvas
Finally, developers can create custom views on Android Canvas. This approach allows them to have full control over the animation’s design and implementation. Custom views are useful when the animation requires a high degree of customization and interactivity. Thus we’ve chosen it as the base solution for our project.
The implementation
In this chapter, we’ll explore the two types of animation that we focused on: wave and line animations. By using principles like Bezier curves and Fibonacci sequences, these can be both visually stunning and highly informative. We’ll dive into the technical details of implementing these Android audio animations, providing examples and code snippets along the way.
First of all, to imitate an audio effect, we need sound data to base the animation on.
This data can be obtained using either Android Visualizer or AudioTrack:
- Visualizer is based on the `Record Audio` feature. You can subscribe to get notified whenever any audio session is updated by ID.
- AudioTrack plays files in chunks, which can be configured individually.
Both approaches give us a byte array [-128..127] that reflects the values of the vertices along the y-axis in the equalizer picture.
You can get more info about Visualizer and AudioTrack in the Android documentation. Continue reading to see how we used them in our project.
The second step is to transform these values to get the desired animation.
Here we will briefly analyze 2 Android audio animation algorithms: line animation and wave animation.
Line Animation
The name might be a bit unclear so here is an example of line animation to make sure we’re all on the same page:
The algorithm here is based on the Fibonacci sequence. We can divide the Y-axis into chunks based on Fibonacci values: 1, 2, 3, 5, 8, 13, 21, 34. The number of chunks is the number of animated lines. Here is an example for 3 lines:
So now we can use the chart to calculate the number of the highest points in the corresponding chunk.
Since we have both positive and negative values, we can make the line animation asymmetrical. To achieve this, the left and right parts of it should be calculated separately.
As a result, the custom view can be configured with several parameters using an .xml file:
<eu.bamboo.speech_waves_animation.line.SpeechLineView
android:layout_width="match_parent"
android:layout_height="8dp"
app:baseColor="#1D4A76"
app:color1="#4493E2"
app:color2="#1A5B9C"
app:lineCount="2"
app:lineSpeed="slow"
app:symmetry="true" />
where:
baseColor
is the background color.[color1…color8]
defines the colors of each line starting from the middle to the edges.symmetry
is true – which means that animation is symmetrical.lineCount
is a number of lines from 1 to 8.
You can implement the same animation using Android code. XML version is mostly the only one you need to declare. And just update the audio data from the code.
Wave Animation
Let’s start with an example again:
The Bezier curve is a popular algorithm used in computer graphics and animation to create smooth curves. First, we need to understand the basics of the Bezier curve algorithm and how it can be used to create wave Android audio animations with existing extremums, which is one of its most popular use cases.
The Bezier Curve Algorithm
The Bezier curve algorithm is a mathematical formula used to create smooth curves. It uses a set of control points to define the shape of the curve. The curve is calculated based on the position and tension of these control points. This algorithm is commonly used in computer graphics and animation to create smooth transitions and movements.
Wave Animation with Existing Extremums
To create a wave animation with existing extremums using the Bezier curve algorithm, we first need to define the control points. The control points are used to define the shape of the wave. The x-axis represents duration, and the y-axis represents the wave’s amplitude.
Once we have defined the control points, we use the Bezier curve algorithm to create a smooth curve that passes through each control point. By adjusting the tension of the control points, we can create different types of curves. In the case of a wave animation, we want to create a smooth curve that follows the shape of the wave.
To add existing extremums to the wave animation, we need to adjust the control points’ tension around those anchors. This will create a sharp transition between the extremums and the rest of the wave. The result is a smooth wave animation that accurately reflects the shape of the wave.
Android Canvas
This wave algorithm is based on the calculation of the points for the cubic Bezier function supported by Android Canvas.
Calculating data for a single main line is enough. Other lines will use the same data but modify the y-axis points by applying the corresponding coefficients.
The result of the custom view is more complex. It can be configured with the following parameters:
<eu.bamboo.speech_waves_animation.wave.SpeechWavesView
android:layout_width="match_parent"
android:layout_height="70dp"
app:waveSpeed="normal"
app:endColor="#a9c6f4"
app:gradientOffset="0.1"
app:lineCount="4"
app:lineThickness="6"
app:middleColor="#151764"
app:middleLineThickness="3"
app:startColor="#656ED1"
app:density="0.2"
app:windowPadding="0.24" />
where:
startColor
is the main color of the Wave.endColor
is the color in phases where the wave is at _y = 0_.middleColor
is for the lines inside.lineCount
is the number of wave lines from 1 to 8.lineThickness
andmiddleLineThickness
change the thickness of the main and middle lines.density
defines how many waves are on a linewindowPadding
determines the size of the straight line at the edges of the animation, not affected by the wave.
Kotlin code
The Kotlin code for both animations is the same, we just need to provide the byte array to the animation view:
animationView.update(bytes)
Here, bytes
is an array from Visualiser, AudioTrack, or any other tool used to play or listen to the audio.
Conclusion
In summary, our project has benefited greatly from the solution we have developed. So we’ve decided to make it easy for others to develop wave and line Android audio animations of their own by having this sample go open source.
Thus, all the code used in this article is now available on GitHub. We encourage you to try it out and adapt it to your needs if you’re interested. We would also appreciate your feedback, so we can continue to refine and improve the solution together.
Author:
Katsiaryna Saroka
Android Developer