In this episode we talk to Ty Smith about all things Developer Platform. Currently a tech lead at Uber, Ty has quite the illustrious career having worked on some of the biggest names you’ve heard like Uber, Twitter(Fabric), Evernote, Zagat etc.
Unlike regular client app development, Developer Platform spans a variety of interesting topics like building consumable SDKs, building libraries with good APIs, creating Android integrations and App to app communication via components like Content Providers, AIDL Integrations, Intent APIS and deep links.
We ask Ty how he got started in this field, how one should go about thinking about it and the interesting challenges that one would run across in this intriguing field.
Ty’s all star Dallas crew
- Chris Banes [@chrisbanes] previously on FriendCaster
- Chris Arvin [@ChrisArvinSF] previously on BaconReader
- Juan Gomez [@_juandg] on Netflix
- Matt Wear [parallelcross.com] prevoiusly on Evernote
- Tests? Ain’t Nobody Got Time For That! by Ty Smith [youtube.com]
- Content providers [developer.android.com]
- AIDL (Andorid Interface Definition Language) [developer.android.com]
- TransactionTooLargeException [developer.android.com]
- @tsmith [twitter.com]
- @fragmentedcast [twitter.com]
- @donnfelker and +DonnFelker
- @kaushikgopal and +KaushikGopalIsMe
Donn Felker: Okay, here we are again. How are you doing, Kaushik?
Kaushik Gopal: I’m doing well. How are you?
DF: I’m doing really well. I’m very excited about today’s topic. It’s something I’ve dabbled in for a couple of clients, but not at the level of the gentleman who we have on today’s show.
KG: Yeah, this gentleman is known for having a sound understanding of the subject.
DF: Definitely. Let’s go ahead and introduce him before we really dive in. Ty Smith, welcome to the show!
Ty Smith: Thank you, guys. How are you doing today?
DF: We’re doing well. Thanks for coming on the show. For folks who haven’t been introduced to you, could you give a little background information about yourself? You know: who you are, where you work, and where you’ve worked before. You have quite an impressive background in Android, and learning a bit about it would be a great help.
TS: Sure. I’m currently a Android engineer at Uber. I’m the tech lead on the mobile platform’s external API, which is our group that focuses on external partners and how they integrate with our platform. I’ve been working for developer platform related companies within the Android space for quite a while, but before that, I was just doing pure product development on Android.
The very first step I took is actually a pretty funny story. I was working at this small consulting company as a Ruby on Rails developer. I was going along my merry way, not worried about the really hard world of mobile. I wasn’t worried about fragmentation or anything else.
KG: No concurrency training. No main threads.
TS: No semi-colons. Ruby was nice! So my boss, the founder of the company, came to me one day and said, “Hey, we’ve got this pretty large client.” You guys may have heard of Zagat. They’re a restaurant review company based in New York. They were purchased by Google years after I worked on the project.
Anyway, he said, “We secured this project. We were subcontracting, working on the Zagat app, and we hired this Android contractor.” This was 2009, so Android was pretty fresh. I think we were working with Android 1.6 on an LG G1. “We hired this contractor, but due to some issues, he’s going to have to step off the project.” This was two or three weeks in. “We have a really tight timeline. How do you feel about learning Android and shipping the first version of this in 3-4 months?” I think I said something to the effect of, “I don’t think you’re really asking my opinion.” He was like, “Well, that’s the state of the world.” So I dove right in and worked on it. I don’t think we made it on time, but it went out and worked fine. It was great.
I stuck around at that job for a little while, working on a few other small app contracts. Then I ended up moving to the company that had contracted to us for Zagat. It was a small company out in Texas, called Handmark at the time. They ended up splitting off into another company called OneLouder, which you guys may have heard of. Chris Banes worked on a Facebook app called Flow that they purchased, which then became FriendCaster. So I worked on Zagat directly there for a little while, and then I worked on an app for Sprint. They were a big partner with Sprint to write their SMS, MMS, and group messaging app.
It was almost amusing, because several names who are pretty well-known in the Android community worked there with me at the time. When Chris Banes’ app was bought, he helped out for a little bit as a contractor. Chris Arvin did BaconReader, which they bought. Then he went to Expedia with Dan Lew. Juan Gomez, who is now at Netflix, came in there to take over the project I was on right as I left. Matt Wear was another guy in this community. He was at Evernote, and is now at HomeAway. So there’s this tiny little Dallas based consulting company who had a few of the Android community folks float through.
KG: Wow, that’s an Android all-star crew there.
TS: Yeah, it was interesting. After a year or so there, I moved out of Texas into the Bay Area. That’s when I got my first taste of Silicon Valley life. I joined Evernote to do Android work. It started with normal product work—doing different features and design-related stuff. I was there when we did the Holo redesign, which was interesting. That was a fun project.
Then I started working a lot on business development and Partner Integrations for different specific partners who we worked with. I started working with the developer relations folks, and developed a passion for interacting with external developers and for these integrations. I began to see how Android could really become a platform there. I thought, “Wow, I really like this developer advocacy and ‘Android engineering as a platform’ perspective.”
After I worked there for a couple of years, I moved to Twitter and worked on Fabric, which I’m sure most of you are familiar with. It was a very small team at the time, right after the acquisition of Crashlytics. I worked pretty heavily, and saw it move from a single SDK to a suite of SDKs. Now, finally, I’m at Uber, working on building a new developer platform. I’m trying to make Uber a platform and build strong use cases that people want to integrate with. It’s pretty interesting.
DF: If you had to explain what a developer platform is to someone who’s just getting into Android development, how would you do it, and why would they want to use it?
TS: I think there are a few different elements to a developer platform. There are all the APIs, docks, and everything else that you expect to be able to interact with. But you have these different companies who view developer platforms in slightly different ways. Some companies build tooling, and that’s their primary value—companies like Optimizely, Leanplum, BuddyBuild, and even Crashlytics (before they were acquired by Twitter). Their primary job is selling an SDK, an API, or some sort of other developer tool to their audience. For those companies, their developer platform and tooling is their lifeblood.
But then you have other companies—like Twitter, Facebook, and Dropbox—who see the developer platform as a way to extend outside of their core competencies and build up power users who have multiple integrations. They try to encourage new apps to build in and create a stronger platform with higher retention.
So you have these two different perspectives. The bigger companies (which I’ve been working with more recently) view it as just one other way to acquire users and then provide value to them. But some of the other companies (which I’ve invested in and give advising to) focus more explicitly on the developer platform as a tool that’s directly served to their customer, which they try to make revenue on.
KG: You summed it up really well. So essentially, there are two aspects to this: there are companies who want to expose a service that they provide (for example, Uber exposing the service of using Uber) as a platform; and there are companies that provide with developer tooling as a product.
So developer platforms actually encompass both business development support and the whole SDK, along with any integration that had to be done on the back end. Essentially, any company that has an API that’s consumable from the outside needs to up their game on the developer platform scene.
TS: It depends on the company. I mean, for a long time, Twitter just had a restful API that people could hit. It wasn’t until after the acquisition of Crashlytics that they started building multiple teams which were focused on how to give a good development experience to mobile developers (as well as, potentially, server developers).
KG: That’s a good distinction.
TS: It definitely went through its ups and downs, but the main third-party library for consuming the API (Twitter4J) was completely community developed. It wasn’t until Fabric that they started bringing some of that in house, saying, “How can we control this piece of the platform?”
DF: A lot of folks who listen to this show are on teams that are either building or wanting to build some type of developer platform—or even just an SDK that they can ship to other users. I know that you’ve worked on these things at the various companies that you’ve worked at. I’d like to start discussing what the best way would be for folks to build consumable SDKs for different developers and teams.
The reason why I want to talk about that right now is that I’ve actually had a small bit of experience doing this for previous clients. We had built some things with AIDL services, content providers, and all kinds of different ways to expose data. But I was wondering if you had thoughts on what you would consider most important when you’re building and shipping these SDKs. Is it stability? Is it a consistent API? Is it package visibility? Is it testing? Is it hosting? Let’s hop into that for a little bit.
TS: I think that stability is probably your number one concern. This is incredibly important for a few reasons. First, when you roll out an SDK, you’re rolling out a binary to a hosted location. Say you’re on Maven Central, and people are consuming it. Maybe you are even just putting out the source code on Github, and you don’t have a binary. But you put this out in a steady state and say, “Okay, I have an SDK that my customers should start using.”
Now if I’m an app developer and push out a crashy update, I can notice that. I can check Crashlytics or Bugsnag. I can see that I have bugs, get user reports, and (potentially) roll out a fix pretty quickly.
But when you roll out an SDK that has issues, the developers that are consuming it aren’t thinking about it past the point where they integrate it. That’s not the business value that they’re providing. They just want to include it so that they can get some analytics, load an image, do some dependency injection, or whatever use case drove them to do that. But once they’ve put it in (with very few exceptions), they’re not actively thinking about it, watching the new releases that you’re putting out, and seeing the communication that you’re trying to drive to your community. If you put out an SDK that crashes—one that’s a horrible experience for the consumers of your customer’s application (your customer being the developer)—this application may be their lifeblood. They may be indie developers who are making their income off of this, and you’re causing a poor experience for their users.
KG: It isn’t just indie developers, though. Even when you work at a medium-size company (like I do), if an SDK or a library that you use crashes, you immediately lose all faith in it. The whole idea is to save our time. We don’t want to actually build this on our own (which most engineers typically love doing). The only reason to use it is so that you don’t have to deal with the problems—and the minute the library starts crashing, it becomes your problem. That’s a big no-no.
DF: It’s like a black box, too.
TS: Absolutely, depending on whether it’s open source or not. But one of the bigger problems with that is that once it’s crashing and you push it out, it may not be a clear crash. What if your SDK needs to talk to a web service, and you’re improperly using the Alarm Manager, the Job Scheduler, or something like that, and you start DDOS-ing your own web service? You have to try to communicate to the different implementers of your SDK that, “Hey, you guys are seeing a lot of users. Because you’re seeing a lot of users, we’re getting a lot of traffic on our SDK. But we had a bug in our SDK, so you need to put out another update.” That’s a terrible relationship to have with your developer.
Even once you put out the update, it may be weeks or months before they see there is one. Then, if they’re not on a regular build train, it may be months more before the update is out in the wild. So if you put out a crashy update, the crash might be out in the wild for months.
KG: Just thinking about that sends shivers up my spine.
TS: What that makes you do is think about strong engineering rigor. Test the quality of your APIs. Dogfood them. Get really strong user feedback. It instills a lot of the other qualities that you have to think about when you’re building SDKs.
KG: I have two quick follow up questions. First, when you’re building an SDK or working on developer platforms, does that mean that you can’t afford to move as fast as startups typically do? For example, if you’re building a front-end consumer product, most startups intend to accelerate at neck-breaking paces. They understand the trade-off: “Sure, if we move fast and release a feature, sometimes there might be crashes. We’re willing to accept the pain that’s associated with users facing that crash.” That isn’t necessarily a luxury you can get as a library or SDK maintainer. Does that mean that you intentionally slow down your pace, or do you try to adjust that by having more tests?
TS: I think it requires a different mentality, honestly. I believe that you can still move quickly while testing. If you’re thorough in your architecture and hire the right quality of engineers, it’s possible to write testable code in a well-architected, separated way, so that you can have confidence in it and sleep at night, even when you’re on call while moving at startup speed.
I gave a satirical talk on this at Square last year called “Tests? Ain’t Nobody Got Time for That!” It was about the other qualities that having to test your code makes you think about. Once you get into the mindset of separated, proper interfaces with modular, more maintainable code, it actually becomes somewhat challenging to go back to thinking about coupled spaghetti code. In my mind, it’s made me a much better engineer to think about systems in this way.
Maybe you can’t move quite as fast as someone who’s constantly pumping out features, but in the end, they’re thinking about different product requirements than you are. They’re retaining users by having new features to compete against their competitors. You’re retaining your developer users by building developer trust, ease of integration, and a developer community.
KG: That makes sense. Second, you mentioned that when your interface crashes, you use something like Crashlytics to see what your crash metrics are. I was curious: if you develop an SDK and discover a crash happening, how do you monitor that on the other side of the equation? For example, if my app is crashing, I use Crashlytics—but can you use Crashlytics inside your SDK?
TS: I think there isn’t one straightforward answer to that question. In general, I think that putting analytics in an open-source SDK would be viewed pretty negatively. One of the conversations that I had at Twitter when we were putting out the Twitter single sign-On SDK, the embedded tweet SDK, and all of that, was, “How do we record impressions on the different things? From a business value, we care about that, but developers may not want this open-source library that they’re including to be sending up analytics events.” I think there is a balance to be had. You have to be clear with your developer community as to what you’re tracking and why you’re tracking it, so that they can trust the transparency that you’re providing.
But when it comes specifically to crashing, that’s difficult as well. When a Java crash happens, the UncaughtExceptionHandler is thrown. It’s a global system that’s going to handle it from that point. So when you use something like Crashlytics, it makes it pretty easy to see, “Hey, we had a crash in our code,” and they can funnel that stack trace down, such that the SDK or the developer app can get information on the crash.
But that’s a unique case, where the platform owner sees that. When you’re developing something like the Evernote SDK or the Uber SDK, it becomes a lot more challenging. You have to rely a lot more on communication from your developers, who see the crashes going on. I can imagine scenarios where you would do things like install your own UncaughtExceptionHandler and then wrap their UncaughtExceptionHandler, but there are a lot of edge cases that could come along with that. You could have conflicts. You could be dual-reporting. You could prevent their crashes from going up. I’m not saying that you shouldn’t, and I’m sure that some companies have figured out how to do that the right way, but I think that relying on communications from your developer community is paramount.
DF: Naming is one of the hardest things in software, it seems. There are a lot of arguments about how you should name things. In your experience, have you come across any tips or tricks about accurately naming something? What are your thoughts on that?
TS: It’s a little more complex when you’re dealing with SDKs or libraries than when you’re just managing your own project. It can be a really big problem when you put out an API in one version, and then say, “Oh, I have a better name for that”, and change it in the next version. Suddenly, you’ve broken the consumer side when they auto-update. Once you put a name out, you’re stuck with it unless you want to deprecate it. I think that having a better name is not a very good reason to deprecate a method! So putting out some guidelines up front on how you want to name your call-backs, how you want to engage with your methods, or how you keep some consistency between multiple platforms (such as iOS and Android) is pretty important, so that you have a general environment that people become familiar with.
There’s a funny saying that I like to throw around. I don’t know where I originally heard it, but it’s that an API is like a baby: they’re fun to make, but you have to support them for 18 years.
KG: That’s so true. Breaking APIs can be a big problem. A simple method change essentially translates into breaking an API, right?
TS: Yeah, adding new parameters, removing them, changing the name…the list goes on. When you put something out there, you’re stuck with that for a while. You don’t always have the best name. Sometimes, you just have to suck it up and move on. But having some guidelines on how you want to build that out, and having consistency between those, is going to give a much better experience than iteratively trying to choose the best possible name.
KG: I imagine things like semantic versioning also help. People understand that if it’s moving from 1.0 to 2.0, something is breaking. The expectation is that some API is broken, so there’s some level of effort involved in adapting your code.
TS: That’s true, but in practice, I find that very idealistic. I stick with semantic versioning (like everyone else), but I see projects all over the place (even very well known projects) that do breaking API updates in minor version updates or patch updates. Also, especially when you have a broad range of users, not all developers understand that a move from 1.0 to 2.0 implies that it’s broken. Even with a broad range of shotgun communication—where you’re updating your changelog, sending out communications to the consumers of your SDK, and talking about it on Twitter (or the other channels that you frequently use for engaging with people)—you’re still going to run into people who have problems with it.
KG: You touched, offhand, on hosting in Maven Central. You said that if something is open-source, it’s probably on GitHub. Could you tell us about some of the options that you have as someone who maintains an SDK? What are your different options to host an SDK; and, in your experience, which options have worked pretty well?
TS: There are a couple different binaries that are pretty prevalent in the Android/Java ecosystem. One is the standard JAR, and the other is the AAR. We also have the APK library, which was an older format from when more people were using Maven. That was kind of community inspired, but it’s not really prominent these days. AAR is going to be more useful if you’re doing any sort of resource or view related work, whereas JAR is probably just fine if you’re doing pure Java. Depending on how you want to set up your Gradle builds to generate your SDK, AAR is probably simpler if you actually want to reference Android classes. Otherwise, you have to try to do source linking and build a Java project if you want to build a JAR that still references context, activities, or stuff like that.
But once you have your binary, there are a few different options (like you said). Maven Central and JCenter are two prevalent ones, but they both require you to have an open-source library. There is no concept of an induced license agreement acceptance or terms of service acceptance. As a consumer, you put in the Gradle dependency, the Maven dependency, or the Ivy dependency, and it’s consumed. There’s an explicit acceptance of the Terms of Service. Therefore, those hosting providers require that anything uploaded to them that’s available in the default repos be open-source. So if you’re open-source, it’s not too bad. You can just put it in Maven Central or JCenter.
I find that JCenter is slightly easier to work with. They have better plug-ins. The Gradle plug-ins are now hosted out of JCenter as well, I believe. It’s kind of a superset of Maven Central and some others. But Maven Central is a little bit more traditional—a little older. There’s still a lot of tooling that references it directly, so you have to add in JCenter manually. I don’t have a strong suggestion towards one or the other.
But if you aren’t hosting an open-source SDK, it becomes more problematic. You have to host your own repo, which would commonly be used by Artifactory. If you want to host it yourself, I’ve seen companies that just throw up an S3 repo with the Maven structure in it, but it becomes more of a headache.
KG: In fact, one of the options that you have (obviously, this wouldn’t really work with large commercial applications) is JitPack, which is something Donn suggested to me sometime back. It works perfectly well. They alleviate a lot of the boilerplate and nasty setup that’s required to host your stuff on Maven Central or JCenter. But obviously, JitPack is not a standard. It’s privately owned. That’s something to weigh in and think about.
TS: I’ve consumed a few things from JitPack, but I’ve never hosted anything on it. But it’s pulling it from GitHub, and I’ve heard stories of GitHub getting onto people who are using it as a hosting repository when higher amounts of traffic start going to it. That may be better for a small open-source library, but my intuition is that if you’re building a company’s developer platform, and you started getting heavy amounts of traffic to it, you might have representatives from GitHub knocking on your door.
KG: I think that they only pull from GitHub when you make a change, and then they cache it, but I could be wrong. I’m not entirely sure of the internals, but it would definitely be something to keep in mind.
TS: If that’s the case, that might alleviate the concern that I had. But one of the negatives for the user is still that they have to explicitly add the repo, which complicates the build sculpt and increases the complexity of the integration. Especially as you’re trying to target a broad range of developers, that’s something that you want to minimize.
DF: Now that we’ve talked a bit about building SDKs, sharing them, and other high level stuff, let’s hop a bit more into the weeds and talk about when we want an app to talk to another app. One of the primary examples of this is an app that has some type of single sign-on. Have you ever built anything that has single sign-on? If so, what were the main benefits of doing so?
TS: Yeah, I’ve worked on the Evernote single sign-on, the Twitter single sign-on, and the Uber single sign-on, so I have quite a bit of experience with that! I’ve also contributed, both through security reviews and pull requests, to Facebook’s and Dropbox’s, along with a few others.
DF: How does that work? If you build one, what does it look like? If I want to implement that in my application for my developer platform, what are the steps, tools, and concepts that I need to be aware of?
TS: The primary benefit to a third-party developer is to allow their users to authenticate against a third-party app with less overhead. Let’s say that you wanted to integrate with the Uber API. You have a couple different options. You can include the Uber Android SDK and hit some wrapped APIs.
But maybe you want to get the status of a trip that’s in progress, so you need to get an authentication token, such that you can check on the status of that trip. With the Uber app installed, you can navigate the user directly over to the Uber app, where they’re already signed in. They can authorize your third-party application, granting the scopes that are required for the information that you’re expecting, and then return the authorization token back to your application. Then you can make the API requests on behalf of the user.
Normally, you would want to some sort of graceful fallback for that, so that if the app was not installed the user would be able to complete the use case as well. For instance, when the app is installed, you take them to the app and have an experience for them to authorize the scopes. But when the app is not installed, you take them to an oAuth WebView where they can enter their credentials, and it will still return the authorization token so you can make the API request.
Let’s say that the second one had more overhead to it. Maybe you were using Chrome tabs, and they would have to sign in there as well. That’s a little extra complexity.
DF: In the first use case, that’s going to be a deep link, correct?
TS: It can be a couple of different things. It can be just a standard URI (a deep link), where you’re either using a universal deep link (with the app overwriting a specific HTTP URL that’s equivalent to the login for your page) or an explicit scheme for your application (say, “uber://”) and some content to get over to that.
However it could always be just a standard intent. The SDK could say, “Let’s construct an intent with this package set.” Maybe it has a specific action that we want to integrate with—say, one called “Authenticate User”, and it’s fired. My app is registered to receive that in the manifest. Or, if I was the developer, I could also use the Android account manager. That would have to have the extra permissions for “Get Account” and “Manage Accounts”, but with that in place, I could use the Account Manager to authenticate an access token as well. There are a several different implementation methods that can get you to the same experience, but in the end, they all drive the same use case.
KG: Along the same theme of sharing data or information across applications, there’s also the concepts of content providers and AIDL integrations. I know that Donn has worked on AIDL integrations, so you two would probably understand this better, but will you explain when I would use a content provider and when I would just use an AIDL? Why not just use one? Why do I need multiple ways of doing the same thing? Obviously, it’s not the same thing, but if you can call out the differences, it’ll be helpful for our listeners.
TS: The content provider is usually styled by a URI. It’s more loosely typed data that you might want to consume with a cursor. There are use cases where that might be valid. Maybe you want to look at specific types of data that are coming back in a list, which you can iterate on a cursor. There are methods in content providers to stream files, so you can use them to specifically access a file.
A great example of a content provider if from when I was working at Evernote. We wanted to implement ACTION_EDIT and ACTION_VIEW(intent) in Android to have an attachment to an Evernote note be utilized by a third-party app which could specifically handle the MIME type of that attachment. Let’s say that you had a note which had an Microsoft Word .doc attached to it. When the user engages with that, we launch the ACTION_EDIT(intent) with that MIME type specified. Now any application on the device can say, “Hey, I’m available to handle that sort of thing.” Then the user picks one, and we construct the intent. We set the data to the URI of that attachment, which will be provided through the content provider. We’re going to be streaming that file, so we need to grant read or write access to it temporarily as well (depending on if they called ACTION_VIEW or ACTION_EDIT, respectively).
Where it can get a little hairy is that there’s a lot of volatility in an integration like that on the Android platform. Third-party apps would say they could handle that MIME type. When you sent the URI over there, sometimes they would edit it directly, call setResult(), and finish(). That’s a straightforward example. You gave them a URI, they edited the URI, and you got an activity result—a RESULT_OK, a RESULT_CANCELED, or whatever the valid response was.
But we started running into other weird use cases as well. Some apps would copy the URI, write it into a different file as the user edited it, and then return the new data URI. Now you have the original data URI that you provided them and the new data URI that you are consuming from them, which is likely being streamed from their content provider. That was a use case where they did call setResult().
But there was another use case where apps would edit the URI and then call finish() without calling setResult(). You wouldn’t get a valid RESULT_OK, but the URI was changed, since the user engaged with it. We had to set up a weird fallback mechanism. When the user specified interest in handling a file, we first copied the file. We then handed out the URI for the temporary copy that was a representation of it. The third-party app then edited the file. When it returned it, we checked first: was the MD5 of the URI that we sent over the same as the one for the URI from the onResume()? If they setResult() and gave us a URI, is it the same URI, or has it changed? If there was no change at all, that’s another use case. We started prompting the user, based on this data set: “Hey, we got a result back from the app. Do you want to save it?”
Different apps behave different ways. Those all consume from streaming a file over the content provider, which is one specific use case. To take that a step outside of the realm of streaming data, files, or big data sets that you may want to iterate on with a cursor for a list, the AIDL is more statically typed. It explicitly binds a service between their app and your app. It requires them to have a generated code set based on a common defined interface. This allows you to transfer objects directly between them. That’s a little more useful for statically typed content, where the content provider has a looser mechanism for defining the data and handling it, based on the URI.
You could manipulate both of them to handle very similar use cases, so it just depends on what you’re thinking about from a maintainability perspective.
KG: The way that I think about content providers is that they are more of a placeholder, whereas AIDL Integration is more of a service which allows you to be a little more flexible in the kinds of things that you can potentially do.
TS: Definitely. You can send any type of parseable object across an AIDL directly, but that requires that both the consumer and the provider have the same method definitions and class definitions. So if you have an app (maybe your app) that provides a service which has updated, but the third-party app consuming the JAR that you provide is not updated, then you could have weird versioning issues in the AIDL. You could run into similar issues with the content provider, but those are more loosely typed, since you’re specifically assembling a URI when you’re parsing that out.
DF: The thing is, if you are using AIDL, there is something to be aware of—a weird gotcha that you’ll never know about until you hit it: the TransactionTooLargeException, meaning that the binder transaction failed because the objects that you’re trying to send across are just too big to handle. The binder transaction buffer has a limited, fixed size of 1 MB. That’s it. It’s in the Android documentation. But that’s one of the ones that I ran into. We were sending a humongous amount of data over an AIDL service—and one day, it suddenly started breaking, because we were sending more data back than the binder could handle.
TS: Absolutely. That’s a great use case for using an AIDL with a content provider and streaming that out directly.
KG: Wow, so my 10 MB JSONs are a no go with AIDL integration.
DF: That’s not going to work.
DF: This is good information, but there are more ways that we can share data. You touched on a couple of these. That’s going to be through intents, and I even mentioned deep links. Have you used deep links at all to share data? If so, what did you do? If not, do you use deep links at all?
TS: Actually, in working on the Uber app, I’ve been a little more focused on deep links specifically. The Uber SDK generates a deep link to start the user’s trip, to apply promotions, or for a handful of other use cases that are generated through non-published developer means. For example, suppose a marketing email is sent out to re-engage folks. That will have a deep link that fires back into the app. More often than not, that’s going to be a universal deep link, where it’s potentially just a standard URI with query parameters that you’re parsing out, reading, and trying to do stuff with. You could do intent APIs over Chrome until version 24, which allowed for explicitly defined intent APIs. However, as soon as you’re thinking about cross-platform (iOS and Android), using a standard native scheme in your deep links or using universal deep links will serve you much better, in my opinion.
DF: What is a universal deep link?
TS: A universal deep link is an HTTP URL that has a backing server which understands what type of device is connecting to it. It can redirect appropriately to either the Play Store, the App Store, or the application, such that it can be consumed. You can get into some interesting complexity, like deferred deep linking, where you want to fire over a referrer ID to the Play Store. The Play Store then installs the application on behalf of the user. It then emits that referrer ID (in the install vendor BroadcastReceiver) to your application. You would then catch that, read out that data, see the original deep link that the user was trying to engage with, and just continue the flow for that user.
DF: That’s just a great user experience.
TS:. Absolutely. They click a link, which installs the app, and they’re suddenly on the specific page that they were trying to link into, or it’s starting up a ride for them, or whatever use case they had. That’s a fantastic experience.
KG: I remember that when I worked at Wedding Party, this was exactly the kind of thing we wanted. Essentially, if there was a marketing email that went out, we wanted our users to be able to click a button, go to the Play Store or the App Store, and download the app. After the app was downloaded, since we already had some of that information via the intent, we wanted to be able to repopulate the information. It makes the user experience so much nicer.
The funny thing is that this can actually be done (and there are services that apparently do this) by essentially finger printing that call. It’s actually pretty fuzzy. In some ways, they try to see what the last call that was made was. It has to be made within that time frame, with certain attributes matching up (the same device, model, and version). They actually do a lot of fuzzy logic to come up with that solution.
TS: They definitely do. You can use a service like Tune that does the fuzzy matching, but you can define that pretty easily yourself as well (at least on Android), because if you just had a URL encoded string in the referrer ID, you could pass the specific deep link that you cared about and pull that out yourself, without ever having to have any server integration.
KG: That’s pretty cool! On that happy note, thank you so much, Ty. Some of this information is mindblowing. It’s a completely different side or aspect to what we’re typically used to. This is great information.
DF: Yeah, this has been great.
TS: Of course! It’s a fun field to work in, and it’s a very interesting subset of overall Android development.
KG: If folks want to know more about this and want to reach out to you, what’s the best way to do that?
TS: Follow me on Twitter at @TSmith. I’m pretty active on there, and I’m happy to take messages directly. My website is TySmith.me, where I have some information for further contact. Feel free to reach out to me there. If you want to learn more about developer platform, and potentially work in that space, my team is hiring as well.
KG: Donn, if folks want to reach out to you about your adventures with AIDL Integrations and other stuff, what’s the best way to do that?
DF: Test and fastest way is to hit me on Twitter @donnfelker. What about you, Kaushik? How can folks get ahold of you?
KG: @KaushikGopal on Twitter. Twitter is the way to go these days. It’s definitely the fastest way to reach out to me.
Alright, thanks so much for listening! We’ll catch you in the next episode.