Slide 1

Slide 1 text

@francoisblavoet @sarrouna23 And then my phone became smarter

Slide 2

Slide 2 text

@francoisblavoet @sarrouna23

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

Enter : The Awareness API

Slide 8

Slide 8 text

• 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

Slide 9

Slide 9 text

Several types of fences : • Location • Detected Activity • Beacon • Time • Headphone Fence API

Slide 10

Slide 10 text

Let’s dive in the code !

Slide 11

Slide 11 text


 
 Awareness API

Slide 12

Slide 12 text

@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

Slide 13

Slide 13 text

@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

Slide 14

Slide 14 text

@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

Slide 15

Slide 15 text

Awareness.FenceApi.updateFences(googleApiClient,
 fenceUpdateRequest); Fence API

Slide 16

Slide 16 text

FenceUpdateRequest.Builder builder = new FenceUpdateRequest.Builder();
 builder.addFence("fencekey",
 awarenessFence,
 pendingIntent); builder.build(); Fence API

Slide 17

Slide 17 text

FenceUpdateRequest.Builder builder = new FenceUpdateRequest.Builder();
 builder.addFence("fencekey",
 awarenessFence,
 pendingIntent); builder.build(); Fence API

Slide 18

Slide 18 text

FenceUpdateRequest.Builder builder = new FenceUpdateRequest.Builder();
 builder.addFence("fencekey",
 awarenessFence,
 pendingIntent); builder.build(); Fence API

Slide 19

Slide 19 text

FenceUpdateRequest.Builder builder = new FenceUpdateRequest.Builder();
 builder.addFence("fencekey",
 awarenessFence,
 pendingIntent); builder.build(); Fence API

Slide 20

Slide 20 text

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 ?

Slide 21

Slide 21 text

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 ?

Slide 22

Slide 22 text

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 ?

Slide 23

Slide 23 text

Fence API - Let’s put everything together FenceUpdateRequest.Builder builder = new FenceUpdateRequest.Builder();
 
 builder.addFence("walking", awarenessFence,
 pendingIntent);
 
 FenceUpdateRequest updateRequest = builder.build();
 


Slide 24

Slide 24 text

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();
 


Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

@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

Slide 27

Slide 27 text

@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

Slide 28

Slide 28 text

@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

Slide 29

Slide 29 text

@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

Slide 30

Slide 30 text

Fence API - Wait, there is more ! FENCE AND OR FENCE FENCE NOT

Slide 31

Slide 31 text

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 !

Slide 32

Slide 32 text

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 !

Slide 33

Slide 33 text

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);


Slide 34

Slide 34 text

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 !

Slide 35

Slide 35 text

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)
 


Slide 36

Slide 36 text

Snapshot API

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

Several types of options : Location Detected Activity Beacon Time Headphone PlaceLikeliHood Weather Snapshot API : The possibilities

Slide 39

Slide 39 text


 Awareness.SnapshotApi.getWeather(mGoogleApiClient)
 .setResultCallback(new ResultCallback() {
 @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

Slide 40

Slide 40 text


 Awareness.SnapshotApi.getWeather(mGoogleApiClient)
 .setResultCallback(new ResultCallback() {
 @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

Slide 41

Slide 41 text


 Awareness.SnapshotApi.getWeather(mGoogleApiClient)
 .setResultCallback(new ResultCallback() {
 @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

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

Magic Context

Slide 44

Slide 44 text

Magic Context

Slide 45

Slide 45 text

Magic Context

Slide 46

Slide 46 text

Challenge V2 : Architecture • Kotlin • Databinding • Dagger 2

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

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

Slide 49

Slide 49 text

Challenge : Working with immature Api • Some dysfunctions • Random crashes : SecurityExceptions

Slide 50

Slide 50 text

Magic Context - next iterations • More music services • More defined locations • More fence types • More actions : autoplay, fence modification or deletion, …

Slide 51

Slide 51 text

Magic Context - show me the code https://github.com/LostInContext/LostContext-App

Slide 52

Slide 52 text

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.

Slide 53

Slide 53 text

No content

Slide 54

Slide 54 text

Questions ? fb@deezer.com twitter.com/francoisblavoet strabelsi@deezer.com twitter.com/sarrouna23

Slide 55

Slide 55 text

Thanks Liam Spradlin Bhavik Singh Albert Reynaud Raj Ajrawat Maurice Chu Axelle Migniot Nicolas Le Breton