Android Dev Summit 2018 Livestream | Day 1, theater 2

Coming up next: Getting the Most

Out of Android Lint by Matthew Gharrity SPEAKER: Howdy,

welcome to another Android developer summit! So how many people went to the last one? How many people enjoyed the last one? We liked it here, which is why we did it immediately again three years later. We were just building suspense to make it extra special. Hopefully we can do it again. A lot of this content, all of the — most of the content is live streamed, all of it is being recorded. If you prefer consuming this through a live stream, I can pause occasionally and buffer and maybe that will make it more of a live stream situation for you. I’m Che it, I — Chet, I lead the toolkit team, I’m emceeing today. And I

am making it a nice enough event, but short enough so you are not tired of the emcee. I will tell you how this thing is going to work today So Dan went over some of it, and I assumed you went over the keynotes as much as I do The most important to me is office hours, there are two reasons why we like to have these events in Mountain View, it is such an interesting city with so much to do, we live here, and every day we are here So obviously, Mountain View, for the culture And the second reason is Google is just up the street, which means we can drag a lot of engineers from the team that build all of the bugs that you are now dealing with into the product, and we like to bring them into the conference to help answer all of your questions The key thing for you to know, though, is all of those people aren’t here all day We have broken up the event into four half-day sessions, and there are different people in different teams in different technoloies represented at different times And so there are three scheduled posted, there are screens around the conference. This is one of the screen sscreens, if you can’t read this, maybe you can read the screens outside the room instead. There’s a rotating schedule, will tell you when people are on where, if you have a question for the location team, make sure you are at the right time. You can skip sessions if you want, they are recorded, and there are people in all of those sessions. So ask the right questions, find people, they are here at the right time. There’s App Review clinices, there’s the hashtag on Twitter, #AndroidDevSummit, there’s the application. And if you don’t have it, it is an instant app. Do your favorite search in the search engine, click on the link if — for the instant app and it downloads instantly. There’s a party tonight after the session after 6:00, that will kick in, a party with a bunch of engineers, where we all have the excellent experience of talking to each other while the DJ is playing the loud music and having conversations that go along the lines of, what! What! Enjoy the party, enjoy those deep conversations with the new friends, that’s about it. And one more thing, there are three different session links There’s the long session, 40 minutes. There are shorter sessions of 20 minutes. The intention is to link these things, you will go for both of them at one slot. It is awkward to get up in the middle of a crowd, so we are about to see two in a middle here. Please stick around for both of them, if you need to get to one on the other side, try to do so quickly and quietly, we are going to roll from one into the other And then there’s lightning talks that start at 12:05 and will run for an hour, those are going to go back to back into each other So stick around for those And that is about it. I’m standing in the way between you and technical content. I would like to bring up Matthew Gharrity to talk about Lint Thanks [ Applause ] MATTHEW GHARRITY: All right, let’s get started I’m Matthew, on the Android Studio team, I work on project stability, call integration, and we will go to the next slide And one of the most exciting things I get to work on besides project stability is Android lint. It is a very powerful tool, you know a lot about it, but you might not know the cool things it can do So despite the name, it is not just a linting-tool, it is a full-fledged stack analytics framework, it is powerful, you can write your own checks and I will talk about that today No worries This talk is really for anyone really interested in programming languages, compilers, stack

analysis, and for anyone that has to deal with bugs in the project. So that is for most of you Yeah, one last thing, I only have 20 minutes, there’s a lot of material, I will go fast through the slides. Try to keep up. At the end of the day, you can watch it in half speed on YouTube and get a sense of it then Perfect All right, let’s get started So what is Android lint? A lot of you probably already know, if you don’t know the name, you know what Android lint is. It shows up in the IDE saying that you did something wrong. In some cases, it is like telling you that Gradle is out of date, do you want to update it, or maybe you are not calling a super method in a method that expects you to do so. In Android Studio, in the IDE, it will say that there is suspicious code, take a look Sometimes there are warnings, sometimes there are errors that will fail the builds So some of you might not know it, there’s a lot of the ways to use Android Lint. The first is on-the-fly, that I just mentioned, in the IDE as you are typing, shows the error messages right away. You can also do inspect code, this is an action in Android Studio where you can run a batch analysis of the project, a good way to audit your project for common errors And an action called run inspection by name. If you have a particular bug in mind, say you want to find a lot of thread annotation violations, you can run the inspection by name, run the entire projects in one batch analysis and look through those one pie by one. You can run Lint on the command line with Gradle, Gradle Lint debug, it will do a batch analysis for the project. And the great thing about that is it will make an html and XML report. You can parse the XML report, or you can do the html report and do the warnings If you know what Lint is, I want to dive into the advanced use cases, because it is a powerful tool. I will talk about configuration, and it is actually really important. For big projects, you want to make sure that Android Lint is working for your projects and needs. I will talk about annotations, it is a powerful way to mark up your code to help Lint help you more. Lint does as much as it can, but sometimes you need to give it hints to help you more. We will talk about Lint internals, I’m excited about this, I want to give you a good mental model for how it works under the hood This will get you set up for kind of realizing how powerful a tool it is and writing your customcustom Lint chuck schecks We will talk about configuration. The easiest way to see what Lint is capable of, Android Studio, preferences, inspections window You will see the heading, Lint, and all of the inspections that lint has. There are are hundreds, most are enabled by default. There are some that are not, and take a look at them, some of them may apply to your project, even though we don’t enable them by default One example is call interoperability, this is a set of checks we created so you can call it from link code and vice versa. If you do something that makes it difficult, Lint will

tell you to re-name the function so it is easy to call from the other language. There is another way to configure Lint, with Gradle. If you go into the Build.gradle file, you have this Android block, as you know. You can write a Lint options block, and there are powerful options here So this first option, I will go through a few examples. This first option is a powerful tool, if you have a big project, you want to pay attention to this The Lint baseline, when you add this to your options, Lint will look at all of the warnings and errors you currently have in the project. And this will give you a clean slate, so you can say, hey, I want to take a baseline of this point of the project, forget about all of the thousands of warnings that I already have. And I only want to look at new warnings and errors and new code that checks it. And this will help you get a handle on the massive amount of code that you have so you can have clean code going forward When you have more time, free time, you can knack go back and look at the baseline issues that Lint stashed away. Once you have a clean slate, through a baseline, or you want to do a new project, you want to say, I want to have clean code forever, starting now, you can turn on warnings as errors. I encourage you to try it out. And if you want clean code, try to get this to work for you. And then, like in the last slide, you can enable specific checks that are not on by default, like interopability. Some of you may have this Lint options block set up. And some more advanced things I want to talk about is performance issues So one of the reasons we have this lint Lint options block is a lot of people run Lint on the continuous integration server, they are checking the application for warnings, errors, they block Lint submit if you have it checked in. And some people are concerned with performance So just a few tips here, real quick Try to avoid the check all warnings option, I know it is tempting. I know I told you to enable more checks, but some of the checks are off by default for performance reasons, for example. If you check all the warnings, man, my time to check the project just doubled. Be more selective in the checks that you turn on Also avoid the Gradle lint tasks, it is a parent task of Lint debug or release. It will run it multiple times on the project in each Lint variance, that’s a simple gotcha to avoid Use the ignore test sources function. By default, we don’t look at the test sources for warnings or errors, the theory that you don’t care about how clean your tests are. But this option makes it so you don’t parse your test sources at all So presumably, all of you have well-tested code. So this option will help with that, to make things go faster Let’s switch gears a bit, I want to talk about annotations They are a really powerful way to live Lint hints for specific issues that you want to look for And so, I’m just going to go for a few examples, you know about the nullability annotations, you use it a lot in Java, you don’t need them, it is built into the language But we also have really Android-specific annotations, that you should check out There’s the required permission, this is an interesting example, we kind of annotate certain Android APIs with requires permission, like the set wallpaper permission, and Lint does analysis on the code that calls into the API, is the program checking that they have this permission? If you don’t, we can worry, hey, it looks like you have not checked you have this permission, this may crash at runtime. And this impacts the users quite a bit. There is also one of my favorites, kind of annotations, which is UI thread and worker thread annotations, there’s thread annotations in url And these are really important, actually So a lot of — a big problem with application development is a lot of UI frameworks require that you only up Tate the UI on a single thread, the network thread, and everything else is on background threads. If it is on the UI thread, it might block, you will not see a crash report, the user is frustrated, it is hard to track these issues. We have these threat annotations where we say these method should only be called on the UI thread, or the worker thread. And we have some

analyses. So I will actually do a demo of these analyses Hopefully that is set up So let’s switch over Awesome So I will go through an example This is just Kotlin, let’s say that we have a function, oh, the screen is black. You’re right It was there for a second Awesome. Let’s get started. We have a function, update UI, this is run on the UI thread. This is updating the user interface, whatever you want, and the network request. This is a contrived example And this does some stuff All right, and unfortunately, someone decided to call a network request from the update UI method. So this is a problem, as you can see. There is no errors or warnings, and studying this is hard to track down in general. If you know about the threat annotations, you can add the UI thread here, you can add the worker thread annotation here. And instance instantly, Lint says you are making a worker request on the UI thread, that freezes the UI, you don’t want that. So I encourage you to use these. And you might think, this is a trite example. This is too simple In the application, we have the UI method that calls the function, FU, and that function calls something called bar, and then that bar function calls the network request There is just multiple layers of indirection here. And you might think that Lint cannot help us here. It can’t be default, it for performance reasons, we don’t do advanced analyses. We have an analysis for this. I will show you an example of that. You can do run inspection by name. The name of the inspection is called wrong thread, and then interprocedural. You select that, select the scope, I will say module scope. And bam, it will find the path from Fu to bar to network request. You cannot see the error message right here, so I will copy it for you. I will remove the class names, you can see the error message says, hey, you are doing the UI, going to fu, bar, the network request, that is annotated with worker thread and that is an issue. Let’s go back to the slides So please check that analysis is off by default for — it is being performant and doing a program analysis, pretty expensive. Use it when you can, try to see if you can find any bugs in the application All right NERBS next I will talk about Lint internals. This part is really cool The way Lint works, it starts out parsing a source file, so you have some Java or Kotlin laying around, it builds abstracts syntax tree, and then we wrap it in UST, universal Syntax Tree, and this may sound pretty familiar. And this step is really important because it means that when you write a check, you only have to write it once, it works in both Java and Kotlin. That is really convenient. When you write a Lint analysis, you are writing directly on the UAST. When you are writing the Lint check, you are scanning the AST for the source code, calls, and expressions you are interested in and that is how it works And Lint actually works on all types of files, so you can look at Gradle files, you can look at XML files and resources. This is powerful, it gives a wholistic view of your application and can provide a lot more helpful messages with that A couple more points here, so type information is available It is not just — you are not just looking at text, you have the whole AST, you can do method

resolution, examine the class hiarko of of the class you are looking at, that is important for preventing false positives and having powerful Lint checks That is what makes Lint useful We have tight integration with the IDE. And Lint does show you the warning messages right in the IDE. That is critical, if you don’t have that, a lot of your messages are lost in some build-up somewhere and it is not useful to most people And so, with that, we are going to move into writing custom Lint checks. This means that, you know, Android Lint is a framework. You can write your own Lint checks. If you have something that annoys you, a common bug that you run into on your team, or something that you want your colleagues to watch out for, you can run your own Lint check, upload it to the code base, and all of your colleagues will see in the I it DE this highlighted And Lint has an unstable API, we don’t promise that we keep it the same from release to release. The good news is that it is not changing too often, but no promises The other good news is that unstable APIs are really fun to play with All right. And with that, we are going to move into the demo So let’s switch over, awesome All right So don’t bother reading code too much The example I want to set up here is that you see that your call logs are calling thread.yields. If you look at the documentation, there ask is not a useful method. If you are running concurrent data structures, it is useful. But in other ways, you want to avoid it. It doesn’t do what you think it does. So let’s say we will write our own lint check that calls thread.yields. So right now, it is not highlighted, there are no Lint checks yet. I want to show you how I have this set up. You have an Android application module here, here it is called app. The way you will write your on Lint checks, you will have a Java module, checks, for example. And you are going to add a dependency from your Android application to the checks module And we have this nice Lint checks block here that makes it easy to do that. Once you have that set up, and I’m skipping over some of the details here, but I’m going to have some links at the end. I can look at sample projects. Once that is set up, I can go to the Lint check itself. You have a class, yield detector. This is a detector for calls to thread.yields, it extends some classes in the Lint framework, and I have typed up some of the metadata for this check that we want to have. There’s a name, brief description, and explanation for how to fix the issue, the severityseseverity, whether it breaks the build, etc. And once I have the metadata, I’m going to start typing some code here So one method to be aware of is called Git applicable method names So the way lint works is, you know, there’s a couple options You can make your own AST scanner, which will give you total control. You can scan the source file, looking for whatever you want. And for performance reasons, we have these hooks where you can register with Lint, hey, I’m only interested in method calls with this particular name. And so here, we are actually only interested in method calls with name yield And if I have any typos, it is not going to work. So let me know Haha Once you have the hook in place, we have to write the hook itself. So here, we can say visit method And I wil will make sure that is — this method is only called when we come across a yield function call. We will say, okay, let’s assert that the method name we are looking at is actually yield. So this should always be the case And then, because we have type information, we can do due diligence and making sure we don’t have a false positive here. Maybe there’s another class with a function called yield, and we want to make sure that the Java link thread.yield So we will check to make sure we is have the methods, look at the evaluat evaluator, is the method in class, we will pass the revolve method node and give it the class name. So So this means that if this method that they are callingging is part of the exact class, we can record the error And, I will give it the issue that holds the metadata we have above. I will give it the node, I will give it

the locations. We are telling Lint, this is where the error is, what you should highlight And I think I have to give it a message So let’s say, please don’t use this And also, you should use a more helpful error message All right That’s all it takes If I have no typos, I’m going to make the projects It looks like it is done. If I go back to our application, bam, lint scanned the source code, picked up the check right in the IDE. And this is powerful. You can make it pop up for your colleagues and everything Awesome, we will go back to the slides All right So 50 seconds left, happy with the timing here Here are some links, I want you to check them out. If you never read the overview on the development page, go there, there’s a lot of information from this talk and a little bit more Please check out the annotations page, there are so many that can prevent a lot of bugs ahead of time If you are really excited about this demo I just gave, check out the sample project on GitHub, where you can run custom Lint checks. If you have an issue, we have a Lint mailing list Many of you know Tor, he is active on the mailing list and I am, too. We answer all of the questions that are asked there And with that, thank you so much If you have any questions, I don’t — don’t ask them now, I wills will be in the sandbox afterward. Please check out custom Lint checks. Thanks [ Applause ] Coming up next: Testing Rebooted (with AndroidX Test) by Yuki Hamada, John Gerrish SPEAKER: Good morning, everyone. Great to see so many people here interested in testing My name is John Gerrish, with my colleague Yuki Hamada, we’re presenting a session on testing APIs today To get started, hands up, anyone who has written unit tests. It is not a trick question, good And what about integration tests? You can be honest Awesome Okay So let’s get started Click SPEAKER: I have a question while you are setting up. Is this related to the project languages? SPEAKER: There’s a project nitrogen talk tomorrow, it is near the end of the day. I strongly encourage CHERK checking it out. The topic we are introducing today is part of the grander vision, along with project nitrogen, and they work in con conjunction Any more questions? We can do this in reverse [ Laughter ] SPEAKER: I will ad-lib this On Android, there are two kinds

of tests you might be familiar with. There’s local unit tests, and then there’s instrumentation tests. So let’s start by looking at local unit tests So these are ones that — these are tests that are executed on your local developer’s workstation, on the local VM running there And, because you don’t need to run the entire Android build chain, to avoid dexing, packaging, installing on the device, these tests are actually really, really fast. And on these kinds of tests, you can use a tool like robolectric, which comes with its own set of testing APIs to set up the state for your Android aenvironment, or use a tool like Mokito and you can step out the interactions with the Android framework. And either way, they allow you to write tests, setting up the state of the environment that satisfied the preconditions that you might want in your test case The second kind of tests are instrumentation tests. And these are the tests that will run on a virtual, or a real, device. A real device could just be a phone connected to your workstation, or if could be a form of devices somewhere in the cloud These kind of tests run slower because you have to execute the whole build chain and install an application on to the device But they have the advantage of being a lot more accurate, because the real lure of a virtual device is very similar, or in some cases identical, to devices your users are using out until the field. And this brings you the confidence your app will behave as expected One criticism we heard, on these tests, there’s a lack of testing APIs available. And that makes it difficult for you to set up the state of your environment in a way that satisfies certain preconditions, or edge cases, that you might want to be testing. We heard you loud and clear, this is something that we are actively working on So a bit of a history less on, 2017, Android I/O, we wrote out the testing story, the software development pyramid. In this model, we encouraged you to write lots and lots of fast, scalable unit tests that tested all of your exhaustive conditions. We encouraged you to write a smaller number of instrumentation tests that will actually prove that all of these units assemble together, behave as you would expect, on a real device And, in some ways, this was kind of a compromise. It was a compromise between the advantages of one set of — one kind of tests, and the tradeoffs of another. It brings you a wholistic way of testing your app And we showed how this kind of approach can lead to test-drivern development on Android First of all, you would start with a failing UI test. This would be an instrumentation test, probably written with Espresso, and it would test the UI of your component, or your feature. And then you would satisfy that feature by a series of units, classes, coming together that are interactions And you could test drive these as well, using a tool like roboelectric, or Mokeyto, as a unit test. And this gives you fast development cycles. When you bring them all together, you can run the slower-running, but faithful, instrumentation test and hopefully it goes green and you’re done Well, we enter a refactoring cycle because maybe your code leaves a little to be desired and you want to do some clean-up. You can spend some refactoring cycles there before coming around to the beginning of the cycle where if you have any more work on the feature, you might add another test, test another aspect to the that feature. And you will keep iterating until you are complete, at which time you are good to submit your code and move on to the next task So at Google I/O this year, we realized there was somewhat of a

test writing crisis And because there’s so many tools available, it is not always clear which one to use And each of these tools all have their own different styles and APIs and paradigms for the same concepts that exist on Android And the problem with this is that tests written in different levels are not portable across levels, it is stuck in the environment that you have written on. So this year, in Google I/O, we announced the render next test, it brings in testing as part of the tool chain, as part of Jetpack. It includes some of the existing libraries you’ve used before, some new APIs, full Kotlin support, which allows you to run beautiful and concise tests. It is available on and off device Well, last week, AndroidX test moved out of beta into release, 1.0. And it is also, as of last week, fully open-sourced. So we look forward to welcoming your contribution contribute — contributeutions All of it is being revamp ed to show you the new styles of APIs. So please go and check that out Let’s take a look inside The first module that we pulled across was the existing JUnit for support, the runner and the rules that you may have used before We’ve already added a new module, which we call core This includes some new APIs: ApplicationProvider, as its name suggestsZsuggests, is a quick and easy way to get a hold of the application context ActivityScenario, which is a brand-new API that provides a course and fine-grained activities, and FragmentScenerio that provides a set of testing features for fragments We also brought Espresso into the AndroidX family. It is a set of view-matching libraries — a set of view matching APIs and actions, allowing you to match and interact with those UI elements It also includes some other things like the ability to capture intents for the system And finally, we’ve also released some truth Android extensions And truth is Google’s open source, fluent testing assertions library And we brought a bunch of components for Android subjects , which allow you to test your Android objects beautifully and concisely And those of you who have been using roboelectric will know that we had a version, 4.0, in beta for a while And, as of last week, we did a simultaneous release that has now gone into final Roboelectric four fully supports all of the unified APIs that are in AndroidX test, as well as a number of its own new features and improvements Okay. So I would like to welcome Yuki on stage, who will give a deeper dive into some of the APIs available IA [ Applause ] SPEAKER: Thanks. Hi, everyone So let me introduce our new API This starts with ApplicationProvider, a new way of accessing context from your test support. So when you look on Android testing, you need to handle two different context objects. The first one comes from application under your test, and the second one comes from the instrumentation APK, where your test code is stored So with today’s library, we have

two different methods to access this context object. And this makes your test code harder to understand, because the library used, targets the context meaning the context from your instrumentation APK, while, sorry, the target context means that context from your application while get-context means the context from your instrumentation or APK also — it is not obviously which one to use for your tests So, in our new API, we hide the instrumentation context from target API, and we only — only the ApplicationProvider provides an application context in the form of your application graph And let’s take a look at the example So here, let’s say we have a test for the location tracker activity. And in the set up method, we get the target context in the old-fashioned way, and we type cast the location tracker application, so that we can reduce the mark object for testing, and the second line, set a mark object for that. This code is simple, and it actually works. But you could use the run context and face the runtime error, and ended up with wasting your time for debugging Now, with the new way, application context provider provides your context in the application graph So you can do exactly the same thing, but there is less chance for confusion Okay And let me move on to the more complicated stuff, activity scenario Actually, before I — we dive into it, I have a few questions for you. How many of you have written your own activity, and handled the live cycle transitions by yourself? Raise your hands if you are. And how many of you have shifted your activity with a bug related to life cycle? Many of you. Who didn’t write the tests for that? Who did not write the tests? Cool Well, yeah, I see some hands up, keeping up. And to be honest, I do, too. And I agree Writing tests for the activity life cycle transition is pretty hard, and there is no good API in the testing library now So that’s why our team have sought for a solution, and we developed the ActivityScenario, which you can use it for driving your activity state to laboratory state for testing So let’s visit the activity state first So the creative state is where activity is created, and instantiateinstantiated. But it is not visible to users yet Or activity, sorry, can be created state, while it is running in background And the started state is where the activity is created and started. It is partially visible to the users, but not the fore ground of activities The activities running in picture mode is also in this state And the the resumed state is where the activity state is visible to users and running in the fore ground And under the framework, you can change the life cycle state anytime the user interactions, so the activity has to handle those transitions properly for a good user experience, otherwise you see some bugs. And activity scenario provides a method moveToState, where you can move it to testing. We will look at the testing code. We have a test, location Tracker Activity, and here we want to verify that location listener is properly registered from the system when the activity becomes a creative state So across, we have to start the activity. The launch activity takes your activity graph and it

starts the activity and waits for it until it becomes a reasonable state And move to state initiates the transition, and moves the life cycle state to the created state. And the older method, the older ActivityScenario method works as a broken code. So after this method call, it is guaranteed that activity’s life cycle state to be created And then you can inspect your activity’s internal state by calling activity method. Yes, that is easy, and now we have our API And also you can use ActivityScenario for testing the creation of your activity. So activity creation happens when your activity is running in background for a long time and where you can come back to it later. And your activity has to save its internal state, to a saved instance state bundle, where it is destroyed, otherwise you will lose the state. We have a re-create where you can use the testing scenario. This is the example code So here, in this test, we wanted to make sure that input text is restored properly after the activity is re-created after disruption So first, we have some test data, like test user, as our input. And again, we started the activity. And then we input — we filled the text box by u using the Espresso library The ActivityScenario works nicely with Espresso, and we call re-create, which disrupts the activity, re-creates the instance, and waits for the activity to be a reasonable state. And using the Espresso again, we can make sure that the text is there as we expected Yes, it is also simple Okay. And finally, I would like to show you one more example from the Truth extension Intent Subject, by using Intent Subject, you can verify your Intent values and it produced really good schema-friendly error messages, if that error happens This testing example, again, this time, we want to make sure that Intent — we want to make sure that the data intent has an expected contact name in extras So first, we create a bundle of the data intent. And then we start with three lines, one is checking if that intent has the expect action, the second is type, and the third is extra bunted bundles. If the value does not meet the expectation, you see this error. And you can immediately know the, in this example, the intent action is not what you expected And there’s a lot of components that come under the release 1.0 I cannot show you everything today. For example, we have more assertions, and we also have Android Builders where you can create your testing data easily. And also scenarios for activity and fragment. You can look at the documentation to see more. I hope you try it out after the talk Okay, so this is our solution for the test writing crisis So with unified API, you no longer consider whether you have to write an instrumentation test because you can now just write the Android test, and that test runs on both runtime environmentsenvironments nicely With the unified API, you can focus on what to test and you can forget about where and how, and to ensure the contistancy of the behavior of our API, we have a verification test and we run the same tests against the, sorry, we run the same test on locally with Robolectric and on a bunch of devices from the API 15 to

the latest version And let’s go back to the workflow that we showed you earlier in this talk So we can execute the test driven development much more effectively using the device agnostic tests, with the tests, writing it in a unified API As a recommendation, we recommend that you write that test with Robolectric until the call is ready to submit, and run the same test, but on a battery of devices before you submit the test to maximize your confidence And also, you can run the same test as a continuous integration test against the binaries With the upcoming nitrogen tool change, you can set up such a configuration easily If you want to know more about the Project Nitrogen, we have a session tomorrow, and we highly recommend that you attend it Thank you very much for listening, and have a happy testing [ Applause ] Coming up next: Optimizing User Flows through Login by Sean McQuillan, Jeremy Orlow SPEAKER: Hey, everybody. With that interstitial music, the point is to make you really happy for when the next presentation starts. We will do lightning talks that we have not done before. We will see how well it works. The way it is supposed to work, we are going to roll from one into the other They have 5 minutes to go, when it is up, I will call time. In the back, they are going to press a magic button that makes this sound So that’s how we know it is time for the next talk. And otherwise, I have no purpose being here. I will talk about the next speakers, optimizing user flows through login, and I will start my timer Thunderous applause for the lightning talk, please!

[ Applause ] SPEAKER: Welcome to lightning talks, I’m excited to talk to you today about how to welcome your users to your Android app whether you when you get a new phone. Why is this important? On the Android system, we get a new phone every 2 or 3 years and we reinstall the apps that have been installed, and all of the users do this as well. If you buy a new phone every two years, half of your users are going to get a new phone this year. And if you don’t do anything at all with the application, you will give them a cold welcome when they come back. You will show is them an email and a password form that shows them that they have never used it before, you will disrupt the flow of the app. You want to welcome them back to the application and create the continuous user experience that jumps from their old device to the new device, so you don’t have friction or retention problems for these users that are switching devices and using your application There’s a couple products you can use in Google that help you do this. So one of them is Google sign-in, it is a button you press when you log in. It is a button you press, you log in, it is amazing for the flow because it makes it simple to do the log in. It is good for the activation because it makes it easier to log into the app. In your phone, it is good for reactivating the users because they have to click a button. On Android, you can configure it so you don’t can have to click the button on the new device Google sign-in works on iOS, Android, as well as the web. So you can use it everywhere, and it is a great way to add federated log-in to your application And another feature on Android is Smart Lock for passwords. It is a password manager, stores user names and passwords, federated credentials in the cloud, when the user confirms they want to save the password after they log in. So in the old phone, they save the password, on the new device, in the application, you will give them a warm welcome and say, I know who you are, do you want to log in with the new account? And it will create the seamless experience and log the user into the application. One of our partners, Netflix who is here today, they used this and they found that they had 20 percent fewer support requests. If you think about this, every time a user contacts you to get a user name and password fixed, there are five that didn’t, and they will just become a retention problem and may never come back This is a great way to improve your business metrics And Autofill is another feature we launched in Android O, works like smart lock. It is an Autofill system, it Autofills TextViews the way you would think, and one of the most common ways is user names and passwords. After they log into the old device, they will choose to save it to the Autofill service, that comes to the same data store, smart lock. In the new device, it Autofills There’s a few ways to get the application ready for Autofill One is to set up a digital asset link that links the web and the Android app. This is great, it has pluggable password manager and all of them support this and then the user can log in on the web. If they are using the same password manager on the Android device, they are go to going to get the credentials transferred And then the password is saved and you get the seamless experience to the Android application. And another thing you have to do for Autofill, you should set up Autofill hints Tell the service what the user name and the password field is, and that way the service does not have to guess and maybe get it wrong, probably the worst experience you can give your users. And the last thing we are going to talk about is auto back up, I will hand it over to Jeremy SPEAKER: It is a great way to also provide continuity to your users And so even if your app syncs to the cloud, there are still device specific settings you can back up, and no user who has been using your app for a year wants to see a tutorial on how to launch an app on the new phone. So auto back up, when the phone is idle, we back up to the cloud, the data is stored securely, you can have up to 25MG, if you go over that, the back ups fail. On the new phone, when the user restores the app, it will restore the data before the app runs for the first time. And the user picks up where they left off without any friction or churn And you can also include and exclude specific files, so you can exclude OAuth tokens, and keep users engaged when you

switch phones. We will be back in the back [Gong ringing] SPEAKER: Be around if you have any questions Coming up next: Kotlin + Watch Faces by Jeremy Walker SPEAKER: Hi, I’m Jeremy Walker, a developer platform engineer here at Google. I wanted to talk to you about how I use Kotlin to make watch face creation much easier on Wear OS So watch faces are kind of hard right now, and you have to write about 600-plus lines of code, it is not like a nice app you do in Android or iOS, where you declare the UI in the XML format, you have to manually paint everything, and then you have to include a bunch of code so when you are in ambient mode, you are not hurting the battery life. I was trying to think of how to improve this. Last year, we launched the support for Kotlin. So I thought, how can I use Kotlin to make it easier? I converted the whole thing to Kotlin, which reduced the code lines a lot. But I found something else with Kotlin that made it more cool, and that was something called DSL So what is Kotlin DSL? Well, the best way to understand what domain-specific language is to compare it to a regular programming language So, again, domain-specific lang language, that did not really help me what it meant. If you compare to a general programming language, Kotlin or Java, you have a bunch of key words and classes and languages, and you make a big app, on the other side is a DSL that focuses on a task or domain. It foregoes a lot of functionality and allows you to do that specific task You probably used external DSL and have not realized it. For example, SQL, for manipulating databases, that is a DSL. Those are expressions for manipulating strings. They have an independent syntax, reduce functionality, you don’t have methods or a class to make them work. You are not going to write a full-on application in them, either, at least I hope not. And for SQL, the first key word indicates as a verb what you are going to do. You are going to select and update. The disadvantage is you have to put it as a string literal. You have to pray and hope that you spelled everything right until run time, it fails and you have to see what is going on. And Kotlin DSL, it extracts that out the string and puts it in the code so you can have type checking, you can have code hint and all of that good stuff that comes with your IDE So now that I have an idea of what it is, I like to show you two structures really quick And I used the latter, there is one called creating ones for chain method calls, and the other is nesting of Lambda. So recognizing DSL is really subjective. You know it when you see it. So let’s see some So this is Kotlin DSL for SQL You can probably look at it, and if you know SQL, you can understand it right away And it is all words, like Slice, then I select all, group by,ords order by, and limit. This is all type-checked, you get code hinting so you don’t spell anything wrong. This is great and understandable, this is DSL The DSL for the watch face that I liked is the nested Lambda structure. So this is to create a watch face, you can see it right there, create a watch face is a verb. If you look at the structure, you may not know anything about making a watch face, but you probably understand what is going on right away. Analog watch face, it is not digital, it has arms Colors, the dimensions for the hand, the hour, the minute, the second, I understand that. And watch face background image, that is all — it is very declarative, you can understand it right away. This is type checked, and I get code hints and all of that good stuff. In the end, I get this nice little watch face with no work. And the 600 lines, they did not go away I put them in a helper class and combined them with the more important class that interprets the DSL. If you are making a watch face, you only need to know about the DSL So what is next? I — this is kind of an experiment that I did as a code a lab, check it out, it will take eye you 15 minutes to make a new watch face, search for Google codelab, it is under the Wear OS, search under Kotlin You can see how to make a watch face, you can see the source code for how I made the transition between DSL and interpreted it into a nice little watch face. And more importantly, hopefully now you are a little bit interested in DSL, you can use it in a project to make it better, or you can go and use something like the DSL

for SQL, for testing, or in html in the Kotlin coding type checked. So thank you for the talk, for letting me talk, and hopefully I have gotten you a little bit interested in DSL Thank you [ Applause ] Coming up next: Push Notifications: An India Perspective by Amrit Sanjeev SPEAKER: Well down, no gong Next up, push notifications SPEAKER: I’m Amrit, a developer advocate at Google. I want to talk about push notifications and how interapp developers are getting the delivery higher in the region. I want to talk about a stat in India, we have 314 million-plus smartphone users, growing on a 16 percent year on year growth rate, your apps have a chance for users and great business in the region, and it comes with a lot of competition. There’s a need to have a better engagement as well as lighting your users. And push noteification is one of the mechanisms a lot of developers use to engage your users. And when it comes to push delivery ratess some in India affect the delivery. Until recently, data plans were expensive and people have the habit of turning off mobile data when they are not using the internet. So when they go out the WiFi zone, they will turn the mobile data off, and that changes the behavior of time to lift parameter for the push notification, if you have a short one and they turn the data off during that period, the notification is never delivered Recently, new carriers have come in and reduced the data costs drastly, and now those behaviors are changing, but not enough for you to ignore that change Secondly, a lot of devices with custom behavior, or Android builds, where your notification and, because of battery optimization, they kill off the notification services. They sometimes force close the apps, and avoid the app for never getting the notification delivered to it. That is another problem And then your time to parameter, if you actually increase it by, say, from four to-eight eight hours, you see a drastic improvement, or a large improvement, in notification flivverdelivery. You might go over the WiFi user. So that makes it interesting. And in any other region, notification frequency also, the number of notifications that are sent to the users is affected and people get irritated and turn off notifications if you do it too many times. So collapsible keys and things like that are very important here And I want to talk about three design patterns that developers are actually trying out for querying use cases to improve the notification delivery. One is buffering the notifications, to give you understanding of your use case and how the buckets work better for you The neckinism developed here, there’s a period job that runs, refreshes the npm token, sends it to the server, when the server gets the data, it maps the fcm and the update. When it you send out oo cap — a campaign, they split it based on recently. And you put in the first batch based on what is in the last 7 days, the next batch is to update it from 7 to 31 day said, all the tokens from the 7 to the 31 days, and the third is 31 is above. And what this allows us, in each of these buckets, the parameters for each of these buckets will improve notfication delivery, you have a better understanding of which users get the notification and might react to your notification better. And because you have a lot of tokens, which are not updated frequently, or the users never send that update cycle, you don’t end up calculating that in peer notification delivery and you miscalculate the effectiveness of push notifications The second one is basically where you have, again, a job that comes in. It checks whether a notification was delivered to the device from the last one or not. If not, it will go to a service, an RS service in the notification to the user And you have to ensure that this does not wake up the device This is not the most efficient way of doing things, but it still works. And the last I will call out is data messages in the scenario. In the case you want to send a message, there’s a sale that is going to start at 12:00 you want to show the message at 12:00, and your users are 20 percent more on

this service. Instead of senting at — sending at 12:00 and hoping that the users receive it, they will send it two days before, which as a data message. So the app will receive it, and then based on the schedule that is within the data message, they will schedule a job to come up at exactly the right time to display the message to the user SPEAKER: That is time’s up SPEAKER: [Gong] SPEAKER:Coming up next: Understand the impact of Generic System Images (GSI) by Hung-ying Tyan SPEAKER: Hello, I’m Hung-ying, I’m talking about GSI, the generic STIMP system images It is the purest form of Android framework that we can build from AOSP. By purest, it does not have a device maker or carrier customization You will want to ask — AOSP has been there for 10 years. Why does it become a thing right now? It is because GSI is the central piece in travel compliance. So remember the project travel, we took out the Android updateability prom in trial. We architected between the flame work and the hardware original vendor implementation With this, we no longer need to update the vendor implementation with the Android framework This reduces the time for the device maker to update their Android framework Now, to make sure that the boundary is not altered by device makers at will, we require every treble-certified device to pass a series of CTS and VTS tests with the Android framework replaced by GSI. So with all of these powerful tools in place, about a year ago, we started to see the momentum of faster Android adoption this year So let’s take a look at the Android developer program at Google iOS last year. Only Nexus and Pixel forms were able available for you to try out Android Oreo. And fast forward one year later at Google I/O this year, it was the first time we had non-Google phones join the beta line up. It is not one, it is not two, it is seven device makers joining us So the progress was phenomenal We know we are on the right track, and we will continue to push for it Now, despite that GSI is the central piece in Treble compliance, we feel like it has a lot more potential than that So we set up a goal to make GSI be more accessible and useful, not just for device makers, but also for the general public Including app developers like you, and even consumers An important first step toward that goal is to make GSI available in AOSP So, for this, we have published pie GSI in AOSP, so you can download and build the pie GSI today. We are exploring ways to make future GSI available earlier than the release of the next Android version So you will be able to try out next century version earlier than GSI And, at the same time, we can get early feedback from you. So the benefit is mutual So please stay tuned for our further announcement on this Finally, we understand that

trying out GSI can be cumbersome sometimes We are looking into different ways to improve the process Right now, we have an idea of trying out GSI without actually flashing GSI out to the device But I’m not going into detail here. We do have a working early prototype at our demo booth In addition to that, we also prepare a set of devices. They are all running on the same pie GSI i. So please do check out our demoes at the Android platform sandbox SPEAKER: Thank you SPEAKER: Coming up next: Buiding Reliable Apps When Connectivity Is Unreliable by Naheed Vora, Ryan Hamilton SPEAKER: Hi, I’m a product manager at Android checkativity SPEAKER: I’m Ryan Hamilton, a manager on the Chrome networking team SPEAKER: So we will start with the — how many of you have noticed this in the last few years? The signal is flaky and you turn off the WiFi Connectivity keeps changing underneath you, and the application is trying to understand what is going on underneath, is really complicated And, for creating a good experience, we need to hide this complexity from the user. We don’t want users to go and turn off their WiFi in order to use the app. It could be any app that you can think of that the user is using at a given point in time So who should care? If you are building a user-facing application, maybe your app depends on mobility Maybe it is Google maps, or something like that. Or you are building a gaming application or communicating app. Anytime you know you need to react really, really fast, irrespective of what is happening in the activity is critical. This is important to make, that you address this point in your application And one thing I would add here is that the user dropoff rate with had when the delayss are 1-3 seconds, or 10 seconds, it may vary in markets. If you are in a market that is emerging like India, it may be resilient to delays. If you are in the United States, if you go beyond three seconds, you will lose the user So what I have here is a demo And it is a Google assistant demo, what we are doing is we are using the technology and we will talk about that a little bit later. On the left-hand side, there is no optimization on the phone. On the right hand side, there’s an optimization, and we are doing a Google assistant query and the user is walking out of the building The phone is connected to WiFi, as the user walks out, the user loses connectivity. Let’s see what happens Trying to click. This is interesting Okay, in the interest of time, this is what happens The one on the left-hand side, it takes — is it possible? Awesome. Okay So the — we will make a query, and what it is doing — it is in direction to Oxford service in London. And you can see on the right, the response came back already. The left one, it is still waiting and waiting. The right one is like, eh, I don’t have anything to do. I’m out The left one is like, ah, finally. This is a lot from reaction time perspective. You want to have this resilience in your app, it can reconnect fast irrespective of what is happening in the connectivity stack So let’s get out of here. It is a separate problem Okay, so what it is using, what you need is you need a protocol that can handle this different mobility where the device is moving between the networks And so that’s where the Cronet and QUIC comes into play, the application layer and the protocols that you are using can handle this mobility. So I will hand it over to Ryan to talk

about Cronet and QUIC SPEAKER: I will do this quickly We have taken the network stack that is inside of the Chrome web browser and made it available as a library for apps to use, we call it Cronet, Chrome, network, Cronet. Since it comes from Chrome, it has the reliability and interoperability that you would expect. It is used by a variety of Google apps, search, YouTube, maps, and available on iOS as well. Coming soon, it is an option to pull from the Play Store, you will not need to bundle it in the app. You can get the automatic opdates and security and performance improvementes Part of the coolness of Cronet is that it comes with support for QUIC, a new transport we have implemented in the user space on top of GDP. And it does some things that TCP can. It is a modern transporter, provides new teachers and better performance. And with QUIC connection migration, you can switch back and forth between WiFi and Sailor. It has a bunch of awesome performance highlights, we release every six weeks, it comes with state of the art security SPEAKER: And the best part is that the platform optimizations are built in, you do not have to do everything time there are Android releases, it will take advantage of the latest and greatest that Android has to offer For any more questions, we have a booth outside. You can talk to us, we are happy to help Thank you SPEAKER: Thanks Coming up next: Quick Ways to Ensure App Compatibility with Android Autofill by Felipe Leme SPEAKER: Next talk, as a bonus, this person lets 10 minutes on Autofill SPEAKER: Hello, everybody So my name is Felipe Leme, and I’m talking about what Android Auto fill is and why it is important for you to optimize your apps for it It is a new feature that we introduced last year on the Android Auto release, and the goal is to provide a safe and fast way for platform managers to do their job. To use Autofill, you need to select an Autofill service which could be provided by Google, or third-party apps, like One password, and many others. Last time I checked, there are about 30 different apps on the Play Store that provides an Autofill service And one key decision we made when we designed the API is that it should work out of the box with existing apps. In order words, as an app developer, you do not have to support the app — if you don’t do anything, the password manager will figure out what to do for you But just because you don’t need to change it, it doesn’t mean you shouldn’t. After all, it is your app that is on the line, and you don’t want to depend on the third party app it has no control over. And the tip I want to give you, you should not rely on Autofill service heuristics, you want to make sure that the password manager does their job properly, you can do it quickly and easily by annotating your XML views The first thing you should do is make sure that you annotate what should be Autofilled, and you do that using the Android Auto fills filling stack. So let’s say you have the user name and password loading screen. If you don’t annotate it for Autofill, and the layout XML is using user name fields and password fields, it is going to work fine. When they use the instructor, they will say, there’s a user name string here and password here, and that is the user name and passwords And say you are in Brazil, your name is in Portuguese, and I grew up there and it is common So my fields are [speaking in language other than language] So the password manager you get is this instructor, and it knows what it is. So it is providing the Autofill data, and the user, you have to manually type in the user name and password, which is the problem to avoid with password managers. So you will annotate the fields, the user name, and the password, you use password And on Java, we provide fields for the user name and passwords, like

telephone number, etc And there is another issue, you should annotate what should not be Autofills, using the Android import texts So to see another example, in developing the API last year, I wanted to send an SMS to my friend, and then I got a pop-up with my own telephone number as a recipient of the SMS. Am when you are composing an SMS, or a spreadsheet, you want to type something dynamically, you do not want to use a pre-define said ed variance. This was annoying for me, I knew the API, it is confusing for ra a user that doesn’t. So you can disable the field for the activity, you can do it on the whole activity layer by annotating the root view, it is important for Autofill, no exclude descendantdescendants It will not use password manager when it doesn’t make sense and it will improve the experience And say you are using the tags and you are so excited to change, that you skip the presentation, the summit, and go back to your laptop and change your apps. Don’t do that. If you are going to change, how are you going to test the changes? You need to select a service to see what is the data provided by the service, and you will say, we will choose whatever comes with my device, Google Autofill, or install a third-party password manager. You can do that, but you can go back to that problem of relying on the password manager heuristic, and we can provide it without a lot of changes, and you cannot see what is going on with making these changes. You can use the standard Autofill service, and we can provide some samples on GitHub. We provide a couple Autofill samples permutations project, one is the basicservice, which is a service that only understand Autofill hints. If you are using auto fithints on your app, you will see something like this that will pop up, because in this field, the user name, you will see is the the options. And on the other screens, the base fill will not show anything And it has a pretty simple service, less than 200 lines of code. If you are interested in seeing how it works, you can do this a well. And debugservice, it will try to fill anything based on your search IDs. This is useful to test what would happen if you are not tagging your views So back to my SMS app, you would see something like this, and you will click on two. And I’m just making sure that — okay So we will make sure that I’m seeing, I’m looking on the screen So when you click on two, you are going to see this pop-up with some user data, which is two, which is just the name of the resource ID. You can see how confused it is for the user if they see something like that on the app And then, the final tip that I would like to give is you should also make sure that the app works when the Autofill service requires authentication. So what does that mean? So most password managers, they don’t retain the data right away, it is encrypted somehow. So they will ask the user to authenticate, a master password or a finger print to unlock the data. The way the framework works, we are launching this, it belongs to the service on top of the app stack. The user does the authentication, and when you are finished, the activity resums So for most apps, it is not a problem. If your app is doing something where it is resumed, you are revalidating, or rebuilding this new hierarchy hierarchy, you might break it out of view So to test this, to make sure that the app works in this scenario, you need an Autofill service that requires a permpermutation, the debugservice And when you launch the debugservice, you need to launch the Autofill and click and select the debugservice, you will see the debugservice is one of the options. We provided that example. And then you can select this authenticate response option on the top When you go back to the app, when you trigger out of view, instead of getting the data, and unlock it, you will have this response toa thent caught. So icate. So when the user attempts to — it will ask for yes or no. So when you click on yes, this screenshot, the sample

app where I have re-created a new hierarchy. When you click yes, you will return to your activity, and now from the framework point of view, all of the data is different. So they don’t know that they have the locked data for your activity, for your user name field, it is a different ID. They are going to show the response again When there’s a click there, it will launch the authenticate, and then it go backs and asks it again. So the user is now on this groundhog loop where it never goes forward, it is frustrating. And the solution for this case is to make sure that you don’t — you create a view hierarchy. So the user attempts to authenticate, we will launch the authenticated activity, and now when we go back, we will see the unlocked data and when the user selects the data, and we are Autofill and everybody is going to be happy. These are the main tips I would like to give from this session. Make sure that you have your notater views, the tess in the standard service, and the work with usera thent authentication. I have links for all of these talks for Autofill service as well that explains all of the apps that I’m using. That’s it. Thank you for coming, and I’m supposed to say that the QA will be out I have 25 seconds before I’m going to be gonged out it SPEAKER: SPEAKER: Do you want to say anything else, or are you done? SPEAKER: We are done, I guess SPEAKER: Thank you SPEAKER: Thank you to everybody that played the game today. $1 did And we will assume that the

users are able to touch the device, or they can see what is

on the screen. That turns out not to be true

So these assumption

s assumptions helps people with disabilities to overcome

obstacles Not what they are interested in

or what they are actually able to do

And so the way Android does accessibility is it depends on

the entire ecosystem. So we were directly on Android, and we

— we build a lot of the core of it. But we really depend on the

entire ecosystem to make this work

So the accessibility

framework is able to handle a lot of low-level features, like

magnification, you are not able to build it into every app, if

you do, we will have a nightmare experience. And that is handled

down close to the graphics level, you want to magnify things. Accessibility developers who work on services, TalkBack, select to speak, they build these plugin services and the idea is that they generally have a particular type of user in mind, they will go through and really understand what those users need, what their challenges are, and try to build something that works for them But they cannot do everything on their own, they need to get information from, somebody who is blind, you need to be able to speak what is on the screen. We need to find that out from the apps what is going on in the UI, and that is where we really need the help of the ecosystem and all developers So as a general model, we have these plugin services, like switch access, voice access, and Braille, they are able to query an API for the accessibility service to tell me what Windows are on the screen and the views inside the windows, what text is where, what actions are available on each view And then they can present this to the user in whatever way they need to. The user does not touch the screen, it do do you want to perform this control, that control, that gesture. And we need the apps to provide the right semantics to do that And the — I want to try to make

this as simple as possible. So a few things to keep in mind One is just to make sure that the information that you are presenting to all your users is as visible as possible So color — luminous contrast is the most importantsingle thing you can do in that regard to make sure you are not using gray on slightly lighter gray to convey information. Thatt can look cool, but it is difficult for people to use. And the second is to prefer controls to be big and simple It is sometimes — you want to cram a bunch of stuff to get as much options as possible for users, and you want to figure out what is important for your users can simplify things for everybody, and for somebody who does not have perfect dexterity to use it. We can have a 48 by 48 density independent pixel, that’s a guideline we can throw out there, to have a uniform standard throughout the ecosystem. That is set as a min height and width thing Next is to label toff stuff If you are conveying information visually, if you have a button, just have a label and the labels should be precise and concise So the users who cannot see the screen can find out what they do And so people ask when in the project should I consider accessibility? Early and often is the short answer. The longer answer is, in each of these different phases of your project, there is something that you can do So in design, ZERL generally the things that I mentioned, keeping the contrast, control size, labels, that will get you a long way. If you are using standard UI patterns But the more innovation you are doing on your user interface, the further away you get from the stuff we built into the Android framework. At that point, it is really helpful if you can think broadly about the full range of users who use your project. So the more gesture type things that you are doing, you want to make sure that you are taking into account how people are going to interact with that that cannot perhaps perform that gesture During development, we have a series of APIs, Qasid is going to show those, and we have testing tools that show, as much as possible, we can automate the processes to make sure you are handling these things correctly So just to explain a bunch of stuff about the complexities of users and things you can do, you can forgive me for saying making accessibility easy, and I said making, and not that we already made. In general, we want this to be easy. We want to make sure that we are doing that, if we are not, please let us know If you are using standard com POFE components and ways, it should not be complicated, like how a particular user is going to use your project. It is something like, what does this control do? And as you evolve, it gets less easy. But we want to make sure that the incremental work that you do for accessibility grows more slowly than the work you need to do to serve whatever users you have in mind to begin with And now, Qasid is going to talk about a way to think about the development process for folks with disabilities SPEAKER: Hey, my name is Qasid, I work for Phil on the Android accessibility team Let’s get into it. If you really think about it, there are two ways that your user can interact with your application Right? The first is consuming information. This can be content that the user wants, or indications how to use the UI And the way we use information varies from user to user. I look at it on a screen and I process it that way. A TalkBack user will hear a description of what is on the screen from a device speech synthesizer. Once a user understood and consumed that information and combined it for the real world, they can act on your application to make it do things. And just like consuming information, this varies dramatically from user to user and from circumstance to circumstance And now these actions can be something like a tap, a swipe, a scroll It can be speaking into a device, some users drive the whole device with a single button And now once you combine these two modes of interaction, we see this cycle of action and information, right? And we can see if any part of

this is su subtly broken for a user, the application is useless. How to make it complete for every single user? That seems like a daunting task, like we mentioned before, the way the users interact with our devices varies a lot and trying to understand those users is a complicated task. If you don’t try to do anything through non-standard, you trust us, and you use APIs, it is a pretty easy task. I will show you some trivial things that you can do, that are fundamental, and push your accessibility to be much better than it otherwise would have been Let’s start with the way that we consume information. And I started this search application, a novel idea. And the way that I’m indicating this is a search UI is that, by that magnifying glass on the little line. You will notice something, that’s a very light shade of gray on a slightly lighter shade of gray That is going to be difficult for people who — for a lot of people to see, because that is a very low contrast ratio. It is frustrating and downright impossible for others. So we should darken it up And just like that, many other people are able to use our application. The goal is to make sure that all of the information is visible in terms of size and contrast. If you want concrete guidelines on this, you can go to the material website and we can give you contrast ratios under circumstances and the hard numbers in terms of size, like the 48 by 48 That was straightforward, but there are dramatic variations in how we consume information. For those situations, what we want you to do is to fill in the blanks for our frameworks. What we mean is that your framework can infer a lot from the view hierarchy from the code we have written, but there are some situations where we need your help. I will show you. Let’s assume that I’m a TalkBack user and I’m putting a finger on a screen to hear the description of what is under my finger. I put my finger on the mag finying icon, but there is no way for our frameworks to figure out what that means, because there is no text associated with that It is essentially an arrangement of pixels on a screen. You have to fill in the blanks as app developers, you do it by a label, search. Make your labels concise and to the point. If it indicates an action, make it a simple action word. And this is easy, in this situation, set the content description, make sure it is localized, because accessibility users do not only exist in America. And now that the user can understand what is generally happening on screen, let’s make sure we allow them to act on our device or application appropriately So I decided to add a new feature, clear text button, instead of having a back space, you can reset and start stip typing again. That’s a tiny butpen, buttonbutton, if you have a fine motor disability, that is going to be impossible for them to tap. We will make it bigger. This works for many more users. And make sure that your controls are simple and large I added another feature, a history feature. You can type in the queries and see the results of the query again And now if you end up swiping on that, any of these items, you will see a trash icon indicating this can be removed from history. If you continue swiping, that item will be removed from history. This is great and all, but it is a pretty custom-built gesture overloaded on to an item. It is going to be hard for our frameworks to detect. So you guys are going to have to fill in the blanks for our frameworks and for accessibility users You can do that by adding an action, or an accessibility action. And all you have to do here is specify a user-facing label or description of that action, a simple verb, and the code that should be executed when the action is performed You can do that with the accessibility action API, but we are adding something to the Android X library which allows you to do it in a single line call, with a Lambda and a string passed in So I have shown you a way of thinking about accessibility issues and how to address them, but you still need to know how to find these issues and how to verify that you have actually fixed them. This is where Casey comes in. Casey? CASEY BURKHARDT: Thanks, Qasid I’m Casey Burkhardt, I’m a software engineer on Google’s accessibility engineering team, and I lead the development on accessibility testing tools for Android. So as Qasid pointed out, there are many accessibility issues that actually fixes our fairly straightforward from the

development side and can improve the accessibility of your app The big question, though, is how it do we go about finding those issues? There are three types of accessibility testing today I would like to cover. Automated testing, use of automated tools, manual testing, where you use Android’s accessibility services itself to understand the user’s experience, and and and user testing, where you bring in users with disabilities and get their feedback using your application My section of the talk focuses on automation because, right now, we see that as one big area where we can make vast improvements across the ecosystem if we have some developers’ cooperation using these tools. So automated accessibility testing, until several years ago, on Android didn’t really exist. Around 2015, we launched a project known as Android’s accessibility test framework, which is an Android and Java library that houses a lot of detection logic for the more common accessibility issues that we can identify within an app’s UI, a rule-based fashion. This is an open source project, so you can find it on GitHub. And essentially what it is aiming to do is to look at the app’s UI at runtime and find the automateable, mechanical aspects of accessibility that we see day-to-day that affect users the most. We can find the common issues that Qasid discuss, so we can find an UI that is missing a label for a screen reader, we can identify low-contrast text and images. We can tell you if you have lickable clickable items within an UI that meet the minimums for touch target guidelines, and we identify a number of various other implementation-specific issues, and the core testing library ATF is growing constantly to find new and more interesting issues We have taken this library, integrated it with common developer end points, tools that you will use commonly throughout the development life cycle and you can leverage throughout your project I want to talk through some of those integrations today and how you can use them and get started with them quickly. So first and foremost, we have integrations with two test frameworks that are commonly used throughout unit and UI tests on Android apps. The first is Espresso, and Robolectric. The idea with these integrations of ATF is they will piggy back on top of your existing tests. You have a test that loads, runs UI with the application, and inserts a state. During the phase of your tests, if you used Espresso or Robolectric, if we identify an accessibility issue that we believe will affect a user with a disability’s ability to interact with your application, we will failure the existing test. If you have strong testing coverage with Robolectric or Espressoo, enabling this will allow you to get a decent amount of coverage in accessibility testing for your app And each framework offers what is known as an accessibility validator. And this is an object that you can use to essentially configure ATF’s behavior inside of your tests So you can configure ATF, for example, to not fail your test and to log something, and we’ve run into an issue And you can set up ATF to crawl from the root of your view hierarchy when you perform a view action, rather than validating the item that was interacted with for additional coverage. You can use accessibility validator to set a white list. If you want to turn on accessibility tests within your Robolectric or Espresso tests, you can do so. You can maintain a green presubmit and burn through issues you know about by creating and registering these white lists for issues And how you leverage these in Espresso and Robolectric, you will call accessibility checks.enable within your test set-up. This is going to trigger our global assertion to run whenever you use a view action within an Espresso test So in this case, the view action is run, runs a performant evaluation on the view interacted with and its sub tree. Accessibility val validator is returned through enable. So if you need to customize the enable, you can do so through the object return in that call Within Robolectric, it is slightly different. Instead of

calling accessibility checks.enable, it is annotation, and it will annotate the test method or class that you would like to enable accessibility testing within. It allows you using shadow view.clickon for you to interact with your elements. Avoid the temptation to use view perform click, do it correctly It is available in a different class that mirrors the same API, you can use for accessibility Util and make data calls there to configure your behavior So, in addition to integrations with these automated test frameworks, we built a separate stand-alone tool, known as accessibility scanner And this is a direct integration of ATF, and accessibility scanner acts s scanner as as a front-end for the library. It will evaluate the fore ground for the device It installs the accessibility scanner, you turn it on, it will add a floating button to the device’s screen, you will open up the application, navigate to the UI you would like to evaluate, and just tap the button. What you see is essentially a report that describes the ways in which you can improve that UI for accessibility And again, these will mirror the same types of issues that ATF and Espresso and Robolectric can identify as well. It is easy to take these reports from accessibility scanner and share them with your team, you can export to email or drive. It does not require technical skills, you don’t need a debug version of your application, or a user debug device, you don’t need to — you don’t need to do anything special to set it up It works on any app or any Android device running Marshmallow or later. And you don’t have to have a lot of experience related to accessibility. Each issue that accessibility scanner can identify comes with extensive documentation that gives you background, and how to think about the issue during the design, development, and test phases of your project And so please do download accessibility scanner, it is something that I highly recommend we use when we build UI. will take you to the Play Store page And one last integration I would like to cover today, this is a new one. We launched it a few months ago. An integration of the accessibility testing framework and the Play Store developer console’s pre-launch report. For those of you who have not used pre-launch report yet, it is a great tool to get a sanity check during the launch or release process for an APK to the Play Store on an open or closed channel. The way it works, you upload an APK, pre-launch report takes that APK, instrument it, and push it to a number of different physical devices in a lab And it will crawl your app, essentially on these different devices and generate reports that include findings about performance, security, and now accessibility as well And so ATF is running along side pre-launch report as it is crawling your application and generating reports at each stage in the crawl, and it is taking all of the results and deduplicating them. So if you would like to check this out, it is available now in Play Store developer console under release management, you should be able to see accessibility results for any APK that you have uploaded to the store since fairly early in July. So please do cleck that out. Here is what it looks like, to give you an idea. The main entry point for an APK, it will show you the categories of issues we have identified. It will show you the clusters of issues, you can click on any one of those and it will show you detame tails about the problem So in this case, we are pointing out an issue related to touch target size. In the column on the left, you see many examples of the same de-duplicated issue across different crawls of the application that prelaunch report has performed. You have access to the same additional documentation here as well, too So if you are not familiar with a particular issue, the learn more link will give you the details you need to resolve it, regardless of the stage your project is currently in I want to wrap up by talking about an accessibility testing strategy. We talked about automation, but we did not go into manual testing and user testing. And these are equally important Automation is great because it helps you find issues very quickly, early in the development cycle, especially if you have good test coverage with our automated tools. So think about automation as a way to catch very common issues quickly, but not as a way to guarantee that your app or your UI is fully accessible To really understand your user’s

experience, to get that — to get that awaterness of how your UI is performing within an accessibility service, we really highly recommend you go and actually turn on TalkBack, turn on switch Access, try them out, learn how to use them, and gain a true understanding of your user’s experience. The way I like to describe it is automation is capable of finding a missing label for a screen reader. But we can’t really tell you if your labels make sense So really only by understanding and putting yourself in the user’s shoes and understanding their experience, we are asking users directly about their experience. Only then can you truly understand how accessible your UI is for users with various different disabilities And we have found at Google, both looking at our first party and third-party applications, the most successful, the most highly accessible apps we see day-to-day are the apps that combine multiple accessibility testing strategies, like presubmit, continuous integration, and a process for manual accessibility testing and bringing users in and understanding the perspective of an accessibility application These are things to consider With that, I will hand it back to Qasid that will talk about the newer APIs for expressing app semantics SPEAKER: I’m back, say you have adopted APIs that I talked about earlier and the testing that Qasid suggested. And you have a pretty good foundation of accessibility in your application, and the more you are testing, the more you realize that there are holes in your experience, that is breaking the cycle of interaction that I mentioned earlier. We are adding API and new things to make it so those holes get plugged So the first thing is clickable spans, the clickable bits of text. Before API 26, non-url spans were fundamentally inaccessible. And developers had to write a bunch of hackie work arounds to make these things work. In the latest alpha of the AndroidX library, we made it all the way back to API 19. You can look out for that, too And there are users that make apps behave like — they have their own life cycle and so forth. They are accessibility panes. You need to develop your frameworks that present these differently to the user. And the way you do that is by passing a string to the accessibility pane title on the view. Make sure it is concise and localized. This is available on API 28, and we added this API in the latest AndroidX alpha that will work all the way back to API 19 And finally, there are headings These are used by TalkBack users to navigate through sections quickly and easily And the way you specify that is exactly what you probably expect, pass in a boolean to set an accessibility heading on a view. This is also available in 28, and we added this to the latest alpha of the AndroidX library that will work all the way back to ’19 Now it is back to Phil SPEAKER: Circlng back to the title of this, making accessibility easy. We really want this to be easy. The only way that this — that user’s didn’t disabilities are going to be able to access the ecosystem Sometimes you see somebody that wants to go the extra mile and dig into the app and all the issues around accessibility, that is great but not every developer can do that. We need to make it as easy as possible so everyone can build it into their workflow in a natural way So certainly, to get the basics, we want it to be straightforward So if you have reasonable contrast, to make the information visible to everyone, you have simple controls, you are using labels. We want that to kind of get you almost all the way, and some of the other APIs, like Qasid was describing, should be able to handle the specialized situations. If you have a full screen fragment transition, you can use the pane title to make sure that that gets handled the same way a window transition would So we want it to be easy. That means, if it is hard, we have messed up and we should fix that And we found some developers that really, well, the framework seems to be coming up short, I will engineer a workaround to get around the problems with the framework. Honestly, please don’t do that Let us fix it, because we can

fix it at scale, and it needs to be inside Android. You find it in AndroidX, you know, if you wanted to fix it, by all means, upload it to AndroidX and we would be happy to accept fixes We want it fixed centrally so we can get a consistent experience throughout the whole COREMS. ecosystem If you are engineering a custom solution, if an engineer at a different company is going to do this work, and the answer is no, then there is probably something wrong So please reach out if we are messing this up. You can file bugs on AOSP, you can ask questions on Stack Overflow But we much prefer to, we probably prefer to get the feedback that something is difficult so we can get an elegant solution that everyone can use. Some of the things that Qasid just presented before he did that, the effort required to do some of these things really require, like, learning a new API surface. We wanted to condense everything we could to one line. So we are trying to present solutions that really are — if you have this thing, here is one line of code, all you need. If you get to something that seems like it should be one line of code and it is not, let us know And another place you can go for other resources is to, there’s a link for accessibility testing, how to get to accessibility scanner, and the test framework project that Qasid described. That is available on open source on GitHub if you are interested in that So, I really appreciate your time, I would be very happy — if you have feedback for us, and you think things should be easier than they are, we will be having office hours for a while this afternoon. We would love to talk to you. Thanks a lot for coming and for your efforts and hopefully making a consistent ecosystem of accessible apps Thanks [ Applause ] SPEAKER: Everyone, the next session will begin in 10 minutes Coming up next: Bundling an App in an Instant by Wojtek Kalicinski, Ben Weiss 12C3W4R50I6R7B8G9SDS Wojtek

SPEAKER: Hello, everyone So today at the keynote, you

heard that we are unifying the developerdeveloper experience

for instant apps and Android app bundles

My colleague, Ben, and I are going to talk about how that works for the developer perspective So instant apps, it is a technology that we introduced a little over two years ago at Google I/O. It lets you give your users a native Android app experience without them having to explicitly go and install the app And now how that works is you split up your app, into smaller pieces, and the user can reach that via a link. And now to QUET your apps small enough and to launch it instantly, instant apps for the first time used a technology in Lollipop, called split APKs. And they are able to use the smallest and most optimized version of the app to the user’s device. In order to do that, the build system, the Gradle Android build system that you have that you build your apps with, built all of those split APKs locally, bundled them in a zip file, and you upload that to the Play Store they can choose from the set of APKs and deliver them to the devices To do that, the developer had to do some significant refactoring in your African apps. The project structure of the instant app, as we looked to one year ago, probably looked something like this. First of all, you have to take all of your base application code and move it from the application module into a base feature And then you had to split your app into feature month featuree modules containing the feature of your activities. And then you have almost two dummy modules, application and instant ach app. So the APK, and the instant app zip bundle that you upload to a separate track in the Play Store. This was not ideal. As I said, it required significant work. Your project no longer looked simple And at the same time this year, we introduced a new publishing format called the Android App Bundle. This contains metadata about the targeting of the resource resources, native libraries, and so on, and it contains some of the module information for a module called dynamic feature I called it a publishing feature, we use it to upload a bundle, telling the Play Store everything about your app to play. And together with Google play dynamic delivery, we are able to serve an optimized set of APKs to user devices. In order to do that, there’s a big difference. Because it happens on the server side on the Play Store, we need to be able to sign the app. If you use an Android App Bundle, you need to enable sending by Google play If you allow us to store the key for you, it is more secure There is another benefit, because we can transform the APKs and make them more optimized, as we develop more apt miizations on the Play Store side, what we bring to the users is more optimized from compressed libraries. It makes sense to move instant apps to this new model. Why build all the APKs locally and not be able to optimize them further on the Play Store? What if we could use the new App Bundle for the mat to deliver instant app experience to our users? So let me tell you how to go back to that simpler, better project structure for your instant apps If you have — we need to go back to the simple project you use as your build your APK So we no longer need the instant app plugin, everything we need is baked into the application plugin that can now build bundles. We don’t need the base

feature anymore Instead, we can move our code back to the application, where we will be using that to build our unified bundle artifact And so, again, with feature modules, we replace them with dynamic features that work in the App Bundle world So ultimately, we want something simple. You can have your application module with any additional library modules that you need. Optionally, we have dynamic features that can be downloaded on demand, adding functionality alt run time. We have single piece of metadata that tells the Play Store that this is instant bundle app enables. That would be great if you can upload it to the Play Store and all have it downloaded on the install and instant track which, what we is what we are aiming for We are testing it, but you are not able to upload it just yet If you want to try it right now, create two project variants, it is in the simple project still In one of the variants, enable the metadata, enable the instant app for your bundle and use the other variant to build it without that entry, or man manifest. Still one app, one codebase, and you may have to do that in order to upload to the Play Store There is another white list n , if you want to use dynamic features in order to let your users download them on demand as they run the app, this is on a white list for developers who want to test that. You can apply online, however, you are currently not able to publish your app to the production track if you have more than one module Okay, so how to try it yourself right now. First thing you need to do is use the new Android Studio 3.3 that is currently on the channel. If you are creating a project from scratch, you can select this check box We will collect the modules with the necessary metadata in there already. That’s what it looks like, thin in the base manifest, you enable it, you are good to go. If your app is compliant with the other instant app restrictions, such as file size, you will be able to publish an instantly enabled bundle. If you have a project that you use to enable an App Bundle, you can use the wizard to allow a bundle. This will instant enable your base module if you haven’t done so And next, we will build an App Bundle through Gradle, through the bundle release command instead of assembly release, or through the wizard and the UI By the way if you are using our Android dev summit app at this conference, it has been built exactly as an instant enable App Bundle. We publish that to our channels on the Play Store, what you are using right now is exactly what I’m talking about And it has been great. It is has greatly simplified what we need to do in order to have that working Let me invite on stage Ben who will tell you about best practices for modeler modularizing this copy of your app. Round of applause, please SPEAKER: Thank you very much. I will talk a little bit about discoverability of your instant apps. One of them you saw, the try now functionality. I will talk about this. Try now is basically a second bud button on the Play Store that allows users to download and run the app without having to permanently install it on the device. That’s a great experience that we can easily see how it works, you can go to Play Store now and check it out through the Android dev summit app, and you can get to it directly from the dev landing page. If you don’t have an url associated with your app, that works as well. You don’t have the restrictions that you have to map to your urls anymore How do you do that? That is basically it. I think that everybody has this somewhere in their application, the main launcher. You don’t have to do anything else other than add the instant metadata that you were shown earlier, there is nothing else you have to do in order to be eligible for the try now experience. What is your app, you want to have your app available with an url mapping? That allows you basically to access your app through any url that you have associated with your app. The first thing you have to do, you have to verify if you own the domain. In order to do that, you upload an asset links JSON file There are resources where you

can identify what you uploaded is correct and the mapping you have is correct as well, you can share the link with anyone and they can open the app straight away. I will show you how that works where we started with the main launcher You have to set a second filter with it set to true. That tells the Play Store it should check for the asset links JSON file on the url provided below. Then you add the action view, the browseable default, this is what I want to use as the default to view this url. You have the scenes for https, or http, and multiple path prefixes for multiple activities. If you want to use a default activity, whether it come from try now or the home screen, is the metadata here, the tag for the filter This is the default url, this is where I want users to come in initially. Like I said earlier, if you don’t have an url in the first place, you don’t have to do this. If you have to have an url mapping, then this is the way to go And it is not a lot of work to do. It gives you the — it uses the experience that you can share any link that leads to your app and any user can open the app straightaway without having to install it permanently. And I think for a conference, it is a good use case to have an app that you use once, you don’t have to fully install install it. You have a couple features, like notifications, you have to install the app. But it is fair enough to have the experience that you can have straight away without the first steps that are necessary And also there is another thing that we use for app bundles in order to download code dynamically So going back to the previous section is basically, you can do that with the zip and feature instant apps. What we are going on forward now, you have to ship, as the App Bundle, and you have to use dynamic feature modules in order to use the play core library. This allows you to download features dynamically on demand, not during the instillation, andapp. And it does all the heavy lifting. If you say to the library, download this, it connects to the Play Store, downloads it, puts it in the right place. For instant apps, it puts it into the shared catch there, and then it installs it on the device permanently. So how does it work? So you add it as a dependency, available from, you can use it in your project. You create a splitinstallmanagerfactory, create a request where you can install one or multiple modules at the same time. Those module names have to match the module name that you set for the dynamic feature module directly in the manifesto module. You build it, and you tell the manager to start the instillation And that’s all the code you need to get started with it. There’s a couple things to go around it, I will go into it in a second If you don’t want to do instillation straight away, you can do deferred instillation So you have the app, the user is in a flow where they are buying something, so they have logged in and then they started the purchase process and you want to download a payment module, for example. You can do that deferred, or during the flow with had the user is in that, you can do the instillations And so the deferred — it is not done straight away, the system says I’m cleaning up and this is where the module is removed. And you can also cancel the instillation requests where, for any reason, you want to cancel that, there’s an option to do it And there’s a listener that you can set on the manager that is my preferred way of listening for the updates, the split install state update listener That’s quite a word. And usually what happens, the happy path is you trigger an install, the app starts with Pending and goes to downloading, downloaded, installing, installed. That’s the happy path, for an app or module that is small enough — that required user confirmation If you go into that state, you will get the — you will get some information that you can start the intent with, to show a dialogue whether they want to confirm or deny whether they want to install the module at this point. If they con firm firm they want to install, you continue down the happy path The instllation can be canceled

in the cancelling state, and for a couple reasons, it can fail So that’s the path where you have to handle all those states We do have a sample al — available for that, I will share the urls later in the session so you can see how it works I talked about file size The limit that triggers, for example, the — that requires user confirmation coincides with a couple apps for instant apps in general and for dynamic delivery One of the things we do is we don’t take the installed size, or the downloaded size, as the main factor anymore So if your app or device has a file size that is larger than the limit, that is all right We can take the download size into account. You get compression over the wire, that’s what we take into account for that. And this we show in the play console as well. You will see the download size is this, you are right above or below the threshold. And dynamic feature modules do not fall into the initial download size as well. What falls into it is basically your base module and your instant entry module If you have more than one, that you can have, it is the base module and the largest instant entry module. And those, under a white list, have to be less than 10MB Dynamic feature modules that you download later on or other instant entry modules do not fall into the 10 instant MB in the first place. If your app is larger than 10MB, you do not have the instant app benefits, you are not discoverable to users as an instant app. If it is less than 10 or more than 4MB, your app can be seen and used as an instant app. So you can access it through try now, on the Play Store, and also you can is show it in the web banners and share it viaU urls If your base module and your instant entry model is less than 4MB, your app can be discovered from anywhere, like ads and search results. If you research for Android dev summit app, you will see that and go directly to the instant app because it is under the 4MB threshold. While you are at it, you can continue to modularize. It is a tricky topic because it entails some work that some people are not 100 percent certain how that is done best We recently went through the whole process with a project, it is called Platt, it is on GitHub and I will talk about how we managed to move away from a monolithic app to an app that uses bundles. It uses the same technology underneath for modularizing an instant app as well. So what we did is we, and most apps will do it, we created a base module which hosts the domain code and data so it shares the shared preferences, log in, for example, some of the repository, some persistent API calls, and things like that. On top of that are different feature modules. Those have their own domain code, logic, and the UI which is only displayed in this module. And that set up can be used for many apps, if you have a base module that shares information and the different feature modules. I will share a little bit more in depth what we did So we initially had an app, a module that most people had, a monolith. If we shift to an APK, that is fine. There is no way to go into the whole modularization part if we have, in the end, one single monolithic app, APK, that we ship to our users. And since we were considering going towards dynamic features and app bundles, we move everything into a base, with the shared dependencies, that means everything that we include, coming from whatever repositories externally as well as a couple of local, third-party APIs and libraries that we have forked and worked with After we tested this, we worked on features that we extracted from the app itself. The first thing we started with is an about screen. Well, an about screen is kind of untangled from most of the stuff within the app. It is a good starting point for getting our hands wet with — what does it actually entail to make the dynamic feature module, how we make it do all the things. Then we did a search screen, and then we have two new sources that we extracted into the dynamic feature modules as well. They

all depend on the app, and everything shares the information through that as well. You can read up more in-depth on a blog post on the Android developer’s medium publication, and we also have information available on instant apps on general, and on App Bundle on dynamic features, and instant apps without urls. The instant app scene is outside during office hours to share information and knowledge. If you have questions, please come there. And with that, thank you very much [ Applause ] Coming up next: Android Slices Best Practices by Arun Venkatesan, Artur Tsurkan SPEAKER: Hi, everyone. My name is Artur, I’m a product manager on Android SPEAKER: My name is Arun SPEAKER: We’re going to tell you about Android Slices, part of Android pie So we’re going to start an introduction to Android Slices, user experiences, best practices in constructing your Slices, and more details on search indexing best practices, and finally through the — what we have been running over the course of the summer, the important developer gotchas for when you start building slices whether when they are available We will start by reintroducing get SNOOT slices Before we into it, I wanted to remind you of some resources We introduced slices at Google I/O, you can find documentation at And you can look at our I/O session video, Android slices, building interactive results for Google search and that will give you information on building slices, building a custom template and an UI for your slice . Slices are a new way for you to present remote app content in Android Think of Slices as embeddable app snippits that can be inserted inside another app or part of a system. Slices are meant to work across multiple possible surfaces, the whole idea of a slice is the ability to constrain and provide you with a lot of power in how you express your app. Slices contain a variety of components, including text and images, and they are powerful. They are not just static pieces of content, they can house realtime data and interactive controls, and TalkBack to your app in the interaction. So all of these examples you see here are examples of slices that you can build I mention that slices can be embedded across a number of contexts, and we are excited to be bringing them to search as the first surface to insert slices. So as they are typing

in a search on Android, you can enhance the predictions offered by Google with lives, personal content from your apps, constructed through the slices you create. There are two types of slices you can provide in search predictions. The first are app name queries, if somebody can search is searching for your app, you can direct them to a canonical part of your app. So maybe in YouTube, you want to get the visitors to the video they were watching Or maybe you want to get beyond the name, and the settings app will give them toggles for data usage How do we build these slices? We will start with default or app name slices. It is easy to build an app name slice Construct it as you would Android’s recent updates include tooling. When you create a slice, you will create a definition in the manifest, like this one, and the exception to the slice provider class. That provides details of how the system can find your slice and what templates it offers to the system when it does. To make this slice map to your activity, or to make it map to the app name, you need to add the slice content URI to the content activity and specify it in the metadata field. So this tells the system, this is a slice that I want to point to the main activity, this is the content from which you can reference that slice The implementation details for general terms are a little bit different So first, you actually don’t provide the same linking in an activity as you would have an app name slice You are going to use updates to the Firebase app indexing APIs to expose the content URI for a specific set of key words Using the Firebase APIs, you would construct an indexable That would have a public url, it will also have the name for that indexable content, some very targeted key words for users to find that content, a description, and then finally with the update to the Firebase app indexing APIs, you can add the content URI or slice URI for this indexable. When the user is searching for the key words you specified, search on Android will replace the prediction with the slice predicted by the content URI in this indexable Finally, in order for indexables to be transilated transilatedilated from the public urls to the content, you need to over write the URI method into the slice provider This allows you to talk between the two formats in order for the URIs to be visible as a search prediction. Overriing this method allows us to provide you as a developer with flexibility over what schemas are important to you, without attaching them one to one Now we know how to build a slice and also how to expose it to search on Android. Let’s go into a little bit more detail on what makes a good slice, and the user experience best practices to keep in mind So the first is try to focus your slice on one task or a set of sight tightly related tasks Avoid making your slice do too many things, and that the content in the slice is coherent coherent. So those slices are embeddable as a search prediction for now, we would like to think that the slices that you build should be reusable in many other parts of the operating system and you should consider when building your slice for those possibilities. So it focuses on consuming and previewing one video, the slice on the right goes to other functionality, like channel selection, and stresses the definition and use of a slice, which we discourage you doing Try to keep interaction in the slice lightweight, highlight the most important features, excuse me, and make sure that the actions you are presenting to the user are using clear and familiar iconography so they make sure that they understand what they represent. Avoid making it do too many things So the slice on the left focuses on users listening to the content and play list, and offers them the ability to like certain content. The slice on the right leans into things you can do with the play list items, functionality that is probably best within your app When sharing your slices to different platforms, make sure you are surfacing recognizable features and content so that users know that they can query for them. When they query for them and see it as a prediction, they can understand how it might have appeared for that particular query. And

Arun will go into those principles, but try to keep that the case to avoid promotional or advertiing content in the slice And finally, have the slice accelerate critical user journeys and make sure that the slice accomplishes as much of the user journey in line as possible without going into the app. By providing the information and actions that the user would need to accomplish that action. So on the left, the user has all of the stuff that they need to know to understand what the slice is for, what kind of information it is representing, what kind of actions I can do with that information, changing the song, adjusting the transfer or brightness, and they don’t need to click into the app to do that. The slices on the right are missing some critical pieces of information or critical component as part of that user journey and adds an additional layer of friction for users in completing the task they want to complete There is more that Arun will go into SPEAKER: Thanks. So here are the main pockets when you think about use cases for building slices. They should be familiar, such as requesting a ride on a ridesharing app. They should be targeted. And finally, recall and reengage with content that the user has seen, rather than discovery use cases Next we will see guidelines around the content you can surface in slices and the data that needs to be indexed Slices should be targeted and personalized Like the video streaming app that shows slices, when a movie a user is searching for is available in the app. The app can index movies, like the users previously, or it is curated based on the in-app behavior Do not create one for all the users in the database Slices should give information A ridesharing app gives users the ability to search for rides Create index cases based on past history, or popular places near the user, such as concert venues Slices should give users timely information Let’s say that a smartphone — they are likely in their home It is not recommended to create an indexed slices for controlling lights at any time or in any place Here are some more examples of the type of app content to index and display in the slice A food ordering app can search relevant realtime data, such as food price, when the user fetches the slice Similarly, a news app slice can index and display information to the readers Travel and local can allow users to look at their content, such as bookings and upcoming flight reservations Let’s now see how to keep your slices fresh When a slice is indexed, the indexable object includes the matadata and the cached slice And in order to make sure it is accurate and not still, you should set a time to live. This is used by the Google search app to make sure the cache is not displayed. In this example here, the time is set to 1R expiration. And if the slice has content that is not time sensitive, use it to time to infinity. In order to present to the user, reindex the slices in the background when content changes, and only when content changes Earlier, arrtur showed us how to index. What are the best practices for key words? Limit key words to 10 per slice Account for likely

permutations This is probably the most important, avoid key word stuffing, use the minimum number needed per slice. So the app slice will be in the search rankings, if you use too many key words that the users are tapping on How do you determine if the — the most important signal is the of times that the user uses the app on the device It is also important that the user has viewed the content previously and interacted with it And finally, in order for us to know that the user interacted with the content, log it to the indexing API We conclude the session today by sharing the lessons learned from the early access program Content URI can be confusing Content URIs are mentioned with a slice and start with content://, and deep uris start with http or https Content URIs use the package name, or the reverse of the package name shown in the example. When you see a content URI, think of a slice. Key words must be included in the slice title or subtitle This is done to ensure that the relevant content is displayed to the user when they search for something How do you handle location? So slices do not provide location to apps, and therefore use the last cached location when displaying the slice Reindex the key words based on the last location. And note that indexables are not instantly updated and it leads to bad ratios. So keep in place when handling location changes for the app, and apply those to slices as well It is recommended to keep the slice initialization short. The on create slice provider method is called for all registered slice providers on the application’s main thread at lunchtime, and therefore do not perform lengthy operations for the application start up will be delayed And if you have multiple indexables, in the case of apps with multiple slices, put in all — pass in all the indexables together as we showed in the example. And make sure to test the indexable. If one is invalid, that update called it failed. So here is a small code snippet that shows it, how to pass multiple indexables to the Firebase app indexing API So now that you have built your slice, you are viewing the API That’s all we have for the talk for today. We want to give a shout out for the developer, to the early access program. Thank you and have a fun rest of the session SPEAKER: We are now on break, this is the worst fab I have ever seen, I recommend people put it on lower right and not have it be that color, there is something disturbing about that one. It is snack time t , it says on the agenda. There is coffee as well as tea, and there is also coffee, there is snacks, and there is coffee, and I have it on good authority that there is also coffee downstairs There is coffee, excellent question Thank you for asking. Let’s see, we are back here at 4:00 Building a great TV app There’s a talk on building Gradle best practices See you back here at 4:00, thanks #

# SPEAKER: Hey, everyone. Today,

we’re going to talk about building a great Android TV app

So before we dig into the details, we will talk about the

ecosystem. We continue to see two times year over year growth

We are investing more in smart TVs, desktop boxes, the

ecosystem has been pretty strong. But you are all

developers, let’s get into how you can make a good TV app So before we talk about what the innards of the app are, we will talk about what the TV is and why it is so important. We have living rooms and other rooms dedicated and focused around a TV. It is a pretty key point for users, it is the focus of an entire room. Just think about that for a second. So your app matters. The content matters So if we try to think about what is the foundation for an app, the biggest piece is your content That is your value prop to your users. If you add on to that, usant, how do you make it easier for users to add. You have great content, how can they discover more of your content inside of your app. If you want the cherry on top, think about the experience. How can you layer in all of these extra things to build a sweet experience for users, no matter where they are in your app? We will dive into each of these concepts and I will call ’em out later on. But the key take away is they come from your content, but they stay for your app So what I would like to talk about is how to build a great TV app. There are three things to think they can see other content in your app easily, and distributing, making your content easy to find should be as easy as making your app easy to find Let’s talk about the player Player can make or break an app We will talk about this review, feel free to read So the key take away for me is that it constantly stalls, this app is completely frustrating They ended up with just a one-star review, just because they are a player. And reviews matter, there are whole other talks about Google play and how to improve your reviews. But the player was the key point here, it is the why their app was not as good astle could it could be. So it is very clear to users that the play back is important. They don’t want to have stutters and stales, they want to be able to watch the content. And even in that review, they talked about XHURNS commercials and ads. They are okay with it, they don’t it like that they stalled Soshowing things that may be annoying, such as commercials, as long as they play fine, users are okay with it. So the player, we have many options to build a good player. Media Player is a good tool, comes out of the box in the framework, you give it a data source, it chugs long in play, you can build a great experience with media player. If you have more advanced things you want to do, Exoplayer is a great tool. We work hard to make it customable, there’s a lot of extensions. If you are using lean back, there’s an extension that hooks into the lean back controller. If you are doing ads, there’s a bunch of ad stitching support. Lets talk about ads, ads are important. You are going to make money from showing ads And ads are just as important as the content shown and displayed to the user. Focus on ads and make sure that adstitching works, whether you do it server or client-side, these are considerations you should make for your app So there’s many options for players, media player, ExoPlayer, custom player. And having a player is a good start But there are things that you can layer in, that top part of the pyramid, the experience, there are things that you can to

to build an experience around the player to make it even better. So we talked about this at I/O, play back controls Everyone’s phone should be ready, here we go. Okay, Google, skip 5 minutes. Okay, Google, pause Okay, Google, play. Thesep types of transport controls can be commands through the assistant Adding this extra little feature, this little nice nugget of delight, helps build that experience experience for your app This works with Media Session, if you have Media Session call back, you get all of these features for free. Since I talked about this at I/O and there are other talks, I will jam through this fast. Pay attention, here we go Boom, beautiful Six wonderful methods: Pause, play, stop, seek, next, and previous. But in reality, that’s a lot. That’s a lot to think about, all of these different casesism if. If you use ExoPlayer, it can be done for you. There’s an extension, all you do is connect the player to the media session and it works out of the box. Making a media session is pretty simple, there is documentation and talks ants about Media Session. I will not go into it, set it to be active, set the controller, set anything else you need to set. Set the current state, are you currently playing, what position are you in, set up the media session to be what you need it to be, and once you have a media session and you have an ExoPlayer instance, connect them. There’s the extension library for ExoPlayer, add in the media session as the parameter, and set the ExoPlayer instance. The media session connecter helps understand how to set up the call back, the edge cases around playing and seeking, you don’t want to go back past the end of the video, rewind before the video starts It handles the edge cases for you. In this sample, we are saying set player, player, and then null And you can set a custom play back refair. There are other customizations you can do as well, so if you are music app and you have a custom playlist, and you want to set a different order for how the songs go through the queue, you can set up a custom queuing mechanism on the extension. That’s it Three wonderful lines of code, and the instance is taken care of for you. All the default behavior you would expect, done So having a great player is great, that is one example of how to layer thin experience to make the player even better We’re going to skip ahead to discovering content So the whole point of discovering is you want users to stayp in your app, and you want them to discover and watch content faster So let’s look at this review, I love the first sentence, they love love love — so many loves in this ach So the key takeaway here is that it was a five-star review, they loved that all of the content was there. It is easy to find, they can do whatever they need to do inside of that app and watch what they want to watch Funny story, it is the same app that got the one-star review So even though they had a bad player, they worked on discoverability and they are able to have good review in the flay Play Store So how can we make content discoverable? Everything happens in threes, that’s a rule of comedy, and a really good rule in life. And discoverability also happened happens in threes. We can work in in-app browsing, search with the assistant, and the home screen We can start with in-app browsing, there’s a beautiful library, Lean Back. If you have done TV development, you are very familiar with it. It is a templated UI system where you can plugin data and it works on building the UI for you, so you don’t have to worry about the focus handling and the user input. You can just, this is the content we have, and it will show it for you. It is not just how to browse content, though, leanback also works and showss details. So there’s a bunch of information about content, you have duration, content rating, the rotten tomatoes score, the album, artist, I can keep going on and on for the rest of the 30

minutes of this talk. But I think you get the point, there’s tons of information You can show it using lean back and in multiple places on the home screen, in search. And by showing this information sooner, it lets users make these microdecisions faster and they don’t have to go in and out, in and out, to figure out hot what they want to watch. Make your user’s lives easier by showing this sooner. Let’s look at another example, search. We talked about this at I/O, there’s tons of documentation on this. I want to breeze through some of these things quickly Search is all supplied with the content. Content providers are simple, they return a cursor, you can do whatever you want in the background with the content provider If this did a network call, maybe you have a bunch of pojos This is a database call, you have a cursor. That’s fine, the trick for the search provides provider is it needs to return results that match the search manager’s criteria. A search manager is way of saying this cursor has a bunch of columns with these names, and then the assistant is able to pull in from that cursor and say, here’s the title, here’s the duration, and is able to figure out what content is where Super simple to do to do with the matrix cursor, we will dive into it closer. You need to take each of the results, add them into a row as a matrix cursor, and then return the matrix cursor. The matrix cursor is really just like a mock cursor, it is a 2D array, essentially, under the covers So if you don’t have to go about, how it do I store all of these in a database, you can mock it out at the very end of your search So mapping, this is where the hard work happens You have a matrix cursor, it takes in a query projection This query projection is going to have all of the columns defined that match the search manager So here we have suggest column, text one, is the title of the content An action, the data ID, the ID is what is unique to your content inside the app And if you take the context into this row, you supply an array, the name, and it corresponds to the order in which the query projection was So the ID, the title, the action, etc. All of the fields you have, you can return it back So search manager, and with the search and assistant, you can make the return result mump much faster And so we will cover the new stuff that is happening The app will have the channel, the play next row, and for the video apps, you will have previews. We have seen up to 2X increase in engagement , you can see a trailer for a movie, or a recap, but they take a little bit more work because it requires the content team to make the content for you. We will not talk about play next, or video So inserting it into the content provider. So set the preview, the link, when they open the channel, they put it into the app and set the internal provider ID. This is what the app keeps track of and knows about. And then you just get the content resolver, you call the insert, give the content values, and you are good to go So you do stuff, the channel ID, you keep track of it for sink synchronization So it has the deep link, the internal provider ID, and the logo, those are the key pieces of the channel So what just happened? We created a channel, we inserted it, and then we stored the logo So we did two things with the home screen, insert the channel, store the logo So, as of AndroidX 1.00, we have a new API. This API looks very

similar, small differences. We have a preview channel helper class. It takes in a context, and then it does a bunch of look-ups to get the content resolver for you, so you don’t have to do context, content resolver.insert, it does the work for you. It makes a channel, you have the builder, you set the name, the description, the app link, the intent provider url, you think you should set the type. But this class knows it is a preview channel. It knows the preview, and you don’t have to set the type. Instead, you can set the logo Now, all of this is contained in one united, you can call the helper.publish channel, and it gives you all of the work for you And you can get the channel ID back. So what it does under the covers, it inserts the channel into the provider, and it goes to add a logo And if the channel isn’t able to be inserted, maybe you have bad data and you are hitting an error or something, it will return an error back to you If it is able to insert the channel, it tries to store the logo on that channel. If the loFWO it go cannot be persisted, it wraps it all up, unwinds the channel, so you have half one on the home screen. It treats everything as an atomic unit Pretty convenient. It does everything CRUD does. So we talked about publishing the channel, you can read all of the chanles les and get individual channel, you can update a channel and you can delete them And all of this also happens for preview programs, and there is support for the play next proin this class There are two options to do it, which one is better? You could say I want to use content providers, I want to fine tune the performance, I can do batch inserts, bulk operations, I can go lower-level control. I don’t need an entire program with all of that metadata, maybe I want the title and the duration, and now I can slow down that query projection, and have faster results And it is based out of the framework, you don’t have to do all of this extra work to access it. You get it out of the box from the framework. If you want to use Android X, you get more convenience, you don’t have to worry about all of the nuances of a content provider, it is a-liner for all intents and purposes, and you get the benefits of having the AndroidX in your app Discovering content is great, three ways to go about it. In the app, searching the assistant, and on the home screen with chan LSS. Les. How do you make your app discoverable? The third thing The app store on TV is a bit different, it makes sure that only apps designed for TV are shown. When the user opens up the app store, they are looking at apps that can be played on or installed on TV Try to make your app stick out can be hard, but there are simple things that you can do to have your app appear on the Play Store. The first is to declare features, and even if you don’t use it, there’s a giant asterisk. Don’t start declarng bluetooth or location just for fun. There are two features that really matter The first is touch screen, you want to declare it as false. It is not a touch screen, this is not a phone, this isn’t a TV from way back in the day, these are smart TVs You don’t need touch screen support. The second thing is to declare lean back as true. This tells the Play Store is ready to be deployed on a TV If you have all of the code in a single code base and making a single APK that deploys on mobile and TV, set the lean back to false. This tells the Play Store that the APK is compatible on mobile and TV. The second thing you should do is try to be visible in the launcher. If you are a headless app, a screen saver or a keyboard, go away for two minutes. And I will see it then So you need to supply a banner to see it in the application or activity. The launcher will go in through the manifest, find the resource, this is what it uses to show the icon on the launcher And once the user selects the icon, it needs to launch something. So the launcher fires an intent, and you need to have an activity that accepts

this intent It is called the lean back launcher intent, cleverly named And from that it will trigger the lean back experience. There are three things you need to have. One, declare the two features so the app is found on the Play Store. Two, how the have the banner, and three, have the lean back intent so the app launches when the user wants to enter your app And that’s it. You are ready to go in the Play Store. This talk is done All right But, in a sense, that is kind of the minimum viable product. You are able to have a strong player, you are able to have easy-to-find content, and you are able to distribute on the Play Store. That is just a good app How do you make it great? To start with this, you should look at your users Imagine the spectrum, they start from one side of the spectrum I bought a TV, I want to be cool, everybody is doing it, sit s in my closet but I have one The next part of the spectrum, I have one, I watch a show every week. You go further down, I love how to get away with murder, field of disease daisies is awesome, I should watch suicide squad, theis in that. Or for sports, here is a fantasy team, the jersey and the player I like and I keep going into it. That side, the left, is called the lean back user They are sitting back, watching TV. That’s all they want to do This is the lean-in user, they are sitting on the edge of the seat, this is awesome, who are the people in the show and going deeper into the content Everything I talked about until now, having a good player, making the app usable, this is for the lean-back, the right side of the screen. If you think about it, how can you tap into that lean-back user? Here you have a beautiful living room, a very beautiful living room. I wish it was mine, but it is not. If you look closer, you see a camera, a microphone, a tablet phone, and then, as you start to think about it, the TV is the center piece of the living room. There are so many devices around. You don’t have to just do stuff in TV, you can tap everything around the liveic ing room. I love the Android TV, it is the focal point around everything that is happening Again, we do it in threes, threes are great. In concept, if you want to tap into the other surfaces, what should we do? The first is controlling media, the play back controls we talked about earlier is a great step. It is going to go a little bit farther advanced, you are building an experience around your app. And another option is to have notefication notifications, the big gomis game is going to start. Do you want to watch in your TV? And the next is going deeper into the content, the cast and crew, behind the scenes of this production, are there extra sponsored content I want to know more about. And the third pillar is about reducing friction, how do Iinstall your app, it is installed, how do I sign into your ach I want to make a payment, how do I authenticate it in a secure way inside the TV. Everybody who has the TV has done the third step, the frictionless interaction. The Android TV set up does it for you, during the flow, it says, do you want to set up on the phone? They give the UX indicator, you get the notification, you say, this is me, this is my account, and the TV takes over from that information and it was really frictionless And how do they do that? It is something that you can do today, it is nearby. We try to use that on TV, what you can do You do the work on the phone, and not on the TV. We will set up a peer-to-peer wireless connection that is encrypted, you don’t have to worry about a

lot of things, you have an intimate connection between the phone and the TV. We will dive in a little bit deeper, let’s get started with this, we will start on the TV side. So I’m on the Android TV, so I’m biassed So TV will start advertising, you set up the nearby.get-connectionsclient That is a helper class from the nearby API that has all of these things to get you started. You call the start advertising, you give it a name, a service ID, a package name is perfectly fine You are going to give it a connection, a life cycle call callback, and set a strategy. A cluster is a really good strategy. If you notice, there’s a P to P, point to point, strategy. And it might be one TV, one point, point to point, that is great. If you try to do multi-device set-up, I have a TV in my living room, in my bedroom, bathroom, all of a sudden that point to point breaks down. So to make it a more robust app, think about using cluster. You also set a success and failure listeners These listeners are not saying, oh, I have been found, I have been advertising on non found, the users will say you can start sad advertising, great for debugging and adding extra information inside the app. The big elephant in the room is the connection Lifecycle Callback, this talks about how the devices talk to each other. What is going to be said is later, how they are saying it now is handled in the connection life cycle callback And a simple three methods: On initialized, results, and disconnected. And they are pretty straightforward, but let’s dive in a little bit more So when the connection is initialized, that means the phone requested a connection, you are going to prompt for security and do a couple things Eventually, you will see nearby.get connections client, and you will accept it. Based on that, there’s a result, was it okay, continue on, was it rejected, maybe it will ask for another re-try. And based on that result, you should handle appropriately And the last one on disconnected is pretty simple So clean up any metadata that you may have started collecting The big line here is the connections client, accept connections And here you pass in a payload callback. This payload doll callback is what the devices communicate. So you have a contract on your phone and on your TV for what they are going to say to each other. Hey, phone, we want to do this. Hey, TV, we’re going to do this. And this is all handled inside the payload callback. So here are a couple tips What you are going to communicate is very specific to your app, but here are some tips. The payload received and payload transfer update are the only two methods you get They are pretty succinct Payload receive, if you want to send an acknowledgement back, hey, thanks for telling us this, phone. We will send back an acknowledge acknowledge.Ment, so you know the message that has been received. You call send to payload. You give it the end point ID and some body, in this case, it says ack, or acknowledge And if you want to disconnect, hey, I received this payload, I want to disconnect the connection and close the session, you should do it in the transfer update. And in the transfer update, you should see if it is in progress or not. If you are sending messages like ack and send, those are fast If you are sending something big like a file, that can take a while. You want to make sure that all of the bytes have been sent. Once all of the bytes have been sent, you can call disconnect from end point So now you are going to say, hey, I’m a TV, accept the connection and you are going to communicate. On the phone, what happens on the phone side? You are going to discover the TV this time, accept the connection, and everything else looks like the slides I showed you To discover the TV, this time you call start discovery. Mind blown. You give it a service ID. This time, I’m using a constant, and there’s a reason for the service ID, depending on your app, it should be the package name or the constant If you have a package name that is the same for both your TV app and your mobile app, it is going to work great. If you have something like com.mycompany.Android, or Android TV as your two package

names, imagine they are on their own channels. So the nearby connections library will not be able to find the phone and the TV. Having a service ID used be both by both sides is a good practice. You will give it a mobile end point discovery call back, I love really big words And you will have a strategy, and I encourage you to use cluster for this use case. You get listeners, they are pretty important, and they are able to start discovery. This does require location permission, so if you get a failure listener, like permission for location hasn’t been enabled, so they are great for debugging and trying to urge the user down the correct path So the next part, accept the connection. Really simple, you have the mobile end point discovery call back. It has two methods, you found the end point or lost the end point. Pretty simple. If you find the end point, go ahead and request a connection This requests the TV initialized on the TV you saw earl ierearlier. If you lost the end point, maybe the user is no longer nearby, or they gave up and closed the app and said forget it. Hopefully it is the first for you, not the second You should clean up whatever metadata you collected already And anything after this is identical, you will have the connections live cycle call back that shows how they communicate, and the payload call back that shows what they are going to communicate. And that’s it, that’s nearby in a nutshell And nearby is a cool tool, it is a nice box in your kits to have more experience in a TV app. We wills go on payments, we will look at one more example Payments is cool, it adds a family-friendly idea Imagine you are at work, your kid is at home, and they want to buy the next season of a TV show. You get a push notification, are you sure you want to purchase this, you say, man, my kid is at home buying stuff, no, or yeah, they are bored, I will use my finger print or anything from the phone to authenticate yourself. And you enabled a purchase at home from your office And I have not seen a lot of this in Android. This is not a good fit, it is not a good tool in the toolbox, but it is not necessarily the best fit. So let’s talk about a good fit, you get a push notification, and it says watch on TV, or watch here This a big game, you want to watch it, watching on a small phone. Eh. Watching on a big TV? Awesome So you can use nearby to figure out proximity. They are close to the TV, we should watch the TV button. That’s a great use for nearby. Receiving the notification an example of content immersion. When you said watch on TV, the background lit up, the schedule for the game, the highlights, the score And then whenever the user wants, they can put the phone to the side, it is very non-intrusive, and they can focus on their game. So in a sense, this is kind of kicked off from a notification And in a way, you would say that is more of a push model. Nearby feels more like a pulling, I’m pulling a conversation between the two devices, and whereas in this case you are pushing that information to the user And you are talking about Firebase cloud messaging after this, I will not step on their toes too much. We will talk about it for fun, what is the worst that can happen. You set up the Firebase members of the jury messaging messaging service, and this is what to do And if the action happens to be watch this movie or game, start watching and you are good to go Start watching, then it should literally launch an activity This is the Android Dev Summit, I will assume that everybody has launched before. In this case, we will set up the intent, the extras, this is a

video to watch and the activity And next, what happens when the TV is off? I am at home, I get a push notification, oh, man, the game is about to start. I have to hit power on the remote, I have to tune to the channel, man, this is first-world problems at its finest But you can solve this. With the fragment activity, you can call, set turn on screen to true. And this is a cool API on activity. It is actually introduced in OMR1. So if you are on API 27 or higher, you should do a check. Hey, turn on screen to true, otherwise you can add the flag. So start with your player, your content is king. So really focus on the player, whether it is content or an ad, make sure the player is solid. How do you make the app more usable and get the lean-back experience so users can quickly find other content to watch? The third pillar is distribution, is my app deployed to set up on the Play Store correctly? When you have all three of these, you have happy users, and who DUNCHT doesn’t want that? If you want to take it further, use these lean-in experiences, have payments, push notification control, add the immersive content, the details of the game Thank you, and everyone go build great TV apps. If you have any questions, you can see us at the office hours, thank you very much SPEAKER: The next session will begin Coming up next: Android

Suspenders by Chris Banes, Adam Powell

S PEAKER: Hey, good afternoon,

everyone. Thanks SPEAKER: I’m Adam SPEAKER: I’m Chris SPEAKER: This is Android suspenders. We’re going to talk about coroutines, and to get started, many of you are probably familiar with Android’s main thread. Like any other toolkit, it exposes a UI or main thread for exposing updates to parts of the UI. You may be inflating views, measuring layout operations to change the shape of your view hierarchy, drawing, and many other things like processing input events and so on and so forth So today you are probably familiar with the 16 millisecond time limit, the vast majority of devices out there are have a refresh of 16 hertz, which means you have 16 mill secondss to load the display framework. You have less and less time to get this work done as the hertz go up The things that cause you to miss a frame and have Jenk in your application is app code If you are binding items to a recycler view, these are all bits of work that are great if we can keep it out of the main thread and off the critical path. How do we fix it? This talk is not about achieving 8 millisecond refresh boundaries, but using the resources we have available. All the phones we have have multiple cores in them today. How do we make use of that? Some of you probably remember this thing, it has been around for some time It has issues around rotation, a lot that it gets wrong. There are executors, that developers are familiar with. It has thread pools that are nice, but it is a raw API. You can build things out of it, but it is not convenience — convenient to use on its own Loaders are a thing out there that solved a few problems, narrowly-scoped, it is deprecated and there’s not a whole lot there. We can use features, there’s listenable future that showed up in the AndroidX APIs, but you might not want to pull in all of the infrastructure that helps you to leverage some of the thingsout you can do with it. And unless you are working in min SDK24, you cannot use importable future either and there’s a lot of reasons you don’t want to use it to begin with So Guava, you can use that to pull into the app. And RSDK is helpful as well. If you are here, you probably want to talk about coroutines, which went stable in Kotlin 1.3 this fall So why should we use them? All right So whaI when I think about this question, what does the typical mobile app do? They are CRUD apps, they Create, Read, Update, Delete data. And usually it is a source, a database, or whatever it may be. And it has some kind of sync. They will upload data and pull it back from some kind of web service And apps are pretty simple computationally, you are not taxing the CPU very much. And I guess the logic can be tricky to get right, but they are pretty simple. And in Android, we put a lot of stuff in your way. We make your life harder, but your apps are pretty simple from a logic point of view So why coroutines? And how do we fix that? They are great for I/O tasks, especially a resource-constrained system, like the phone and tablets you are using today. And you cannot create a thread for everything network request that you ever use, because threads take in the space of that, they take about a megabyte of RAM every time you create one. That is why thread pools cache threads for you And coroutines take in the realm of 10s of kilobytes in a Coroutine, they use threads underneath in a much more

optimal way. They have an easier development model. It is easier for developers to come into a new source, and see an imperative, line-by-line Coroutine of something like an RX Java chain. To understand what is happening there, in my mind it is easier, and the same for call-backs, everyone knows about call back hell, and going line by line and seeing what you have called and stuff. And coroutines hopefully, anyway, fix that And so a lot of this talk was written in mind with an app I have been writing called Tivi, I went all in in RX Java, it is 50 percent coroutines and 50 percent RX Java. I use both, they both have a place in Android development, so I say use both. And as developers, we have to care about APK size and method cans. I’m using free libraries from the coroutines core, and RX2 that allows you to interact with RX Java And if you are actually pulling down the jars files to central, they come to 774 kilobytes That is quite big. And once you are actually putting that in your APK, it shrinks down. It comes down to 500 kilobytes And the references are quite high, 54 percent of your 64K And as soon as you turn on minify, and now this is tree shaken, no optimization turned on here. And they both have results You are looking at 113K. So a lot less, and again, the references is dropped. As soon as you turn on optimization, and you fix all the program rules, you are coming down to the magic value, which is less than 100 kilobytes. And your reference is now 834, less than 1 percent of your references And now one thing to note, when you are using R8, you need to use this rule. It is not bundled with Java, hopefully added soon, but a simple rule to add SPEAKER: Okay So hopefully you are thinking about how to use coroutines in your app, we will talk about how to write them. Anything you do with a call back feature, you can do with a suspend function Anything with coroutines is a suspend function for creating APIs, they can suspend without blocking and resumed later with a call back and can only be called from another suspend function to set up the machinery involved in that. The core thing is all of this fits in one slide, the language works the same in thethe presence of suspend functions and we will spend the talk talking about that. This is the suspend from Chris’s app, a data repository for TV shows, you call the update show function with the ID, we get some shows, and we get a little bit more data from a remote source, and a little bit more data from a second source. We merge all of that together and we save that data So these three main tasks where we spend the bulk of the time, these are done sequentially, but none of them have a dependency on one another. Wouldn’t it be nice to do it concurrently? With the async builder, we can do it We start from the top here, we open a Coroutine scope, and this allows us to build a parallel composition using the async builder, it has the receiver in the scope for the Lambda block block we have. We build the async operation, the second, and the third. And we await the result of each one in turn. So the nice one is that we have launched all of these things, let them run independently and then we bring them back together again So since all of these things can be now done in parallel, things should complete faster. Trying to do this with raw threads by hand is a lot more code than you need to maintain along the way The async builder is when you want to run something and await the result after giving it a chance to finish while doing something else. It is similar to C# or promises in JavaScript What if you want to launch something and forget? There is that, too, it is called launch and works the same way. In this case, it is a lot more similar to executors and just sort of submitting a task, submitting something to an Android hand led handler when we just want to

fire and forget and deal with it later Those are the basics of running coroutines in isolation, how do you handle it on Android? So you may have the components ViewModel, wouldn’t it be nice to have a way to put all of this stuff together automatically? You need to open a scope, where can you open those things to begin with that you can launch into? In this case, the model has a show repository, the data layer, we have the viewer state that the viewer activity or fragment observe. We refresh on construction and we have the construct property This is coming up soon. The refresh function uses the Coroutine, the launch builder, and updates the function on the repository. And the Coroutine updates back on the main thread so we can manipulate the view hierarchy, so we have a nice, clean, sequential ordering of operations So those of you who want to check out this thing that is upcoming, you can go to this link, take a look at the change so far in advance of the actual release. It is a release of the KTX libraries. We will demystify how this works Before we go deep, we will talk about the other primitives that are under the hood here Woah, we lost our deck Uh-oh. Did we switch to the wrong — keynote crash SPEAKER: We will talk about jobs, so what is a job? So when you look at the code snippet, you are actually using the launch method. And now when you are actually running that launch method, it returns what we call a job. And a job allows us to reference, keep a reference of the ongoing piece of work, it has one method on it, it is called cancel. In this example, we would not call cancel straight away after we launch something, that is ridiculous What it does allow us to do is to handle double refreshes, if you have something that pulled the refresh in your app, you don’t want the bugs to happen at the same time and then you have two things happen at the same time. So here, this code snippet, you can keep a reference of the one that is currently running, and if first one. And that is the kind of how the job works, it is a very simple object. It allows you to keep a reference of the on going piece of work. So you may have seen that scope and wondered what it is, Adam explained it earlier. You can have a scope, and it provides you with all the context that you need to run a launch or an async So let’s look at how they work underneath So Coroutinescope ask an interface that allows objects to provide a scope for coroutines, think things like with a life cycle, like fragment, activities, ViewModel. They can provide a life cycle full of Coroutine itself and start and stop it as it needs. Async and launch used to be global methods, and a recent refactor brought them as instant methods on the coroutines scope. And what it means is that, mentally, instead of just launching something, you are launching a Coroutine on X. So I’m launching a Coroutine on the activity. It changes it in your head, so it is tied to the life cycle of something else SPEAKER: Right if you are used to working with the life cycle owner in arch components, the life cycle owner has a life cycle that you can observe and attach things to. A Coroutine scope has a context that carries everything necessary to launch the Coroutine SPEAKER: YOU CAN s SPEAKER: You can essentially map the context SPEAKER: And it crashed again SPEAKER: Well, it is a good day for slides SPEAKER: Got it back? SPEAKER: Okay, cool SPEAKER: So we will look at another example. We are not using the V model scope, we’re going to add the data ourselves We created a job, a simple instantiation, and then we are going to keep that — we are going to create a Coroutine scope using add a job. Anything that runs on it allows us to track back using that Java object. We will give it a default dispatcher, talk about it later. And anything that is launched on that scope will be run on the main thread, so the Android main thread. So once we’ve done that, we will have

the refresh method, and we will use our own creative scope, the same code, using a different scope. And this time the launch we scoped to the job object woe created — we created earlier And what has been torn down, we can call the job.cancel, and any coroutines that are running when it goes down will be canceled at the same time. It reduces memory leaks and allows it to tidy up. So if you can look at how things are running now, so we have launched the Coroutine and we are going to go into the update/share method So here we are in Coroutine, the launch, which is that blue thing going around. And in the update share method, which is denoted by the yellow. And this is the async builder, we have a first Coroutine running. And so it is running nicely, doing its thing And the outer Coroutine goes past that, and the second async, which is the remote. We have two coroutines running, well, we have three. But two in the launch And once they are going along, we go into the first await. And that first async, the local, to finish itself off and return a result, what is what the await will return. Because we are waiting on the first Uync, the outer coroutines are suspended And during that time, the ViewModel is down, and we call job.cancel. And at this point, the outer Coroutine is cancels and the inner two are canceled And the child coroutines inherit from the parent. So if the parent has been canceled, anything below it will also be That is something that was added recently WLAUPS if what happens if you are using view models? So as part of the Android architecture components, we added a listener functionality of the life psych cycles. You create a life cycle observer, in this case we are using default, you can add create, destroy, stop, or whatever it be. And you can create instance or observer, hopefully you have seen this API before. And this builds a scope of where life cycle observer, which allows us to scope coroutines to the actual life cycle instance. The primary API is it passes the Lambda, and that is what everything runs with when you are started, that is kind of what you are using most of the time. So it will allow the governance, and the first thing we want to do is on start, we are running the piece of code, creating the Coroutine scope, and running the dispatches domain. And then we will call script.launch and call the Lambda. Pretty simple. And finally, on stop, it seems like a good life cycle to use that will call and will eventually cancel the job. And that means the Coroutine will be canceled You can see that it is not actually that complex. In AndroidX, if you look deep down into it, it is pretty simple To finish it off, we will have a nice build function, you pass the Lambda, and it will observe it for you And what it allows us to do is like this. So here we have a detailss fragment, the live scope, and then run something And it will automatically start it, when we get to — it will be started when we go to start and new fragment, and then it will be closed or ended when we get on stop All right. Brings us to cancellation SPEAKER: SPEAKER: We talked a lot about cancelling a Coroutine, what happens when this cancels? If you have a block of code that is running, what is torn down when you need to clean up? So when a Coroutine is canceled, if it is while it is suspended and waiting for something else to happen. In call back terms, it has not been invoked yet. It will throw a cancellation exceptionexception, it will resume from the point it was suspended with a cancellation exception. What does that look like? This is the example from before. What happens if we need to clean something up if this is canceled in the middle of the update show function? Because it throws a cancellation exception, this is something we know how to do already. The blocks run as expected, we don’t need to add concepts from what we already know from the rest of Kotlin If the block-in code is running, it requires cooperation in order

to stop what it is doing. So we can check for that cancellation explicitly in a couple ways Generally this means checkinging to see if the Coroutine is active And one of the patterns is if you know the job is canceled, you can call the stock suspendingsuspending method, such as yield, to force the cancellation to be thrown. If you are canceled, when you are trying to suspendsuspend, you will resume when the cancellation exception, so it will immediately throw if we happen to be canceled. If you throw a tight loop, you can check the is active that is available from any suspending scope and you can stop what you are doing. There is no reason to involve an exception here if you are doing a tight intercomputational loop you need to break out of. And that leads into how exceptions are handled with coroutines in general, and there’s a few things to point out, especially if you followed Kotlin’s development leading up to release, because there were significant things that happened. Launch will re-throw unhandled exceptions as they happen. It fails the parent, it cancels the parent job. The parent sees the cancellation with the original exception as the cause. And they get thrown back to the exception handler in the root of the job tree, and the Coroutine context gets a chance to intercept. You can attach a special element to the Coroutine concept itself that you can use to handle handle unhandled exceptions How does it work? So say that save show throws a domain-specific exception in this case So in this case, this will be treated like an on-call exception at run time, just like anything else that calls the exception on the main thread Async is different, if the exception is thrown while something you launch with async is running, it will hold the exception and only throw when the caller calls await. So going back to the example from before, we will use what we know So we throw our exception from one of these async jobs, and that gets thrown from this call to await itself. So we know exactly where we need to try and catch that exception in the normal way and handle that error But there’s a gotcha here, and that is that async works the same as launch in terms of how the nested job tree is handled The deferred object is another kind of job, it will cancel the parent, just like launch does, and it will do it even if we did an await and called it. This is important, if something throws an exception, it is important that your app knows about it, it should not disappear into the Ether, but it we caught it, what do we do? So instead of using Coroutine, we can use supervisor scope. It works like a Coroutine scope, but it is a supervisor job that will not be canceled if it is handled with an unhandled exception SPEAKER: And earlier, we mentioned that me can decide when coroutines are run and what thread they run on. On Android, we run on threads, and we are using the thread pull underneath. And we can decide when that is dispatched on And now let’s have a look. We are running a very simple launch, that is missing a scope We are looking at the example And default is the context we are using what is called a dispatch.default, that is what is given to you for free, and it is default for everyone FWLNCHLTS SPEAKER: A computation thread pool SPEAKER: So what is a Coroutine dispatcher? It schedules it to run on something, in a thread in this case And the default, which you can get, is it uses CPU threads. So your device has four CPUs in it, you will get a thread pull of four. So it is not as great as I/O, it is more like a computational-type dispatcher And it is also an Elastic thread executor, that I will talk about in a minute, but it is the default. There are dispatchers.I/O, that was added recently, and it was designed for blocking I/O tasks, so things that we care about, network, image loading, reading disks, database, blah blah blah It uses 64 parallelism, which

means you can have 64 tasks run at a time. It can launch it like that. And the really great thing about the I/O dispatcher is it shares thread pulls with the default dispatcher. And the point where it is great is this We have an async that is using the default dispatcher, and then we load an image on the I/O dispatcher, we do disk reading, and then we’re going to use that result and process it somehow It is a computational task And now what? Because this is running on the default dispatcher, there is no actual switch in there, we are using the shared thread pools, the I/O uses the shared threads, and there is no actual thread switch which makes it a whole lot quicker. And we have dispatch.main, it allows running coroutines on the main thread And it uses service loader to load the dispatcher in your code, which is tricky when we have things like Pergyle, so you need to be careful and add the Android dependency. So use it, launch the dispatch. That brings us to reactivity How many launches can be summarized by this slide? I have been guilty of this And I will make the premise and the statement that most devs use RX Java because you can switch a thread, or switch multiple threads, that is when most RX Java is useful. And I think, for 80 percent of the cases, it is a switcher thread. And that is because the APIs that we have, and we spoke about them earlier, are not so great to use And because of that, most people end up using things like single, maybe, and completeable. That’s what they are, they are a single, one-shot thing, a single allows you to have a type, maybe it is nullable, and the completeable doesn’t have a return type. They are all pretty similar. But in fact, they only exist on RX Java, RX Ruby So they can be replaced by single, maybe, and completeable They do what you think. They replace call-backs, and they replace these nicely. So as an example, we have a retrofit interface, and it has a Git and returns a single. And the way you use that a in RX Java, we have the scheduler, and we will do some calls when it is finish ed. The nice thing about the RX two libraries of coroutines, you can use that exact single as an await. So you can actually use it as a suspending deferred. So it is handy for when you are slowly migrating towards coroutines and you don’t want to change from day one. You can actually keep those interfaces, and you can actually just call await on them and you never receive using coroutines. It is a handy way to slowly migrate And wouldn’t it be great if we can make the retrofit call, a suspending function, and remove the RX from the start? Well, we can. And that is coming to retrofit soon. Jake has a PR, in review, and he tells me it is soon. And if you look at consuming code, it is a normal suspending call. And that brings us to a final section, bringing it together and trying to think of two scenarios that we will show you to use coroutines to make your lives easier on Android. Both of these examples are about location. The first is about getting the last known location, which is the call back. And we will use the fused location provider client. And it is kind of cool, it combines all the providers that we have, like WiFi, GPS, mobile, and bluetooth, it provides all the providers for you into one single API. It is a nice API to use. And it returns a task, a futury-type thing that the library has

And so you get the classification and it returns the task. And then you add the complete listener and you get the result back. So it is completely async So what we are doing is we are converting the call back API into a suspended function. The coroutines library has two builders that do what we want The first is suspend Coroutine, and you pass a Lambda under it that allows you to set up the call back. So we call play services. And then, at that point, the Coroutine suspends waiting for the results to come back, and the call back can wake up, basically So right now, you are getting a continuation to later resume And then you will pass the result back And it allows the call So there is the suspend cancelable Coroutine. So let’s say it is canceled, you can — under the line API, play services, to cancel its call So we will build that function, get classification, and it returns a location, not the future or anything like that Just a straight location. And so we are going to use our suspend cancelable Coroutine builder, and then you get a continuation, the call-back type thing, and then we are going to set up, so you are going to call the location client, the play services API, the last location, and then we get a task back and add the complete listener. At that point, we are going to wake up our Coroutine. So that is how we pass back to the suspended Coroutine, the result, and it wakes up in the suspended function basically, or it resumes And because this is a cancelable, because this we are using task, we are not using success, we are using the complete listener, which means that the task itself can throw an exception. It can fail for whatever reason, so you don’t have location permission or whatever it be. It will raise an exception on you, so you can populate that back up to the call, which is done with the review and exception method And finally, because we are using suspend cancelable Coroutine, we need to tell the play services API that we have been canceled, so therefore it should cancel. So we did that with a call back, which is invoke on completion, and once you know it has been canceled, you have play services. And play services does not have the cancel method, but imagine it exists And now Adam is going to talk about observing SPEAKER: Sure. So what happens when you want to observe a sequence of events over time? This is what RX is good at, if you are using it for anything t , it should be this. People compare RX and coroutines quite a bit, so what does it look like if we emulate this using coroutines as a primitive. So it is an API in addition to letting you get a one-shot, it the current location, you have the up adapts updates. So this is a prime candidate to be an observable. And we get this composable control over shutting it down the down the updates cleanly. It offers a lot of functionality to build things like this. So how many similar benefits can we get if we base this off of suspending functions? So let’s again start just writing a simple function, or it is going to start out simple Suspending functions do not return until the work is done There is no disposable or closeable return, since the calling scope itself is cancelable, we do not return until we are done. So the observer in this case can be a Lambda that accepts a location result, we will call it whenever a new location is reported without returning from the observed location. So if you take in the giant pile of code here, some of you may mote notice that it looks like an observable.create. We will create the done signal that we can await on later, so is this like the observable completion If you have a stream with a well-defined end signal, you can clean this up to let it clean up and return and we will see that in a bit. So the next piece here, we are creating a location call-back, we need to know when to receive updates from the provider. We use launch to get the — the Coroutine scope that we opened here carries the dispatcher with it that it was called with. So we know that we

are going to call the observer in the same place that the caller wanted the information reported So we cancel the old job, and we call the observer when holding the suspending new text, it keeps it serialized so we don’t have too many at once And it will not have multiple calls open at once either. And this is an example of some of the things that if you are building one of these things yourself, this is a comparison that RX Java does a lot of these things for you. With coroutines, we have the primitives to build it, but we need to do a little bit more by hand. And so we register the call back, and then we await on the done signal. Since we never complete it, when is the location stream complete anyway? This waits for the calling job to be canceled. So we have it on the blog, and request location updates takes a looper instead of an executor, which is unfortunate. So if you can use a direct executor, it will just go ahead and run the observer wherever the update happens on the incoming binding thread, it shines when you can avoid the extra hops. You get the idea And so here is what it looks like in use, and it looks a lot like a four H call in a collection and behaves the same way. If we use launch to call the observer, if the location call itself will throw in itself. So it is a child job, it will chancel the parent scope with the exception as well, what wraps the observed location function body. It will have the await, unregister it from the final block from above and all of this composes so you can lean on the constructs of the language that you know by adding some of these suspending primitives SPEAKER: So we will wrap up a little bit. What is next? Well, the first is that, as you saw thin keynote earlier, we have a code lab for coroutines, that was released three weeks ago, a really good introduction into coroutines and how to use it in your app. Read the manual, and the docs are really, really good And you can edit them how you want to, they are use-case based, so I need to do X, how do I do it? Make sure to check it out if you are using coroutines That is it, thank you very much [ Applause.] Coming up next: Modern WebView Best Practices by Nate Fischer, Richard Coles, Toby Sargeant Coming up next: Modern WebView Coming up next: Modern WebView Best Practices by Nate Fischer, Coming up next: Modern WebView Best Practices by Nate Fischer, Coming up next: Modern WebView Coming up next: Modern WebView Best Practices by Nate Fischer, Coming up next: Modern WebView Best Practices by Nate Fischer, Coming up next: Modern WebView Best Practices by Nate Fischer, Richard Coles, Toby Sargeant 1XZ Coming up next: Modern WebView

Best Practices by Nate Fischer, Richard Coles, Toby Sargeant. [

Applause ] SPEAKER: Hi, everyone. My name

is Nate, I’m here from the WebView team, I would like to talk about some modern WebView best practices or, as I like to call it, using WebView like it is 2018. Because it is Before I dive into what is modern with WebView, we will talk about what is old So WebView has been around since the very beginning, added in API level 1, and it changed in a significant way, starting with Lollipop. It became updateable, the implementation was. And this was great, it meant that users could benefit from security fixes and bug fixes, it would update every six weeks, just like your browser. And a lot has changed since then, too We added 40 new APIs, ZUST — just to make it easier to work with WebView to help developers But what has really changed? Well, when we look at the ecosystem, it seems like apps are kind of using WebView the same way they have always used it. And when you look at StackOverflow, the answers are outdated at best. They are certainly not best practices and, often times, they are just wrong. But some of the blame is on our shoulders, too. A lot of the doc is still written like it is API level one and a lot has changed since then. So we looked over the past year and we looked out at the Android ecosystem and the devices that are out there today. And what we found is that, although we added, you know, on nougat, all of these great APIs, a lot of apps cannot take advantage of them because they run on the nougat devices, less than 5 percent of devices today and it has been two years since it came out. And a lot of devices are running lollipop and the implementation of the APIs are not exposed on older platform levels. We thought, can we do better? So, over the past year, we worked on our AndroidX library We launched a new AndroidX library, and we are pretty excited about it. The basic idea is we will bring in all of these brand new developer APIs, but we are going to try to give you the device coverage you need, and we are going to support lollipop and above. We will leverage the update cycle, and make sure that it is usable so you can use the APIs to do productive things. We designed them to be straightforward to swap out from the framework’s APIs. So this all sounds fine, but how can we use it to make your apps better? So let’s take an example. Since the very beginning of Android, we have given apps a lot of power to customize WebView’s behavior. And, in particular, we added a call back called override loading, and the idea of this call back, for search and navigations, you can cancel things in the WebView and dispatch them to a different thread instead. Joy can have a YouTube url that is better suited in the YouTube app. And this is great, a lot of apps took advantage of this. But there was a problem with the API, we did not get it right the first time. And the issues that JavaScript can trigger navigations, there is malicious JavaScript out in the wild that actually tries to exploit this app behavior. And, from the useruser’s perspective, they might be reading web content and without their interaction, it starts opening up some new Android app that they are not trying to open And so we actually already fixed this issue. We fixed it back in Nougat, where the idea is that we exposed this notion of user gesture. Did the user trigger this navigation? And it actually works really, really well, but it only works on the Nougat and above devices, and these — before, Nougat devices are still vulnerable Weal thought it was a candidate

for AndroidX library, we will do this gesture all the way back to loll Pop for devices and you can make it a safe experience for all of your users, and we can make it easy for apps to override T There is no confusion. I think we succeeded, but we will look at the code. Before Nougat this is what a lot of app code looked like, we are doing overview coding, and in the coding, and this is the insecure version of the API but in the past the best we could do. Some better apps that were out there is something like this, you are overriding the old implement from before, the before Nougat devices, and the newer devices, you have this implementation, we are choosing user gesture, we not launching intent if we don’t have user gesture So this seems great, but it only runs on a small number of devices, even today, only 50 percent So here’s how it looks like with AndroidX. And the first thing I want to point out is that almost nothing changed on this slide I think that is really beautiful, it means all the code that you already wrote to handle, you know, the old framework APIs, that code is all the same The only difference here is that we are employing — we are importing our WebView client compat class from the AndroidX library, we setting this compat client, and the idea is that we are using the compat client, instead of invoked on Nougat and involved, they are invoked to Lollipop so you can provide your users a safer experience without changing a lot of code This is one example we have to everyone in AndroidX. O I I would like you to check it out it to so how it can make your app better. We are giving you the device coverage you need to use these APIs, but we will have a lot more APIs available. Some of these are small improvements on classic APIs, like we’ve seen, and some them are for en tirely new features, like safe browsing And had point is this is not in a soon to be released library, it is out there, ready to go, so you can try to 1.0 release. I would like to shift gears a little bit. We looked at the AndroidX APIs, these same great You are going to give us new APIs with, you know, pretty good device coverage, almost ninety 90 percent. What about the APIs around forever, they have 100 percent device coverage, but some of them are hard to use Even I struggle to use them correctly and I working on the team. A common use cay we have seen is loading in-app content And the idea is that you want to display some content in your application, but you don’t necessarily want to fetch it over the internet, you want to just compile it right into your app But you also want to continue to build this content with web technology. You want to use html, JavaScript, CSS. And WebView has had pretty good support for this, in fact, we almost have too much support for this. We have so many APIs that it is hard to figure out which one is actually the right thing to use And some of them have some weird gotchas that make them kind of hard to use And so I thought maybe we could take a look at some of these APIs and talk about what is so tough about them and recommend some best practices. You don’t have to start from scratch with a new API, but you can kind of tweak how you are using these So the first API that we can look at is Load Data, and the basic idea is that this is going to accept some html content. It accepts it as a string, and it is supposed to display this in the WebView And but one of the gotchas is it does not really accept html content, but encoded content The idea is that you need to escape special characters, replace them with a percent sign and the code following it And we call this percent in coding, this is the default configuration for the API. But there is actually no framework API to do the percent in coding for you It is kind of an oversight But the end result is that developers, what we’ve seen, is that developers tend to actually do this percent in coding by hand themselves. And this is manual, it leads to bugs, and these bugs can have significant impacts for your application You know, one small bug might seem okay today, but it might break in a future WebView update if you forget to encode a

particular character The other issue with load data is this thing called an opaque origin So when your content is loaded with what is called an opaque origin, this means that it is going to fail all the same origin checks in the web And these same origin checks are actually chit critical to providing powerful web APIs securely. Without these, you cannot provide great APIs, like html http requests So what can you do with this APIAPI? You can escape the coding-related problems. This API has always accepted an alternate encoding scheme, base 64. This is not that special of a coding scheme, it is just a different scheme. It is not necessarily better, but it is kind of nice because there is actually a framework API that will do the encoding for you, and it does it correctly Great So the base64, encode to string, it will take the content, spit out the right answer. And the only reason it is not documented is because this came out in API level 8, which today is ancient history, but was still in the future at the time of writing load data But we can also take a look at the same origin restrictions So the way we recommend to get around this is to use something called load data with base url And one of the nice things about this, I think of it as a feature, not a bug, is that it actually accepts the content as is. You can give it content that is totally unencoded, you don’t have to worry about the base 64 stuff if you use this API The other really nice thing about it is it has this thing called a base url. You are displaying this as you pass in as a string, the base url configures the origin that it operates it. You can control the origin that you get without disabling the important security settings, just to make the APIs work. How do we choose the right base url? So this is something that even I struggle with when I try to use this API, I know it is the right thing, but I don’t know what the right thing is to pass to it So we will go through the common use cases. So something that we’ve seen in a lut lot of apps use cached content, it is downloaded from the web over the internet, but they are saving it for later. Now when they show it, they need to show it with the right base url. And the url you choose is just the original url it came from. So if it worked originally, it has the same origin and all the APIs are going to continue to work. The other use case that we have noticed is that apps tend to shift the own content and display it this way, which is great And we recommend that you choose a real internet-type url, and it should use your organization’s real domain. The reason for this is so you can import other resources from the servers and use this content without worrying about same origin checks, it will all work. And the question is, do we use https or http? Here is the rule of thumb, you want to use https as the secure protocol. If you need to share insecure resources, we recommend that you use the html scheme as opposed to disabling important security settings just to get your app working And as a last point I want to urge apps to avoid curs custom url schemes. This is something that cropped up, they make up their own scheme and use that But the problem is that the web standards don’t really expect custom url schemes. They are very vague about how to handle this, and it turns out that they wind up getting handled very inconsistently, and this can lead to surprising app breakage So if you can stick to one of the internet url schemes you will have a much better time So hopefully I have expressed that we care about developers at the WebView team and we are working hard to make sure THLT that you have powerful new APIs, paying attention to the old APIs, and explaining how they need to be used and they are actually usable. If you have any questions, me and my colleagues will be around for the rest of today as well as tomorrow and would be more than happy to talk to you about WebView usage and what you need for your application. Thank you very much [ Applause.] Coming up next: Low Latency

Audio – Because Your Ears Are Worth It by Don Turner Coming up next: Low Latency Audio – Because Your Ears Are Worth It by Don Turner

SPEAKER: Hello, hello. My name is Don, I work in the Android developer team, I’m here today to talk to you about low latency audio on Android So why is audio latency important? Well, there are many use cases where the audio latency is directly proportional to the user experience So this can be in games, where you tap on the screen and you hear a sound, particularly in rhythm games, like Guitar Hero-style games, you are tapping in response to some rhythmic event and you need to have audible feedback as quickly as possible, like the longer the delay between tapping on the screen and hearing a sound, the worse the user experience And also in DJing apps, you are tapping on the screen and manipulating odd we and you expect that audio manipulation to happen in realtime Karaoke, you have the input, your voice, against a backing track and also your own voice So if the delay between you singing and hearing your own voice is too long, then it sounds awful And also, in VR, we have objects that make sound in a virtual world and, if that sound doesn’t follow you around as your head moves in this environment, then it kind of distorts the reality And lastly, of course, theres a whole load of apps for live performance, sin hesizers, drumming apps, anything where you press a key and make a sound, you need low-latency audio So, with this in mind, we built a library to help developers build these kind of apps. It is called Oboe, and it is available on GitHub now. We just launched version 1, it is production-ready, to be included in your apps today And the way it works is, under the hood, it uses the audio API on API 27 and above, which is the new high performance, low latency, audio introduced in Oreo. And on all the devices, it uses open SLES. It

provides a simple, easy-to-use API that works across the widest range of devices So rather than me talking about this API, I thought it would be fun to build a musical instrument in 17 minutes and 23 seconds So, before I start that, I’m going to explain the architecture so it makes sense when I’m in the code. So we have an app, and I’m going to build the audioengine part of this app This audioengine is going to be responsible for creating an audiostream that is provided by the Oboe library, we’re going to be passing audio frames of data into this audiostream Ultimately, this stream is responsible for putting data out of the audio device. In this case, it will be the 3 and a half millimeter jack on this pixel XL phone. And every time the audio device needs more information, it is going to give us a call-back. So we get this call-back loop of, hey, I need more audio data, and our audioengine is going to be passing frames of audio data into the audiostream For some form of control, we’re going to monitor tap events in that screen. When you tap down, the sound will go on. When you lift up, the sound will go off This works about 50 percent of the time in rehearsal, we will see what happens Okay First, I need to log in Okay, and can you see my screen? Fantastic Okay, so I’m just going to run the app. So I have a very simple shell of an app. It doesn’t really do anything at the moment, but it has a few little shortcuts that make it possible for me to do this in a short amount of time So I would just run the app on this pixel XL, and hopefully you will be able to see that it does nothing So here we go. Here is the app, when I tap on the screen, nothing happens. No sound comes out, it is non-functional. I want you to know that there is no smoke and mir and mirrorers, it is jen genuinely live [ Laughter ] Thank you, GLRKS Glenn I have a few methods I will use, and I will implement them in a second So we will create an audioengine, and we will start by calling start engine So we will just jump into our J&I code So this is in native lib.CVP here. So I’m going to define an audioengine up here I will call it engine And then I’m going to call a method on my engine called start And now, I have already created the header and implementation files, just the blank files for this audioengine class. So I will go ahead now and write the class So audioengine And I’m going to have one method called start Okay, now I can use option enter to generate the definition for this in my implementation and I’m in the start method. Before I use the Oboe library, I need to include the Oboe header There we go And the other thing I need to do, where it makes it easier for me, to use the Oboe name space And this avoids me having to prefix the objects with the word Oboe So, in our start method, I will create an audiostream. To do that, we use an audiostream builder That builder allows us to set properties on the stream. That is like the format of the stream And now, when I set the format, there are two choices I can choose from, 16-bit integers, or floats. I will use floats. I can also set the number of channels, so that is two for stereo, or one for mono And I can also set properties which inform the stream of my latency requirements. So the most important one here is set

performance mode And there’s a number of options, but the one I want is the low latency one The second thing I can do is set the sharing mode on the stream We will set that. I will set it to an exclusive sharing mode So that means that I’m requesting the audio device give me an exclusive stream, that means that my app’s audio is not mixed with any other audio in the system. If the device supports it, I can avoid having my odd ye — audio mixed with anything else and I can cut a few milliseconds of latency in the output So that’s all I need to do to open the stream, Joe can go ahead now and call open stream, this takes a reference now to an audiostream pointer. I can use option enter to create a new field called stream. So back in the header, it is done automatically for me. And once the stream is open, there is one final step I need to take which, is to set the buffer size on the stream. I can do this by setting buffer size in frames To get the smallest possible buffer size, we have to interrogate the audio device for the minimal amount of data it will read in one operation, a discrete chunk of audio data, and we call it a burst. So we want to obtain the burst size from the odd — audio device We will use stream, gets per burst. And that’s the minimum number of buffers we can set our stream to have, but we to not recommend that you use this absolute minimum. We recognize that you use double this, because it provides a good protection against under runs, and it is a good tradeoff with latency That’s all I need to do to create a low latency stream. So I can go ahead and start the stream, which will do nothing because we have not found a way of putting data into the stream To get the data into the stream, we use a call back. I’m back in the builder, I will send the call back method. It will take the call back object, and using this, I will use my this object, which means that my audioengine needs to implement this interface So I will do this, and I will use control O to show me the methods I can override in this interface. I want on radio ready, the method that is called every time the audio device needs more data So inside here, I will look at what this method signature is So on audio ready is called, it tells me the stream that wants more data, and it gives me a container array. So this container array, which is of type void star, because it can be either 16 bit integers, or floating point samples is something that I’m going to write my audio data into. SoI so I write that, that is passed to the audio device. And next is num frames, it tells me the number of num frames that need to be populated in this container array. I need an audio source, I will cheat a little bit here. I created an oscillator in advance, we will take a quick look at it, and it is going to generate a square wave here. So that’s a periodic signal, varying between two points to create a square wave We will create an oscillator So this is the template object, I need to tell it what type I will include the oscillator header. And now I have the oscillator, I will do ask render, so Android Studio is complaining about the signature I will build, and that will normally sort it out Ignore the arrows. So on my oscillatoroscillator, I have a render method to put the audio frames from the oscillator into the audio data array. So the first thing I need to do is to cast it to this — an array of

floats So audio data And pass in the number of frames So the last thing I need to do on audio ready is return a result. This can be either to continue where the call backs will continue, or it can be stopped and the call backs will stop. So, in my case, I’m going to continue. And the final thing I want to do is set some things up on my oscillator And soso I’m going to set the amplitude, which is the volume, and I’m also going to set the frequency, set that at 80 hertz, a nice base freaks frequency, and the sample rate, which tells the oscillator how frequently these samples should be produced And I can get that from the stream, get sample rate there Okay, I know that you are all desperate to hear a sound There is a final thing I need to do here, I need to respond to tap events. So I will just go back into the main activity and I will override the on touch event so that if the event is down, then I’m going to call this native method tap, to make that true Otherwise, if the event is up, I’m lifting my finger off the screen, then I will pass in false. Okay, let’s have a look at the tap method This needs implementing So I will pass in the true or false value, create the new method, and they will just call ask, set, wave on, and that is going to pass that in there Now, a moment of truth So I’m going to run this and, in theory, you should hear a sound And when I tap on the screen, we should hear an 80 hertz square wave The pressure [Tone] There we go [ Applause ] [Buzzing noise] SPEAKER: So you can see, it is the lowest possible latency here, and it is actually — [series of beeps] — pretty responsive. So we have a musical instrument. Admittedly, it is not the best instrument in the world. It is a little bit to be desired on the sound. So what I thought would be nice is if you could add a little bit more control. So for the last four minutes and 30 seconds, I will tie the motion sensor to the pitch of the oscillator. To do this, I’m going to cheap. I will call in some code that I did earlier, and it will register a list now that will listen to the rotation vector sensor So to listen to these events, I need to implement the sensor eventevent listener interface, implement the methods, onsensorchanged. So what I want to do is set the frequency based on the event values of the X axis. And I also need to scale this value So I want to have it from, let’s say, from 20 hertz, the limit of human hearing, and we will go up to, like,- this will give me up to around 100 hertz So, yep, that looks good So again, I need to implement this Frequency… so we will just go ask set frequency, and there we go Okay, so we are good to go on that. Brief interlude. Very brief, in fact. Has anyone heard of the R man break? One person. So the R man break

comes from a song in the ’60s, R man brother, 4bar four bars of the most incredible drum solo, the most sampled loop in history, but nobody has heard of it evidently, apart from one guy. I thought it would be nice if I can play my new musical instrument over this loop So here’s the loop, I need to run the app. We will give it a go We will make sure it is here So, with a bit of luck [drum sample] [Oscillating tone] [Drumming and oscillating tone] SPEAKER: Right [ Applause ] SPEAKER: Okay, so that is about it from me. If you can go back to the slides And, yes, the library is available on GitHub. There’s a documentation, codelabs, all sort saidsses of stuff in there We would love for you to build awesome experiences on Android, and I’m here for any questions Thank you all very much [ Applause ] SPEAKER: Thanks, Don. With the end of that talk, that is the end of the day That means that it is time for a par party. So the theory is we will have food, drinks, and a DJ. I vote for Don do the DJ I wanted want to hear that tune all night long, or a two-minute loop and that is probably about enough. So 6:20, the party starts