Upgrade to Pro — share decks privately, control downloads, hide ads and more …

And then my phone became smarter - A journey into the Awareness API - MobileEra 2016

And then my phone became smarter - A journey into the Awareness API - MobileEra 2016

Let’s take a glance at the Awareness API and apply it to music recommendations.
The geeks have won ! We are all carrying tiny computers with lots of sensors.
With them, we can do more than display content, we can also make these devices aware of the world around us, making them smarter.
One way to do this is to leverage the Google Awareness API in order to have rich features with minimal input from the user.
It can trigger events when some conditions are put together : when you are close to a certain area, when you plug in headphones, when it is cold or sunny, etc
It can also be used to directly poll the sensors and get some information about the world around you.
Using all these capacities to facilitate your life, your device will know what to do and when to do it, with or without your input (as configured by the user). In this talk we will show you how to improve your music experience and take it to the next stage.

Here is the repo of the app presented : https://github.com/LostInContext/LostContext-App

Syrine Trabelsi

November 03, 2016
Tweet

More Decks by Syrine Trabelsi

Other Decks in Programming

Transcript

  1. Smartphones are very personal devices People have different ways to

    use them Your phone has a wealth of sensors Use them to make it smarter
  2. 50 The number of times people check their phone everyday

    Source: The Consumer Barometer Survey 2014/15
  3. 50 The number of times people check their phone everyday

    31% of people use their phone 
 to listen to music everyday Source: The Consumer Barometer Survey 2014/15
  4. • Interacting with the sensors • Coordinate the detection together

    • Use as little battery as possible Fence : An abstraction for something you want to detect Lots of code to do it manually but comes for free with awareness Enter : The Awareness API
  5. Several types of fences : • Location • Detected Activity

    • Beacon • Time • Headphone Fence API
  6. @Override protected void onStart() {
 super.onStart();
 
 googleApiClient = new

    GoogleApiClient.Builder(this)
 .addApi(Awareness.API)
 .build();
 
 googleApiClient.registerConnectionCallbacks(connectionCallbacks);
 googleApiClient.registerConnectionFailedListener(connectionFailedListener);
 googleApiClient.connect();
 
 } @Override protected void onStop() {
 googleApiClient.disconnect();
 super.onStop();
 } Awareness API
  7. @Override protected void onStart() {
 super.onStart();
 
 googleApiClient = new

    GoogleApiClient.Builder(this)
 .addApi(Awareness.API)
 .build();
 
 googleApiClient.registerConnectionCallbacks(connectionCallbacks);
 googleApiClient.registerConnectionFailedListener(connectionFailedListener);
 googleApiClient.connect();
 
 } @Override protected void onStop() {
 googleApiClient.disconnect();
 super.onStop();
 } Awareness API
  8. @Override protected void onStart() {
 super.onStart();
 
 googleApiClient = new

    GoogleApiClient.Builder(this)
 .addApi(Awareness.API)
 .build();
 
 googleApiClient.registerConnectionCallbacks(connectionCallbacks);
 googleApiClient.registerConnectionFailedListener(connectionFailedListener);
 googleApiClient.connect();
 
 } @Override protected void onStop() {
 googleApiClient.disconnect();
 super.onStop();
 } Awareness API
  9. LocationFence.in(latitude, longitude, radius, dwellTimeMillis); LocationFence.entering(latitude, longitude, radius);
 LocationFence.exiting(latitude, longitude, radius);

    DetectedActivityFence.during(DetectedActivityFence.WALKING); DetectedActivityFence.starting(DetectedActivityFence.WALKING); DetectedActivityFence.stopping(DetectedActivityFence.WALKING);
 Fence API - How to build ?
  10. LocationFence.in(latitude, longitude, radius, dwellTimeMillis); LocationFence.entering(latitude, longitude, radius);
 LocationFence.exiting(latitude, longitude, radius);

    DetectedActivityFence.during(DetectedActivityFence.WALKING); DetectedActivityFence.starting(DetectedActivityFence.WALKING); DetectedActivityFence.stopping(DetectedActivityFence.WALKING);
 Fence API - How to build ?
  11. LocationFence.in(latitude, longitude, radius, dwellTimeMillis); LocationFence.entering(latitude, longitude, radius);
 LocationFence.exiting(latitude, longitude, radius);

    DetectedActivityFence.during(DetectedActivityFence.WALKING); DetectedActivityFence.starting(DetectedActivityFence.WALKING); DetectedActivityFence.stopping(DetectedActivityFence.WALKING);
 DetectedActivityFence.during(DetectedActivityFence.WALKING, DetectedActivityFence.ON_BICYCLE); Fence API - How to build ?
  12. Fence API - Let’s put everything together FenceUpdateRequest.Builder builder =

    new FenceUpdateRequest.Builder();
 
 builder.addFence("walking", awarenessFence,
 pendingIntent);
 
 FenceUpdateRequest updateRequest = builder.build();
 

  13. Fence API - Let’s put everything together FenceUpdateRequest.Builder builder =

    new FenceUpdateRequest.Builder();
 
 builder.addFence("walking", DetectedActivityFence.during(DetectedActivityFence.WALKING),
 pendingIntent);
 
 FenceUpdateRequest updateRequest = builder.build();
 

  14. FenceUpdateRequest.Builder builder = new FenceUpdateRequest.Builder();
 
 builder.addFence("walking",
 DetectedActivityFence.during(DetectedActivityFence.WALKING),
 pendingIntent);
 


    FenceUpdateRequest updateRequest = builder.build();
 
 
 Awareness.FenceApi.updateFences(googleApiClient, updateRequest); Fence API - Let’s put everything together
  15. @Override protected void onHandleIntent(Intent intent) {
 FenceState fenceState = FenceState.extract(intent);


    
 if (TextUtils.equals(fenceState.getFenceKey(), "myFence")) {
 switch (fenceState.getCurrentState()) {
 case FenceState.TRUE:
 Log.i(TAG, "the fence conditions are verified");
 break;
 case FenceState.FALSE:
 Log.i(TAG, "the fence conditions are NOT verified");
 break;
 
 case FenceState.UNKNOWN:
 Log.i(TAG, "I have no idea ¯\_(ϑ)_/¯ ”);
 }
 }
 } Fence API - React to the fence
  16. @Override protected void onHandleIntent(Intent intent) {
 FenceState fenceState = FenceState.extract(intent);


    
 if (TextUtils.equals(fenceState.getFenceKey(), "myFence")) {
 switch (fenceState.getCurrentState()) {
 case FenceState.TRUE:
 Log.i(TAG, "the fence conditions are verified");
 break;
 case FenceState.FALSE:
 Log.i(TAG, "the fence conditions are NOT verified");
 break;
 
 case FenceState.UNKNOWN:
 Log.i(TAG, "I have no idea ¯\_(ϑ)_/¯ ”);
 }
 }
 } Fence API - React to the fence
  17. @Override protected void onHandleIntent(Intent intent) {
 FenceState fenceState = FenceState.extract(intent);


    
 if (TextUtils.equals(fenceState.getFenceKey(), "myFence")) {
 switch (fenceState.getCurrentState()) {
 case FenceState.TRUE:
 Log.i(TAG, "the fence conditions are verified");
 break;
 case FenceState.FALSE:
 Log.i(TAG, "the fence conditions are NOT verified");
 break;
 
 case FenceState.UNKNOWN:
 Log.i(TAG, "I have no idea ¯\_(ϑ)_/¯ ”);
 }
 }
 } Fence API - React to the fence
  18. @Override protected void onHandleIntent(Intent intent) {
 FenceState fenceState = FenceState.extract(intent);


    
 if (TextUtils.equals(fenceState.getFenceKey(), "myFence")) {
 switch (fenceState.getCurrentState()) {
 case FenceState.TRUE:
 Log.i(TAG, "the fence conditions are verified");
 break;
 case FenceState.FALSE:
 Log.i(TAG, "the fence conditions are NOT verified");
 break;
 
 case FenceState.UNKNOWN:
 Log.i(TAG, "I have no idea ¯\_(ϑ)_/¯ ”);
 }
 }
 } Fence API - React to the fence
  19. AwarenessFence pluggingInWhileOnFoot =
 AwarenessFence.and(DetectedActivityFence.during(ON_FOOT),
 HeadphoneFence.pluggingIn()); 
 
 AwarenessFence inThePark =

    LocationFence.in(latitude, longitude, radius, dwellTimeMillis);
 
 AwarenessFence complex = AwarenessFence.or(pluggingInWhileMoving, inThePark);
 
 AwarenessFence notInThePark = AwarenessFence.not(inThePark);
 Fence API - Wait, there is more !
  20. AwarenessFence pluggingInWhileOnFoot =
 AwarenessFence.and(DetectedActivityFence.during(ON_FOOT),
 HeadphoneFence.pluggingIn()); 
 
 AwarenessFence inThePark =

    LocationFence.in(latitude, longitude, radius, dwellTimeMillis);
 
 AwarenessFence complex = AwarenessFence.or(pluggingInWhileMoving, inThePark);
 
 AwarenessFence notInThePark = AwarenessFence.not(inThePark);
 Fence API - Wait, there is more !
  21. Fence API - Wait, there is more ! AwarenessFence pluggingInWhileOnFoot

    =
 AwarenessFence.and(DetectedActivityFence.during(ON_FOOT),
 HeadphoneFence.pluggingIn()); 
 
 AwarenessFence inThePark = LocationFence.in(latitude, longitude, radius, dwellTimeMillis);
 
 AwarenessFence complex = AwarenessFence.or(pluggingInWhileMoving, inThePark);
 
 AwarenessFence notInThePark = AwarenessFence.not(inThePark);

  22. AwarenessFence pluggingInWhileOnFoot =
 AwarenessFence.and(DetectedActivityFence.during(ON_FOOT),
 HeadphoneFence.pluggingIn()); 
 
 AwarenessFence inThePark =

    LocationFence.in(latitude, longitude, radius, dwellTimeMillis);
 
 AwarenessFence complex = AwarenessFence.or(pluggingInWhileMoving, inThePark);
 
 AwarenessFence notInThePark = AwarenessFence.not(inThePark);
 Fence API - Wait, there is more !
  23. Fence API - the final bits You can remove fences

    : 
 FenceUpdateRequest.Builder builder = new FenceUpdateRequest.Builder();
 builder.removeFence(“fenceKey”); And also query them directly : FenceQueryRequest queryAll = FenceQueryRequest.all();
 FenceQueryRequest querySome = FenceQueryRequest.forFences("headphone", "walking");
 
 Awareness.FenceApi.queryFences(googleApiClient, queryAll)
 

  24. Several types of options : Location Detected Activity Beacon Time

    Headphone Snapshot API : The possibilities
  25. Several types of options : Location Detected Activity Beacon Time

    Headphone PlaceLikeliHood Weather Snapshot API : The possibilities
  26. 
 Awareness.SnapshotApi.getWeather(mGoogleApiClient)
 .setResultCallback(new ResultCallback<WeatherResult>() {
 @Override
 public void onResult(@NonNull WeatherResult

    weatherResult) {
 if (!weatherResult.getStatus().isSuccess()) {
 Log.e(TAG, "Could not get weather.");
 return;
 }
 Weather weather = weatherResult.getWeather();
 Log.i(TAG, "Weather: " + weather);
 }
 }); Snapshot API : Sample code
  27. 
 Awareness.SnapshotApi.getWeather(mGoogleApiClient)
 .setResultCallback(new ResultCallback<WeatherResult>() {
 @Override
 public void onResult(@NonNull WeatherResult

    weatherResult) {
 if (!weatherResult.getStatus().isSuccess()) {
 Log.e(TAG, "Could not get weather.");
 return;
 }
 Weather weather = weatherResult.getWeather();
 Log.i(TAG, "Weather: " + weather);
 }
 }); Snapshot API : Sample code
  28. 
 Awareness.SnapshotApi.getWeather(mGoogleApiClient)
 .setResultCallback(new ResultCallback<WeatherResult>() {
 @Override
 public void onResult(@NonNull WeatherResult

    weatherResult) {
 if (!weatherResult.getStatus().isSuccess()) {
 Log.e(TAG, "Could not get weather.");
 return;
 }
 Weather weather = weatherResult.getWeather();
 Log.i(TAG, "Weather: " + weather);
 }
 }); Snapshot API : Sample code
  29. Awareness API : music streaming • Intuitive and easy to

    use • No restriction on the choice of the music application • Use Awareness API and available public APIs of music streaming services
  30. Challenge V2 : UI Design • Awareness Api offers endless

    possibilities • We first wanted to expose everything to the user • Designing a usable UI was a big challenge • But … sometimes less is better
  31. Challenge : Side project • It all started as a

    board in Trello • It was sometimes difficult to work on both deezer and LostContext (some of us do have a life) • At the end Awareness Api was integrated to deezer
  32. Magic Context - next iterations • More music services •

    More defined locations • More fence types • More actions : autoplay, fence modification or deletion, …
  33. Awareness Api : Privacy • The awareness api gives you

    access to very private information. • Make clear to the user what data you’re using and how you’re using it. • If you’re storing data to the device make it clear to the user and make it deletable.