[MUSIC PLAYING]
ADAM KOCH: Hi.
My name's Adam Koch from the Android Developer Relations
team at Google.
Today, I wanted to talk to you about the new SMS
APIs in Android 4.4 KitKat.
So let's jump right in.
Starting with Android 4.4 KitKat,
there's the new concept of a default SMS application.
Only the default SMS application can write directly
to the system ContentProvider.
Other apps that try and write will fail silently.
Of course, any app can still read from the system
ContentProvider as long as they have the correct permission.
So you might be thinking, why do we
need this new concept of a default SMS app?
In previous versions of Android, you
could already assign some of the SMS intents to any application.
But the difference is, that app had no unique privileges
over any other app on the system.
With the new default SMS app selection,
that app will now have additional privileges
and be guaranteed to get every single message.
Another app cannot abort the delivery of the SMS
or interrupt that flow.
This helps to increase reliability.
Additionally, no other app can delete or alter messages
out from underneath the default app, which
helps to decrease complexity within the default SMS app.
This, combined with the fact that some
of the previously private APIs in earlier versions of Android
are now public, means that third-party SMS apps
are supported first-class citizens of the Android system.
So let's talk about implementation.
To be eligible as the default SMS app,
you must support some specific capabilities.
In your AndroidManifest, you have
to define two receivers to handle
the receiving of SMSes and MMSes.
You can see here that the actions are
SMS_DELIVER and WAP_PUSH_DELIVER You'll also
note that these receivers require
an additional permission on the actual receiver.
Additionally, you have to define an activity, a UI that
can handle creation of new SMSes.
So here we've got a ComposeSmsActivity.
This might be triggered, say, from the system people app
when you go and create a new SMS to a particular contact.
And lastly, you also need a service
that can also respond to creating and sending new SMSes.
This is used by the system when a phone call comes in.
And if you can't take it, you can quickly
swipe up to send an SMS in the background
to the person saying the reason why you can't actually
take that call.
Once you've defined all of these things,
you'll be eligible to show up in a new system dialogue that
lets you choose the default SMS app.
Additionally, you can also display a dialogue
that lets the user switch to your application as the default
SMS app.
And I'll show you how to do that shortly, after this.
One thing worth noting is that you still
need to declare the same application-wide permissions
that you always did to access SMS functionality,
things like WRITE_SMS, READ-SMS, SEND_SMS, RECEIVE_SMS,
and RECEIVE_MMS.
In some of the previous slides, you
will have seen that two receivers we defined
have two new KitKat delivery actions, SMS_DELIVER_ACTION
and WAP_PUSH_DELIVER_ACTION.
These only get delivered to the default SMS application.
But in previous versions of Android,
there was actually a private API that
allowed you to also receive these SMSes.
These actions were SMS_RECEIVED_ACTION
and WAP_PUSH_RECEIVED_ACTION.
And these still exist in KitKat and are actually now public.
And applications can still listen to them
as they did before.
To distinguish the difference between these two,
think of SMS_RECEIVED_ACTION as the system has received an SMS.
Whereas the SMS_DELIVER_ACTION says
the system is delivering your app and SMS
because you are the default SMS app.
So let's talk about some message receiver best practices.
For apps that are not looking to become the default,
they should just carry on as normal using
the "message received" actions.
These are the ones that, as I mentioned,
were private before KitKat, but are now public in KitKat.
For apps that do want to become the default,
they should probably be listening
to both the "message received" and then new SMS delivered
ones.
So that means that when they're running on KitKat,
they should really disabled the one
that's not being used, the "message received" actions.
To do that, they should use the PackageManager.setComponentEnabledSetting
method.
That way, they can disable these,
and they won't be using unnecessary resources
and be triggered as new SMSes come in.
Another approach to handling them
is to use Boolean resource files to automatically enable
and disable the receivers based on platform version.
Really, the difference between these two
is that setComponentEnabledSetting
is a little more flexible.
You can choose within code when you want to change it.
Whereas the Boolean resource is simpler, but less flexible.
So let's quickly look at how you would implement the Boolean
method.
Here, you see we've created two Boolean XML
files in our resource directories,
one under the default res/values directory, with two values,
hasKitKat and preKitKat.
We've additionally created another one
in values-v19, which means any devices running on Android 4.4
KitKat or above will automatically
load this resource file instead.
And you can see we've set hasKitKat to true
and preKitKat to false.
Then, in our AndroidManifest file,
in our receiver declarations, we assign this Boolean
to the Android-enabled attribute.
This has the effect that on certain versions of Android,
one will be enabled and the other disabled,
and the reverse on the newer platforms.
If you haven't seen this technique before,
follow the link here on the right or the QR code
to get more information.
Another new API in KitKat is the ability
to check which is the default SMS application, using
the Telephony.Sms.getDefaultSmsPackage
method.
Here you can see, we're checking to see
if we're running on KitKat or above,
and then we're going to use that method
to work out if we're currently the default SMS application.
You can then call this in your onResume
of your key activities, hide and show certain layouts as
appropriate, and also enable and disable
certain functionality as appropriate.
For example, you may not want to allow sending SMSes
if you're not currently the default SMS application.
You can also open a system dialogue
to ask the user if they would like to switch the default SMS
application to be yours.
To do this, you use a new intent action, ACTION_CHANGE_DEFAULT,
along with an extra EXTRA_PACKAGE_NAME
to pass your package name to another activity, which
opens a system dialogue that looks something like this,
that I showed you before.
As soon as the user clicks Yes, your application
will now be the default.
Your previous activity will get a call to unresume,
and it can adjust its layouts and functionality as needed.
Lastly, some additional notes.
Messages can still be sent by any application using
the existing SmsManager APIs, assuming, of course,
they hold the send SMS permission.
However, for apps other than the selected default,
the system writes all outgoing SMS messages
to the system provider automatically.
It won't, however, write outgoing MMS.
This is particularly important for auxiliary SMS apps that
may work alongside another app which is the default.
One thing worth noting, though, these auxiliary apps
will no longer be able to write to the system content
provider themselves.
So they won't be able to do things
like deleting messages or marking messages
as read or unread.
On the flip side, the default SMS application
is responsible for writing its outgoing messages to the system
provider.
Lastly, SMS backup apps will need to temporarily become
the default when restoring messages
so that they can write correctly to the system content provider.
For additional reference to the new SMS APIs in KitKat,
see the Android Developer blog, where
we have additional information posted up.
You can follow this link or this QR code
on the right side of the screen.
We'll actually be posting some sample code up and linking
to it in the description of this video
and also on the blog post.
Thanks for tuning in to this DevByte.