Tag Archives: Kotlin

Announcing Kotlin Multiplatform Shared Module Template

Posted by Ben Trengrove - Developer Relations Engineer, Matt Dyor - Product Manager

To empower Android developers, we’re excited to announce Android Studio’s new Kotlin Multiplatform (KMP) Shared Module Template. This template was specifically designed to allow developers to use a single codebase and apply business logic across platforms. More specifically, developers will be able to add shared modules to existing Android apps and share the business logic across their Android and iOS applications.

This makes it easier for Android developers to craft, maintain, and most importantly, own the business logic. The KMP Shared Module Template is available within Android Studio when you create a new module within a project.

a screen shot of the new module tab in Android Studio
Shared Module Templates are found under the New Module tab

A single code base for business logic

Most developers have grown accustomed to maintaining different code bases, platform to platform. In the past, whenever there’s an update to the business logic, it must be carefully updated in each codebase. But with the KMP Shared Module Template:

    • Developers can write once and publish the business logic to wherever they need it.
    • Engineering teams can do more faster.
    • User experiences are more consistent across the entire audience, regardless of platform or form factor.
    • Releases are better coordinated and launched with fewer errors.

Customers and developer teams who adopt KMP Shared Module Templates should expect to achieve greater ROI from mobile teams who can turn their attention towards delighting their users more and worrying about inconsistent code less.

KMP enthusiasm

The Android developer community remains very excited about KMP, especially after Google I/O 2024 where Google announced official support for shared logic across Android and iOS. We have seen continued momentum and enthusiasm from the community. For example, there are now over 1,500 KMP libraries listed on JetBrains' klibs.io.

Our customers are excited because KMP has made Android developers more productive. Consistently, Android developers have said that they want solutions that allow them to share code more easily and they want tools which boost productivity. This is why we recommend KMP; KMP simultaneously delivers a great experience for Android users while boosting ROI for the app makers. The KMP Shared Module Template is the latest step towards a developer ecosystem where user experience is consistent and applications are updated seamlessly.

Large scale KMP adoptions

This KMP Shared Module Template is new, but KMP more broadly is a maturing technology with several large-scale migrations underway. In fact, KMP has matured enough to support mission critical applications at Google. Google Docs, for example, is now running KMP in production on iOS with runtime performance on par or better than before. Beyond Google, Stone’s 130 mobile developers are sharing over 50% of their code, allowing existing mobile teams to ship features approximately 40% faster to both Android and iOS.

KMP was designed for Android development

As always, we've designed the Shared Module Template with the needs of Android developer teams in mind. Making the KMP Shared Module Template part of the native Android Studio experience allows developers to efficiently add a shared module to an existing Android application and immediately start building shared business logic that leverages several KMP-ready Jetpack libraries including Room, SQLite, and DataStore to name just a few.

Come check it out at KotlinConf

Releasing Android Studio’s KMP Shared Module Template marks a significant step toward empowering Android development teams to innovate faster, to efficiently manage business logic, and to build high-quality applications with greater confidence. It means that Android developers can be responsible for the code that drives the business logic for every app across Android and iOS. We’re excited to bring Shared Module Template to KotlinConf in Copenhagen, May 21 - 23.

KotlinConf 2025 Copenhagen Denmark, May 21 Workshops May 22-23 Conference

Get started with KMP Shared Module Template

To get started, you'll need the latest edition of Android Studio. In your Android project, the Shared Module Template is available within Android Studio when you create a new module. Click on “File” then “New” then “New Module” and finally “Kotlin Multiplatform Shared Module” and you are ready to add a KMP Shared Module to your Android app.

We appreciate any feedback on things you like or features you would like to see. If you find a bug, please report the issue. Remember to also follow us on X, LinkedIn, Blog, or YouTube for more Android development updates!

Android’s Kotlin Multiplatform announcements at Google I/O and KotlinConf 25

Posted by Ben Trengrove - Developer Relations Engineer, Matt Dyor - Product Manager

Google I/O and KotlinConf 2025 bring a series of announcements on Android’s Kotlin and Kotlin Multiplatform efforts. Here’s what to watch out for:

Announcements from Google I/O 2025

Jetpack libraries

Our focus for Jetpack libraries and KMP is on sharing business logic across Android and iOS, but we have begun experimenting with web/WASM support.

We are adding KMP support to Jetpack libraries. Last year we started with Room, DataStore and Collection, which are now available in a stable release and recently we have added ViewModel, SavedState and Paging. The levels of support that our Jetpack libraries guarantee for each platform have been categorised into three tiers, with the top tier being for Android, iOS and JVM.

Tool improvements

We're developing new tools to help easily start using KMP in your app. With the KMP new module template in Android Studio Meerkat, you can add a new module to an existing app and share code to iOS and other supported KMP platforms.

In addition to KMP enhancements, Android Studio now supports Kotlin K2 mode for Android specific features requiring language support such as Live Edit, Compose Preview and many more.

How Google is using KMP

Last year, Google Workspace began experimenting with KMP, and this is now running in production in the Google Docs app on iOS. The app’s runtime performance is on par or better than before1.

It’s been helpful to have an app at this scale test KMP out, because we’re able to identify issues and fix issues that benefit the KMP developer community.

For example, we've upgraded the Kotlin Native compiler to LLVM 16 and contributed a more efficient garbage collector and string implementation. We're also bringing the static analysis power of Android Lint to Kotlin targets and ensuring a unified Gradle DSL for both AGP and KGP to improve the plugin management experience.

New guidance

We're providing comprehensive guidance in the form of two new codelabs: Getting started with Kotlin Multiplatform and Migrating your Room database to KMP, to help you get from standalone Android and iOS apps to shared business logic.

Kotlin Improvements

Kotlin Symbol Processing (KSP2) is stable to better support new Kotlin language features and deliver better performance. It is easier to integrate with build systems, is thread-safe, and has better support for debugging annotation processors. In contrast to KSP1, KSP2 has much better compatibility across different Kotlin versions. The rewritten command line interface also becomes significantly easier to use as it is now a standalone program instead of a compiler plugin.

KotlinConf 2025

Google team members are presenting a number of talks at KotlinConf spanning multiple topics:

Talks

    • Deploying KMP at Google Workspace by Jason Parachoniak, Troels Lund, and Johan Bay from the Workspace team discusses the challenges and solutions, including bugs and performance optimizations, encountered when launching Kotlin Multiplatform at Google Workspace, offering comparisons to ObjectiveC and a Q&A. (Technical Session)

    • The Life and Death of a Kotlin/Native Object by Troels Lund offers a high-level explanation of the Kotlin/Native runtime's inner workings concerning object instantiation, memory management, and disposal. (Technical Session)

    • APIs: How Hard Can They Be? presented by Aurimas Liutikas and Alan Viverette from the Jetpack team delves into the lifecycle of API design, review processes, and evolution within AndroidX libraries, particularly considering KMP and related tools. (Technical Session)

    • Project Sparkles: How Compose for Desktop is changing Android Studio and IntelliJ with Chris Sinco and Sebastiano Poggi from the Android Studio team introduces the initiative ('Project Sparkles') aiming to modernize Android Studio and IntelliJ UIs using Compose for Desktop, covering goals, examples, and collaborations. (Technical Session)

    • JSpecify: Java Nullness Annotations and Kotlin presented by David Baker explains the significance and workings of JSpecify's standard Java nullness annotations for enhancing Kotlin's interoperability with Java libraries. (Lightning Session)

    • Lessons learned decoupling Architecture Components from platform specific code features Jeremy Woods and Marcello Galhardo from the Jetpack team sharing insights from the Android team on decoupling core components like SavedState and System Back from platform specifics to create common APIs. (Technical Session)

    • KotlinConf’s Closing Panel, a regular staple of the conference, returns, featuring Jeffrey van Gogh as Google’s representative on the panel. (Panel)

Live Workshops

If you are at KotlinConf in person, we will have guided live workshops with our new codelabs from above.


    • The codelab Migrating Room to Room KMP, also led by Matt Dyor, and Dustin Lam, Tomáš Mlynarič, demonstrates the process of migrating an existing Room database implementation to Room KMP within a shared module.

We love engaging with the Kotlin community. If you are attending KotlinConf, we hope you get a chance to check out our booth, with opportunities to chat with our engineers, get your questions answered, and learn more about how you can leverage Kotlin and KMP.

Learn more about Kotlin Multiplatform

To learn more about KMP and start sharing your business logic across platforms, check out our documentation and the sample.

Explore this announcement and all Google I/O 2025 updates on io.google starting May 22.


1 Google Internal Data, March 2025

Announcing Jetpack Navigation 3

Posted by Don Turner - Developer Relations Engineer

Navigating between screens in your app should be simple, shouldn't it? However, building a robust, scalable, and delightful navigation experience can be a challenge. For years, the Jetpack Navigation library has been a key tool for developers, but as the Android UI landscape has evolved, particularly with the rise of Jetpack Compose, we recognized the need for a new approach.

Today, we're excited to introduce Jetpack Navigation 3, a new navigation library built from the ground up specifically for Compose. For brevity, we'll just call it Nav3 from now on. This library embraces the declarative programming model and Compose state as fundamental building blocks.

Why a new navigation library?

The original Jetpack Navigation library (sometimes referred to as Nav2 as it's on major version 2) was initially announced back in 2018, before AndroidX and before Compose. While it served its original goals well, we heard from you that it had several limitations when working with modern Compose patterns.

One key limitation was that the back stack state could only be observed indirectly. This meant there could be two sources of truth, potentially leading to an inconsistent application state. Also, Nav2's NavHost was designed to display only a single destination – the topmost one on the back stack – filling the available space. This made it difficult to implement adaptive layouts that display multiple panes of content simultaneously, such as a list-detail layout on large screens.

illustration of single pane and two-pane layouts showing list and detail features
Figure 1. Changing from single pane to multi-pane layouts can create navigational challenges

Founding principles

Nav3 is built upon principles designed to provide greater flexibility and developer control:

    • You own the back stack: You, the developer, not the library, own and control the back stack. It's a simple list which is backed by Compose state. Specifically, Nav3 expects your back stack to be SnapshotStateList<T> where T can be any type you choose. You can navigate by adding or removing items (Ts), and state changes are observed and reflected by Nav3's UI.
    • Get out of your way: We heard that you don't like a navigation library to be a black box with inaccessible internal components and state. Nav3 is designed to be open and extensible, providing you with building blocks and helpful defaults. If you want custom navigation behavior you can drop down to lower layers and create your own components and customizations.
    • Pick your building blocks: Instead of embedding all behavior within the library, Nav3 offers smaller components that you can combine to create more complex functionality. We've also provided a "recipes book" that shows how to combine components to solve common navigation challenges.

illustration of the Nav3 display observing changes to the developer-owned back stack
Figure 2. The Nav3 display observes changes to the developer-owned back stack.

Key features

    • Adaptive layouts: A flexible layout API (named Scenes) allows you to render multiple destinations in the same layout (for example, a list-detail layout on large screen devices). This makes it easy to switch between single and multi-pane layouts.
    • Modularity: The API design allows navigation code to be split across multiple modules. This improves build times and allows clear separation of responsibilities between feature modules.

      moving image demonstrating custom animations and predictive back features on a mobile device
      Figure 3. Custom animations and predictive back are easy to implement, and easy to override for individual destinations.

      Basic code example

      To give you an idea of how Nav3 works, here's a short code sample.

      // Define the routes in your app and any arguments.
      data object Home
      data class Product(val id: String)
      
      // Create a back stack, specifying the route the app should start with.
      val backStack = remember { mutableStateListOf<Any>(ProductList) }
      
      // A NavDisplay displays your back stack. Whenever the back stack changes, the display updates.
      NavDisplay(
          backStack = backStack,
      
          // Specify what should happen when the user goes back
          onBack = { backStack.removeLastOrNull() },
      
          // An entry provider converts a route into a NavEntry which contains the content for that route.
          entryProvider = { route ->
              when (route) {
                  is Home -> NavEntry(route) {
                      Column {
                          Text("Welcome to Nav3")
                          Button(onClick = {
                              // To navigate to a new route, just add that route to the back stack
                              backStack.add(Product("123"))
                          }) {
                              Text("Click to navigate")
                          }
                      }
                  }
                  is Product -> NavEntry(route) {
                      Text("Product ${route.id} ")
                  }
                  else -> NavEntry(Unit) { Text("Unknown route: $route") }
              }
          }
      )
      

      Get started and provide feedback

      To get started, check out the developer documentation, plus the recipes repository which provides examples for:

        • common navigation UI, such as a navigation rail or bar
        • conditional navigation, such as a login flow
        • custom layouts using Scenes

      We plan to provide code recipes, documentation and blogs for more complex use cases in future.

      Nav3 is currently in alpha, which means that the API is liable to change based on feedback. If you have any issues, or would like to provide feedback, please file an issue.

      Nav3 offers a flexible and powerful foundation for building modern navigation in your Compose applications. We're really excited to see what you build with it.

      Explore this announcement and all Google I/O 2025 updates on io.google starting May 22.

What’s new in the Jetpack Compose April ’25 release

Posted by Jolanda Verhoef – Developer Relations Engineer

Today, as part of the Compose April ‘25 Bill of Materials, we’re releasing version 1.8 of Jetpack Compose, Android's modern, native UI toolkit, used by many developers. This release contains new features like autofill, various text improvements, visibility tracking, and new ways to animate a composable's size and location. It also stabilizes many experimental APIs and fixes a number of bugs.

To use today’s release, upgrade your Compose BOM version to 2025.04.01 :

implementation(platform("androidx.compose:compose-bom:2025.04.01"))
Note: If you are not using the Bill of Materials, make sure to upgrade Compose Foundation and Compose UI at the same time. Otherwise, autofill will not work correctly.

Autofill

Autofill is a service that simplifies data entry. It enables users to fill out forms, login screens, and checkout processes without manually typing in every detail. Now, you can integrate this functionality into your Compose applications.

Setting up Autofill in your Compose text fields is straightforward:

      1. Set the contentType Semantics: Use Modifier.semantics and set the appropriate contentType for your text fields. For example:

TextField(
  state = rememberTextFieldState(),
  modifier = Modifier.semantics {
    contentType = ContentType.Username 
  }
)

      2. Handle saving credentials (for new or updated information):

          a. Implicitly through navigation: If a user navigates away from the page, commit will be called automatically - no code needed!

          b. Explicitly through a button: To trigger saving credentials when the user submits a form (by tapping a button, for instance), retrieve the local AutofillManager and call commit().

For full details on how to implement autofill in your application, see the Autofill in Compose documentation.

Text

When placing text inside a container, you can now use the autoSize parameter in BasicText to let the text size automatically adapt to the container size:

Box {
    BasicText(
        text = "Hello World",
        maxLines = 1,
        autoSize = TextAutoSize.StepBased()
    )
}
moving image of Hello World text inside a container

You can customize sizing by setting a minimum and/or maximum font size and define a step size. Compose Foundation 1.8 contains this new BasicText overload, with Material 1.4 to follow soon with an updated Text overload.

Furthermore, Compose 1.8 enhances text overflow handling with new TextOverflow.StartEllipsis or TextOverflow.MiddleEllipsis options, which allow you to display ellipses at the beginning or middle of a text line.

val text = "This is a long text that will overflow"
Column(Modifier.width(200.dp)) {
  Text(text, maxLines = 1, overflow = TextOverflow.Ellipsis)
  Text(text, maxLines = 1, overflow = TextOverflow.StartEllipsis)
  Text(text, maxLines = 1, overflow = TextOverflow.MiddleEllipsis)
}
text overflow handling displaying ellipses at the beginning and middle of a text line

And finally, we're expanding support for HTML formatting in AnnotatedString, with the addition of bulleted lists:

Text(
  AnnotatedString.fromHtml(
    """
    <h1>HTML content</h1>
    <ul>
      <li>Hello,</li>
      <li>World</li>
    </ul>
    """.trimIndent()
  )
)
a bulleted list of two items

Visibility tracking

Compose UI 1.8 introduces a new modifier: onLayoutRectChanged. This API solves many use cases that the existing onGloballyPositioned modifier does; however, it does so with much less overhead. The onLayoutRectChanged modifier can debounce and throttle the callback per what the use case demands, which helps with performance when it’s added onto an item in LazyColumn or LazyRow.

This new API unlocks features that depend on a composable's visibility on screen. Compose 1.9 will add higher-level abstractions to this low-level API to simplify common use cases.

Animate composable bounds

Last year we introduced shared element transitions, which smoothly animate content in your apps. The 1.8 Animation module graduates LookaheadScope to stable, includes numerous performance and stability improvements, and includes a new modifier, animateBounds. When used inside a LookaheadScope, this modifier automatically animates its composable's size and position on screen, when those change:

Box(
  Modifier
    .width(if(expanded) 180.dp else 110.dp)
    .offset(x = if (expanded) 0.dp else 100.dp)
    .animateBounds(lookaheadScope = this@LookaheadScope)
    .background(Color.LightGray, shape = RoundedCornerShape(12.dp))
    .height(50.dp)
) {
  Text("Layout Content", Modifier.align(Alignment.Center))
}
a moving image depicting animate composable bounds

Increased API stability

Jetpack Compose has utilized @Experimental annotations to mark APIs that are liable to change across releases, for features that require more than a library's alpha period to stabilize. We have heard your feedback that a number of features have been marked as experimental for some time with no changes, contributing to a sense of instability. We are actively looking at stabilizing existing experimental APIs—in the UI and Foundation modules, we have reduced the experimental APIs from 172 in the 1.7 release to 70 in the 1.8 release. We plan to continue this stabilization trend across modules in future releases.

Deprecation of contextual flow rows and columns

As part of the work to reduce experimental annotations, we identified APIs added in recent releases that are less than optimal solutions for their use cases. This has led to the decision to deprecate the experimental ContextualFlowRow and ContextualFlowColumn APIs, added in Foundation 1.7. If you need the deprecated functionality, our recommendation for now is to copy over the implementation and adapt it as needed, while we work on a plan for future components that can cover these functionalities better.

The related APIs FlowRow and FlowColumn are now stable; however, the new overflow parameter that was added in the last release is now deprecated.

Improvements and fixes for core features

In response to developer feedback, we have shipped some particularly in-demand features and bug fixes in our core libraries:

Get started!

We’re grateful for all of the bug reports and feature requests submitted to our issue tracker - they help us to improve Compose and build the APIs you need. Continue providing your feedback, and help us make Compose better.

Happy composing!

Meet the Android Studio Team: A Conversation with Engineering Director, Tor Norbye

Posted by Ashley Tschudin – Social Media Specialist, MTP at Google

Welcome to "Meet the Android Studio Team," our new ongoing blog series. Each week, we'll introduce you to the talented people behind Android Studio. Get to know the engineers, designers, product managers, and more who create the best possible experience for Android developers like you. Join us and explore their unique perspectives.


Tor Norbye: Building Android Studio for You

Trevor Johns, Staff Developer Programs Engineer

Meet Tor Norbye, an Engineering Director at Google leading the development of Android Studio.

From his early days of coding to leading the charge on AI-powered development tools, Tor shares his insights on the evolution of Android and the vital role Android Studio plays in its future.

We'll delve into the challenges of creating developer tools, the importance of community feedback, and how Google strives to empower developers worldwide.


Can you tell us about your journey to becoming a part of the Android Studio team? What sparked your interest in Android development?

I grew up in Norway and I was fascinated by programming; my first exposure was as a middle schooler reading program listings in magazines (yes, in the early 80s, monthly computer magazines would include source code!) and in 1983 I got my hands on a microcomputer, and knew immediately that's what I wanted to do as a career. And now, 40+ years later, I still love programming. It's not my day-job anymore, but I still write bits and pieces of code for Android Studio on the shuttle and during quiet periods.

I've worked on developer tools my whole career - first, 14 years at Sun Microsystems after college. In 2010 I got increasingly interested in the rise of mobile computing and really wanted to be part of it, so I joined the Android team, and I've been here since.

Back then there was no "Android Studio". At the time we were working on Eclipse-based tooling for Android development. But we all knew that IntelliJ was the gold-standard for Java development, so a couple years later we began the work on building Android Studio on top of IntelliJ and with various new and ported code from our Eclipse plugins. I then had the honor of doing the unveiling demo at Google I/O in 2013.

How has the integration of AI and machine learning impacted Android developer capabilities, and how do you see it evolving in the future?

The integration of artificial intelligence has absolutely impacted Android developer capabilities, and this is just the beginning.

I felt very fortunate to be part of bringing about the massive shift from desktop computing to mobile computing when I joined Android, and I can't believe I get to be in the middle of a second massive industry shift as well, with AI and large language models.

I actually spend a lot of my time on this, working with Studio engineers, UX and product managers on our various AI related features, and talking to partner AI teams at Google. We've made a huge amount of progress in the last couple of years, both on the Studio feature integration side, as well as Google-wide on the AI side. While there is some skepticism that we're just doing AI features for AI's sake, I don't see it that way. With AI, we can suddenly, with relatively low effort, build useful features not previously possible.

Here's a very simple example from the latest Studio version: When you invoke the Rename refactoring feature, we use Gemini to add additional naming suggestions into the name popup based on what your code is doing. Here we're helping you pick good names – and naming is famously one of the two hardest problems in computer science – naming, cache invalidation and off-by-one errors. Yet LLMs are good at this – so coupled with the safe refactoring machinery in the IDE, we were able to safely add a useful feature with relatively low engineering cost on the IDE side (of course, this is building on top of a massive investment from Google over on the Gemini side).

The field is moving incredibly quickly, so it's hard to predict where things are going, but we're actively working in several areas, making the AI more aware of your codebase, and making it handle larger, complex tasks via AI Agents, and so much more.

What are some of the biggest challenges you've faced in your career as a developer, and how have those experiences shaped your approach to your job?

Earlier in my career, at a different company, we had big annual releases. I took a lot of pride in my productivity, and as my responsibilities grew, I'd try to do the impossible and deliver, no matter what. I'd not only work long hours, but I'd also try to work as quickly as I can. This led to a lot of stress. I remember putting my (at the time) young children to bed and impatiently waiting for them to fall asleep such that I could head back out to the garage office and start the evening coding shift. And I knew that stress isn't healthy, so I'd also stress about being stressed! This obviously wasn't sustainable.

Now, I emphasize work life balance not only for myself, but also for our team. I want to make sure our work is sustainable, and that people can thrive and be in it for the long term. It's a marathon, not a sprint.

Can you share an example of how feedback from the developer community has directly influenced a feature or improvement?

We have a number of feedback channels; the most important one is the Android Studio issue tracker.

We still have a very large backlog of bugs, so it's easy to get the impression that we're ignoring user reports, but that's not true. As a team, we've actually fixed several thousand bugs in 2024 alone. The best bugs are those that are clear and actionable, ideally with steps to reproduce.

I'm also very thankful to everyone who turns on data sharing in Studio; if you don't already, please consider it! Our analytics is more of an indirect, but still vital, feedback channel from the community. In addition to collecting information on, for example, which menu items are clicked, we also use it to collect quality metrics on system health. For instance, when we detect that the UI is lagging (such as a 1+ second freeze in the UI thread), we grab a thread dump and send it to the server, then aggregate these into a dashboard where we can see top freeze spots in the IDE across the user population, and can focus our efforts on fixing those.

How does the Studio team contribute to Google's broader vision for the Android platform?

In Android Studio we're always making sure we support the latest technologies and recommendations from Android, Firebase, Material, and other Google technologies. That way, it's easier for developers to adopt recommendations, like using Kotlin, Coroutines, Compose, Material, and so on.

Explore the Power of AI

Unlock the full potential of AI in your Android development journey. Explore the latest advancements in Android Studio, including intelligent code completion, automated refactoring, and other AI-driven tools.

Stay tuned!

Don't miss our next and final installment in the "Meet the Android Studio Team" series; we'll feature one more talented team member and share their unique perspective. Stay tuned to learn more about the amazing people behind Android Studio.

Find Tor Norbye on Bluesky.

Meet the Android Studio Team: A Conversation with Staff Developer Programs Engineer, Trevor Johns

Posted by Ashley Tschudin – Social Media Specialist, MTP at Google

Android Studio isn't just code and algorithms – it's built by real people with fascinating stories. Our "Meet the Android Studio Team" series gives you a glimpse into the lives and passions of the talented individuals who craft the tools you use every day. Tune in each month to meet new team members and discover their unique journey.


Trevor Johns: Building Android Studio for You

Trevor Johns, Staff Developer Programs Engineer

Meet Trevor Johns, a seasoned Staff Developer Programs Engineer at Google.

Reflecting on his journey, Trevor sheds light on the most impactful advancements in the Android ecosystem and offers a glimpse into his vision for the future where AI plays a pivotal role in streamlining development workflows.

Trevor discusses the Android Studio team's dedication to enhancing developer productivity through AI, highlighting their focus on understanding and addressing developer needs, and reflects on the dynamic journey of Android development while sharing valuable insights.


Can you tell us about your journey to becoming a part of the Android Studio team? What sparked your interest in Android development?

I've been at Google in various roles since Google since 2007, and transferred to Android team in 2009 shortly after the launch of the HTC G1 — the first publicly available Android phone. Even in those early days it was clear that mobile computing was a unique opportunity to reimagine many of the limitations of desktop computers and how users interact with the digital world.

Among my first projects were helping developers optimize their apps for the MyTouch 3G and Motorola Droid, as well as creating developer resources for Android's 1.6 Donut release.

Over the years, I've worked on various parts of the Android OS including our first tablet devices, Android Wear, helping develop the original Android support libraries (which later became Jetpack), and the migration to Kotlin.

Recently I joined the Android Studio team to help improve developer productivity, using AI to streamline common developer tasks and help developers have more time to focus on creativity.

How does the Android Studio team ensure that products or features meet the ever-changing needs of developers?

Like the rest of Android, we approach development of new features by listening to our developer community. We hold regular listening sessions with publishers, work with our UX research team to conduct case studies, and participate in online discussions to get a sense for where developers face the most friction — and then try to find ways to reduce that friction.

For example, we developed Gemini in Android Studio's integration with Play Vitals and Firebase Crashlytics based on feedback from members of the developer community who commented to let us know where they would find AI most useful across their developer workflow.

Speaking of, if you'd like to provide us with feedback, you can always file a bug or feature request on the Android Studio issue tracker.

How does the Studio team contribute to Google's broader vision for the Android platform?

In addition to listening to the Android community, we also keep an eye on what's being developed across the rest of the Android team and make sure that Android Studio has the right tools to help developers quickly migrate between Android versions and adopt those new platform features.

Beyond that, the Studio team provides leading edge editing tools to make sure that Android remains one of the easiest computing platforms to develop for — unlocking this unique computing platform for millions of developers.

In your opinion, what is the most impactful feature or improvement the Android team has introduced in recent years, and why?

For developers, my answer would have to be the migration to Kotlin. This language has modernized the Android developer experience — letting developers write apps with less code and fewer errors. It's also the foundation for Jetpack Compose, which is the future of Android UI development.

If you could wave a magic wand and add one dream feature to the Android universe, what would it be and why?

I'd love to see Gemini be able to not just autocomplete code for me, but generate scaffolds for new projects. That way I can focus on building features rather than worrying about basic structure when starting a new project.

Develop Android Apps with Kotlin

Follow Trevor's lead and embrace the power of Kotlin for modern Android development. Enhance your skills and write better Android apps faster with Kotlin.

Stay tuned!

Get ready for another inspiring story! The "Meet the Android Studio Team" series continues next week with a new team member in the spotlight. Don't miss their unique insights and journey.

Find Trevor Johns on LinkedIn, X, Bluesky, and Medium.

Media3 1.5.0 — what’s new?

Posted by Kristina Simakova – Engineering Manager

This article is cross-published on Medium

Media3 1.5.0 is now available!

Transformer now supports motion photos and faster image encoding. We’ve also simplified the setup for DefaultPreloadManager and ExoPlayer, making it easier to use. But that’s not all! We’ve included a new IAMF decoder, a Kotlin listener extension, and easier Player optimization through delegation.

To learn more about all new APIs and bug fixes, check out the full release notes.

Transformer improvements

Motion photo support

Transformer now supports exporting motion photos. The motion photo’s image is exported if the corresponding MediaItem’s image duration is set (see MediaItem.Builder().setImageDurationMs()) Otherwise, the motion photo’s video is exported. Note that the EditedMediaItem’s duration should not be set in either case as it will automatically be set to the corresponding MediaItem’s image duration.

Faster image encoding

This release accelerates image-to-video encoding, thanks to optimizations in DefaultVideoFrameProcessor.queueInputBitmap(). DefaultVideoFrameProcessor now treats the Bitmap given to queueInputBitmap() as immutable. The GL pipeline will resample and color-convert the input Bitmap only once. As a result, Transformer operations that take large (e.g. 12 megapixels) images as input execute faster.

AudioEncoderSettings

Similar to VideoEncoderSettings, Transformer now supports AudioEncoderSettings which can be used to set the desired encoding profile and bitrate.

Edit list support

Transformer now shifts the first video frame to start from 0. This fixes A/V sync issues in some files where an edit list is present.

Unsupported track type logging

This release includes improved logging for unsupported track types, providing more detailed information for troubleshooting and debugging.

Media3 muxer

In one of the previous releases we added a new muxer library which can be used to create MP4 container files. The media3 muxer offers support for a wide range of audio and video codecs, enabling seamless handling of diverse media formats. This new library also brings advanced features including:

    • B-frame support
    • Fragmented MP4 output
    • Edit list support

The muxer library can be included as a gradle dependency:

implementation ("androidx.media3:media3-muxer:1.5.0")

Media3 muxer with Transformer

To use the media3 muxer with Transformer, set an InAppMuxer.Factory (which internally wraps media3 muxer) as the muxer factory when creating a Transformer:

val transformer = Transformer.Builder(context)
    .setMuxerFactory(InAppMuxer.Factory.Builder().build())
    .build()

Simpler setup for DefaultPreloadManager and ExoPlayer

With Media3 1.5.0, we added DefaultPreloadManager.Builder, which makes it much easier to build the preload components and the player. Previously we asked you to instantiate several required components (RenderersFactory, TrackSelectorFactory, LoadControl, BandwidthMeter and preload / playback Looper) first, and be super cautious on correctly sharing those components when injecting them into the DefaultPreloadManager constructor and the ExoPlayer.Builder. With the new DefaultPreloadManager.Builder this becomes a lot simpler:

    • Build a DefaultPreloadManager and ExoPlayer instances with all default components.
val preloadManagerBuilder = DefaultPreloadManager.Builder()
val preloadManager = preloadManagerBuilder.build()
val player = preloadManagerBuilder.buildExoPlayer()

    • Build a DefaultPreloadManager and ExoPlayer instances with custom sharing components.
val preloadManagerBuilder = DefaultPreloadManager.Builder().setRenderersFactory(customRenderersFactory)
// The resulting preloadManager uses customRenderersFactory
val preloadManager = preloadManagerBuilder.build()
// The resulting player uses customRenderersFactory
val player = preloadManagerBuilder.buildExoPlayer()

    • Build a DefaultPreloadManager and ExoPlayer instances, while setting the custom playback-only configurations on the ExoPlayers.
val preloadManagerBuilder = DefaultPreloadManager.Builder()
val preloadManager = preloadManagerBuilder.build()
// Tune the playback-only configurations
val playerBuilder = ExoPlayer.Builder().setFooEnabled()
// The resulting player will have playback feature "Foo" enabled
val player = preloadManagerBuilder.buildExoPlayer(playerBuilder)

Preloading the next playlist item

We’ve added the ability to preload the next item in the playlist of ExoPlayer. By default, playlist preloading is disabled but can be enabled by setting the duration which should be preloaded to memory:

player.preloadConfiguration =
    PreloadConfiguration(/* targetPreloadDurationUs= */ 5_000_000L)

With the PreloadConfiguration above, the player tries to preload five seconds of media for the next item in the playlist. Preloading is only started when no media is being loaded that is required for the ongoing playback. This way preloading doesn’t compete for bandwidth with the primary playback.

When enabled, preloading can help minimize join latency when a user skips to the next item before the playback buffer reaches the next item. The first period of the next window is prepared and video, audio and text samples are preloaded into its sample queues. The preloaded period is later queued into the player with preloaded samples immediately available and ready to be fed to the codec for rendering.

Once opted-in, playlist preloading can be turned off again by using PreloadConfiguration.DEFAULT to disable playlist preloading:

player.preloadConfiguration = PreloadConfiguration.DEFAULT

New IAMF decoder and Kotlin listener extension

The 1.5.0 release includes a new media3-decoder-iamf module, which allows playback of IAMF immersive audio tracks in MP4 files. Apps wanting to try this out will need to build the libiamf decoder locally. See the media3 README for full instructions.

implementation ("androidx.media3:media3-decoder-iamf:1.5.0")

This release also includes a new media3-common-ktx module, a home for Kotlin-specific functionality. The first version of this module contains a suspend function that lets the caller listen to Player.Listener.onEvents. This is a building block that’s used by the upcoming media3-ui-compose module (launching with media3 1.6.0) to power a Jetpack Compose playback UI.

implementation ("androidx.media3:media3-common-ktx:1.5.0")

Easier Player customization via delegation

Media3 has provided a ForwardingPlayer implementation since version 1.0.0, and we have previously suggested that apps should use it when they want to customize the way certain Player operations work, by using the decorator pattern. One very common use-case is to allow or disallow certain player commands (in order to show/hide certain buttons in a UI). Unfortunately, doing this correctly with ForwardingPlayer is surprisingly hard and error-prone, because you have to consistently override multiple methods, and handle the listener as well. The example code to demonstrate how fiddly this is too long for this blog, so we’ve put it in a gist instead.

In order to make these sorts of customizations easier, 1.5.0 includes a new ForwardingSimpleBasePlayer, which builds on the consistency guarantees provided by SimpleBasePlayer to make it easier to create consistent Player implementations following the decorator pattern. The same command-modifying Player is now much simpler to implement:

class PlayerWithoutSeekToNext(player: Player) : ForwardingSimpleBasePlayer(player) {
  override fun getState(): State {
    val state = super.getState()
    return state
      .buildUpon()
      .setAvailableCommands(
        state.availableCommands.buildUpon().remove(COMMAND_SEEK_TO_NEXT).build()
      )
      .build()
  }

  // We don't need to override handleSeek, because it is guaranteed not to be called for
  // COMMAND_SEEK_TO_NEXT since we've marked that command unavailable.
}

MediaSession: Command button for media items

Command buttons for media items allow a session app to declare commands supported by certain media items that then can be conveniently displayed and executed by a MediaController or MediaBrowser:

image of command buttons for media items in the Media Center of android Automotive OS
Screenshot: Command buttons for media items in the Media Center of Android Automotive OS.

You'll find the detailed documentation on android.developer.com.

This is the Media3 equivalent of the legacy “custom browse actions” API, with which Media3 is fully interoperable. Unlike the legacy API, command buttons for media items do not require a MediaLibraryService but are a feature of the Media3 MediaSession instead. Hence they are available for MediaController and MediaBrowser in the same way.


If you encounter any issues, have feature requests, or want to share feedback, please let us know using the Media3 issue tracker on GitHub. We look forward to hearing from you!


This blog post is a part of Camera and Media Spotlight Week. We're providing resources – blog posts, videos, sample code, and more – all designed to help you uplevel the media experiences in your app.

To learn more about what Spotlight Week has to offer and how it can benefit you, be sure to read our overview blog post.

Google @ KotlinConf 2024: A Look Inside Multiplatform Development with KMP and more

Posted by Murat Yener – Developer Relations Engineer

Following our recent Google I/O announcement recommending Kotlin Multiplatform (KMP) for sharing business logic across mobile, web, server, and desktop platforms, and our move to use KMP in Google Workspace, KotlinConf 2024 was the next moment to share the highlights and connect with the Kotlin community.

Kotlin Multiplatform, developed by JetBrains, allows developers to build cross-platform apps by compiling Kotlin code into platform-native binaries while leveraging the full capabilities of a modern, memory-managed language. This approach has been a long-term investment for the Google Workspace team, enabling them to share the business logic between different platforms.

The Android team has been working to support KMP and recently released an alpha version of Room with KMP support. As of today, Annotations, Collections and DataStore are already in stable with KMP support . We've also commonified Lifecycle, ViewModel and Paging libraries to allow integrations with non-Android platforms.

Keynotes and Technical Sessions

The conference kicked off with a keynote, as part of which, Google’s Jeffrey van Gogh gave an overview of Google’s contributions to the Kotlin ecosystem. As part of this, Jeffrey delved into how Google leverages Kotlin Multiplatform (KMP) to streamline development across its own product portfolio. Jeffrey highlighted the benefits of code sharing and efficiency that KMP brings to Google's projects, aligning with our recent recommendations for Android app development.

Our technical sessions at KotlinConf 2024 span a range of topics:

  • A Tale of Two Languages by John Pampuch offered an engaging comparison of Java and Kotlin's evolution, highlighting their symbiotic relationship and mutual influence.
  • The Android Jetpack team, represented by Elif Bilgin, Yigit Boyar, and Daniel Santiago Rivera, unveiled Enabling Kotlin Multiplatform Success: The Android Jetpack Journey. They provided insights into the current state of KMP in Jetpack, shared updates on KMP-enabled Jetpack libraries, and explored the migration process of a well-established Jetpack library to KMP.
  • Going Fast with Kotlin by Andrei Shikov shared valuable insights gained from optimizing Compose for Android. Andrei highlighted interesting performance nuances in Kotlin and the guardrails the Compose team established to ensure optimal performance.
  • Kotlin Multiplatform in Google Workspace by Jason Parachoniak discussed Google Workspace's ongoing migration from a Java-oriented multiplatform foundation to Kotlin Multiplatform, aligning with Google's broader adoption of KMP. Jason shared lessons learned and the current state of this ambitious transition.
  • Write Your Own Kotlin Lint Checks! by Tor Norbye, Android Studio Engineering Director, empowered developers to extend Android Lint, a static analysis tool used by millions, by creating their own checks. Despite the name, it's not actually Android specific -- it's also used to analyze server Kotlin and Java code inside of Google!

Community Engagement at KotlinConf

We are always looking into ways to be actively engaged with the Kotlin community. If you attended KotlinConf, we hope you got a chance to check out our booth, with opportunities to chat with our engineers, get your questions answered, and learn more about how you can leverage Kotlin and KMP.

Learn more about KMP

In addition, you can view updated docs and a new mobile sample on KMP. These resources should have what you need to start learning KMP and if you have any feedback or come across any issues, please share them through this link.

Looking Ahead

We are excited about the future of Kotlin and are planning to add KMP support to more AndroidX libraries. We are looking forward to seeing how you will adopt and build the next generation of apps using KMP.

Thanks to KotlinConf organizers, speakers, attendees, and the entire Kotlin community for making this event happen and bringing Kotlin enthusiasts together.

Android Support for Kotlin Multiplatform to Share Business Logic Across Mobile, Web, Server, and Desktop Platforms

Posted by Maru Ahues Bouza – Director, Product Management, and Jeffrey van Gogh – Director, Engineering

Traditionally, developers must either write code individually for each platform they want to target, or make a number of compromises in order to reuse code across platforms. Android has been actively supporting Kotlin since 2017, and today we are excited to announce we are supporting Kotlin Multiplatform on Android, which enables sharing code across mobile, web, server, and desktop platforms. This helps increase productivity for developers, and fits great with Android's Kotlin-first approach, resulting in higher quality Android apps. Our focus is to support sharing business logic (the parts that are most agnostic to the user interfaces) because we've seen Android developers get the most value in not having to maintain duplicate copies of this code.

Kotlin Multiplatform (KMP) has been a long-standing investment for the team behind Google Workspace, allowing for flexibility and speed in delivering valuable cross-platform experiences. The Google Workspace team is enthusiastic about KMP's potential as the direction for its multi-platform architecture investment, confident in its ability to meet performance expectations for various workloads.

The initial step in this journey is the rollout of the Google Docs app for Android, iOS, and Web, which leverages KMP for shared business logic, validating its readiness for production use at Google scale. The Google Workspace team is thrilled to continue exploring the possibilities of KMP across its product suite, aiming to enhance productivity and deliver seamless experiences to users on all platforms.

We see a lot of companies successfully leveraging Kotlin Multiplatform for cross-platform development of their apps, learn how they apply different code-sharing strategies here.

Kotlin Multiplatform, developed by JetBrains, provides a novel approach to sharing code across platforms by compiling Kotlin to platform-native binaries. Kotlin is able to provide the full, modern, memory managed language to native platforms enabling native interoperability and incremental adoption. Kotlin on Android, combined with Kotlin Multiplatform on other platforms, provides a great way to increase productivity and quality, without compromising on performance or interoperability.

Architecture overview for Kotlin Multiplatform (KMP)
Kotlin Multiplatform Architecture

Current Status of Support

Many widely-used libraries offer built-in support for Kotlin Multiplatform, streamlining your cross-platform development experience. These libraries work seamlessly together. For example, Ktor simplifies networking tasks by handling REST service consumption, while kotlinx.serialization converts data to formats like JSON, and Okio manages essential file I/O. Additionally, SKIE facilitates the use of modern types and coroutines on iOS, and CocoaPods integration enables the use of iOS-specific dependencies.

We've worked with JetBrains and the Kotlin developer community to add Kotlin Multiplatform support to a number of Jetpack libraries and in some cases provide the iOS platform targets, while in others, JetBrains and the community provide the multiplatform distributions.

Today, the Annotations, Collections, and DataStore libraries all have support for Kotlin Multiplatform in stable versions. We are also adding support to validate binary compatibility for the iOS platform targets, bringing them on a par with the quality standards for Android. In addition to the libraries above, we've also begun working on Kotlin Multiplatform support for Room, Lifecycle, and ViewModels with alpha versions now available. To better understand which classes and functions are available where, the library reference documentation now indicates "common" and platform support.

Indication of Common, Native and Android support in documentation
Indication of Common, Native and Android support in documentation

Android engineers have collaborated with JetBrains on the Kotlin compiler to improve runtime performance in Kotlin/Native (for iOS & native desktop operating systems), showing 18% runtime performance improvements in compiler benchmarks. In addition the Android team contributed to build time performance improvements for the Kotlin Native Compiler of up to 2x speed ups.

The Android Gradle Plugin now has official support for Kotlin Multiplatform, enabling a concise build definition for setting up Android as a platform target for shared code as shown below:

plugins {
    id("org.jetbrains.kotlin.multiplatform")
    id("com.android.library")
}

kotlin {
    androidTarget {
        compilations.all {
            kotlinOptions {
                jvmTarget = "11"
            }
        }
    }  
    listOf(
        iosX64(),
        iosArm64(),
        iosSimulatorArm64()
    ).forEach { iosTarget ->
        iosTarget.binaries.framework {
            baseName = "Shared"
            isStatic = true
        }
    }    
    sourceSets {
        commonMain.dependencies {
            // put your Multiplatform dependencies here
        }
    }
}
KMP Support in the Android Gradle Plugin DSL

As Android Studio is based on the IntelliJ Platform from JetBrains, it inherits support for Kotlin Multiplatform code editing and many other development features. Other Android development tools like Android Lint and Kotlin Symbol Processing (KSP) are also beginning to add more Kotlin Multiplatform support as well.

Google Chrome now has official support for WasmGC which is used by Kotlin Multiplatform's WebAssembly platform target to enable code sharing with the browser in an efficient and performant way.

Latest details on these projects are available on the updated Android Kotlin Multiplatform page.

Future Areas of Work

We've heard from many Android developers and Google engineering teams that they want expanded support for Kotlin Multiplatform so they can more easily share code with other platforms. Android plans to continue collaborating with JetBrains, Google engineering teams, and the community on a variety of projects, including:

    • Expanding and stabilizing Jetpack libraries with Kotlin Multiplatform support
    • Wasm platform target support in Jetpack libraries
    • Kotlin/Native build performance
    • Kotlin/Native debugging
    • Expanding Kotlin Multiplatform support in Android Studio

Learn More and Try It Out

Sharing code with Kotlin Multiplatform between Android and other platforms enables higher developer productivity and quality so we hope you will give it a try! You can use the Kotlin Multiplatform wizard to create a new KMP project. Learn more in the documentation.

Alternatively, explore one of these sample projects showcasing how to use some of the Jetpack libraries with Kotlin Multiplatform:

If there are additional areas you would like Android to work on let us know and also be a part of our vibrant Android Developer community on LinkedIn, Medium, YouTube, and X.

Jetpack Compose compiler moving to the Kotlin repository

Posted by Ben Trengrove - Developer Relations Engineer, Nick Butcher - Product Manager for Jetpack Compose

We are excited to announce that with the upcoming release of Kotlin 2.0, the Jetpack Compose compiler will move to the Kotlin repository. This means that a matching Compose compiler will release alongside each release of Kotlin. You will no longer have to wait for a matching Compose compiler release before upgrading the Kotlin version in your Compose app. The Compose team at Google will continue to be responsible for developing the compiler and will work closely with JetBrains, our co-founders of the Kotlin Foundation. The version of the Compose compiler now always matches the Kotlin version. The compiler version is therefore jumping to 2.0.0.

To simplify the set up of Compose, we are also releasing a new Compose Compiler Gradle plugin which lets you configure the Compose compiler with a type safe API. The Compose Compiler Gradle plugin’s versioning matches Kotlin’s, and it is available from Kotlin 2.0.0.

To migrate to the new plugin, add the Compose Compiler Gradle plugin dependency to the plugins section of your Gradle version catalog:

[versions]
kotlin = "2.0.0"

[plugins]
org-jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }

// Add the Compose Compiler Gradle plugin, the version matches the Kotlin plugin
compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }

In your project’s root level Gradle file, add the plugin:

plugins {
   // Existing plugins 
   alias(libs.plugins.compose.compiler) apply false
}

Then in modules that use Compose, apply the plugin:

plugins {
   // Existing plugins
   alias(libs.plugins.compose.compiler)
}

The kotlinCompilerExtensionVersion is no longer required to be configured in composeOptions and can be removed.

composeOptions {
   kotlinCompilerExtensionVersion = libs.versions.compose.compiler.get()
}

If required, you can now add a top level section to the same Gradle file to configure options for the Compose compiler.

android { ... }

composeCompiler {
   enableStrongSkippingMode = true
}

You might currently directly referencing the Compose compiler in your build setup, rather than using AGP to apply the compose compiler plugin. If that is the case, note that the maven artifacts will also change:

Old

New

androidx.compose.compiler:compiler

org.jetbrains.kotlin:kotlin-compose-compiler-plugin-embeddable

androidx.compose.compiler:compiler-hosted

org.jetbrains.kotlin:kotlin-compose-compiler-plugin


For an example of this migration, see this pull request.

For more information on migrating to the new Compose compiler artifact, including instructions for non-version catalog setups, see our updated documentation.