When you want to gather information about a user's current context, you can use the snapshot functionality of the Awareness API. This API will gather information depending on the type of API call made, and will cache this information for quick access across various apps.
Headphones
One of the new additions to Play Services through the Awareness API is the ability to detect a device's headphone state (plugged in or unplugged). This can be done by calling getHeadphoneState() on the Awareness API and reading the HeadphoneState from the HeadphoneStateResult.
- private void detectHeadphones() {
- Awareness.SnapshotApi.getHeadphoneState(mGoogleApiClient)
- .setResultCallback(new ResultCallback<HeadphoneStateResult>() {
- @Override
- public void onResult(@NonNull HeadphoneStateResult headphoneStateResult) {
- HeadphoneState headphoneState = headphoneStateResult.getHeadphoneState();
- if (headphoneState.getState() == HeadphoneState.PLUGGED_IN) {
- Log.e("Tuts+", "Headphones are plugged in.");
- } else {
- Log.e("Tuts+", "Headphones are NOT plugged in.");
- }
- }
- });
- }
Location
Although previously available as a component in Google Play Services, the location feature of the Awareness API has been optimized for efficiency and battery usage. Rather than using the traditional Location API and receiving a location at specified intervals, you can request a one-time location snapshot like so.
- private void detectLocation() {
- if( !checkLocationPermission() ) {
- return;
- }
- Awareness.SnapshotApi.getLocation(mGoogleApiClient)
- .setResultCallback(new ResultCallback<LocationResult>() {
- @Override
- public void onResult(@NonNull LocationResult locationResult) {
- Location location = locationResult.getLocation();
- Log.e("Tuts+", "Latitude: " + location.getLatitude() + ", Longitude: " + location.getLongitude());
- Log.e("Tuts+", "Provider: " + location.getProvider() + " time: " + location.getTime());
- if( location.hasAccuracy() ) {
- Log.e("Tuts+", "Accuracy: " + location.getAccuracy());
- }
- if( location.hasAltitude() ) {
- Log.e("Tuts+", "Altitude: " + location.getAltitude());
- }
- if( location.hasBearing() ) {
- Log.e("Tuts+", "Bearing: " + location.getBearing());
- }
- if( location.hasSpeed() ) {
- Log.e("Tuts+", "Speed: " + location.getSpeed());
- }
- }
- });
- }
You will want to verify that a specific piece of information exists before using it, as some data may not be available. Running this code should output all available data to the Android system log.
- E/Tuts+: Latitude: 39.9255456, Longitude: -105.02939579999999
- E/Tuts+: Provider: Snapshot time: 1468696704662
- E/Tuts+: Accuracy: 20.0
- E/Tuts+: Altitude: 0.0
- E/Tuts+: Speed: 0.0
While not as robust as the standard Places API, the Awareness API does provide a quick and easy to use way to gather information about places near the user. This API call will return a List of PlaceLikelihood objects that contains a Place and a float representing how likely it is that a user is at that place (hence the object's name).
Each Place object may contain a name, address, phone number, place type, user rating, and other useful information. You can request the nearby places for the user after verifying that the user has the location permission granted.
- private void detectNearbyPlaces() {
- if( !checkLocationPermission() ) {
- return;
- }
- Awareness.SnapshotApi.getPlaces(mGoogleApiClient)
- .setResultCallback(new ResultCallback<PlacesResult>() {
- @Override
- public void onResult(@NonNull PlacesResult placesResult) {
- Place place;
- for( PlaceLikelihood placeLikelihood : placesResult.getPlaceLikelihoods() ) {
- place = placeLikelihood.getPlace();
- Log.e("Tuts+", place.getName().toString() + "\n" + place.getAddress().toString() );
- Log.e("Tuts+", "Rating: " + place.getRating() );
- Log.e("Tuts+", "Likelihood that the user is here: " + placeLikelihood.getLikelihood() * 100 + "%");
- }
- }
- });
- }
- E/Tuts+: North Side Tavern
- 12708 Lowell Blvd, Broomfield, CO 80020, USA
- E/Tuts+: Rating: 4.7
- E/Tuts+: Likelihood that the user is here: 10.0%
- E/Tuts+: Quilt Store
- 12710 Lowell Blvd, Broomfield, CO 80020, USA
- E/Tuts+: Rating: 4.3
- E/Tuts+: Likelihood that the user is here: 10.0%
- E/Tuts+: Absolute Floor Care
- 3508 W 126th Pl, Broomfield, CO 80020, USA
- E/Tuts+: Rating: -1.0
Another of the new additions to Google Play Services through the Awareness API is the ability to get the weather conditions for a user. This feature also requires the location permission for users on Marshmallow and later.
Using this request, you will be able to get the temperature in the user's area in either Fahrenheit or Celsius. You can also find out what the temperature feels like, the dew point (the temperature where water in the air can begin to condense into dew), the humidity percentage, and the weather conditions.
- private void detectWeather() {
- if( !checkLocationPermission() ) {
- return;
- }
- Awareness.SnapshotApi.getWeather(mGoogleApiClient)
- .setResultCallback(new ResultCallback<WeatherResult>() {
- @Override
- public void onResult(@NonNull WeatherResult weatherResult) {
- Weather weather = weatherResult.getWeather();
- Log.e("Tuts+", "Temp: " + weather.getTemperature(Weather.FAHRENHEIT));
- Log.e("Tuts+", "Feels like: " + weather.getFeelsLikeTemperature(Weather.FAHRENHEIT));
- Log.e("Tuts+", "Dew point: " + weather.getDewPoint(Weather.FAHRENHEIT));
- Log.e("Tuts+", "Humidity: " + weather.getHumidity() );
- if( weather.getConditions()[0] == Weather.CONDITION_CLOUDY ) {
- Log.e("Tuts+", "Looks like there's some clouds out there");
- }
- }
- });
- }
- E/Tuts+: Temp: 88.0
- E/Tuts+: Feels like: 88.0
- E/Tuts+: Dew point: 50.0
- E/Tuts+: Humidity: 28
- E/Tuts+: Looks like there's some clouds out there
- int CONDITION_UNKNOWN = 0;
- int CONDITION_CLEAR = 1;
- int CONDITION_CLOUDY = 2;
- int CONDITION_FOGGY = 3;
- int CONDITION_HAZY = 4;
- int CONDITION_ICY = 5;
- int CONDITION_RAINY = 6;
- int CONDITION_SNOWY = 7;
- int CONDITION_STORMY = 8;
- int CONDITION_WINDY = 9;
Your user's activity will play a large part in how they interact with their device, and detecting that activity will allow you to provide a more fluid user experience.
For example, if you have a fitness app, you may want to detect when a user is running so you can start recording a Google Fit session, or you may want to send a notification to your user if you detect that they have been still for too many hours during the day.
Using the getDetectedActivity() call in the Awareness API, you can get a list of probable activities and how long the user has been doing each one.
- private void detectActivity() {
- Awareness.SnapshotApi.getDetectedActivity(mGoogleApiClient)
- .setResultCallback(new ResultCallback<DetectedActivityResult>() {
- @Override
- public void onResult(@NonNull DetectedActivityResult detectedActivityResult) {
- ActivityRecognitionResult result = detectedActivityResult.getActivityRecognitionResult();
- Log.e("Tuts+", "time: " + result.getTime());
- Log.e("Tuts+", "elapsed time: " + result.getElapsedRealtimeMillis());
- Log.e("Tuts+", "Most likely activity: " + result.getMostProbableActivity().toString());
- for( DetectedActivity activity : result.getProbableActivities() ) {
- Log.e("Tuts+", "Activity: " + activity.getType() + " Likelihood: " + activity.getConfidence() );
- }
- }
- });
- }
- E/Tuts+: time: 1468701845962
- E/Tuts+: elapsed time: 15693985
- E/Tuts+: Most likely activity: DetectedActivity [type=STILL, confidence=100]
- E/Tuts+: Activity: 3 Likelihood: 100
- int IN_VEHICLE = 0;
- int ON_BICYCLE = 1;
- int ON_FOOT = 2;
- int STILL = 3;
- int UNKNOWN = 4;
- int TILTING = 5;
- int WALKING = 7;
- int RUNNING = 8;
The final type of snapshot—and most difficult to set up because it requires a real-world component—involves BLE (Bluetooth Low Energy) beacons. While the Nearby API is beyond the scope of this tutorial, you can initialize beacons for your own Google Services project using Google's Beacon Tools app.
![]() |
In the above screenshot, you can see one item under Attachments. The namespace for this attachment is reflected-disk-355 (this tutorial's example project's namespace is tutsplusawareness) and the type is nearby. You will need this information for your own beacons in order to detect attachments with the Awareness API.
When you have beacons configured, you can return to your code. You will need to create a List of BeaconState.TypeFilter objects so that your app can filter out beacons and attachments that do not relate to your application.
- private static final List BEACON_TYPE_FILTERS = Arrays.asList(
- BeaconState.TypeFilter.with(
- //replace these with your beacon's values
- "namespace",
- "type") );
- private void detectBeacons() {
- if( !checkLocationPermission() ) {
- return;
- }
- Awareness.SnapshotApi.getBeaconState(mGoogleApiClient, BEACON_TYPE_FILTERS)
- .setResultCallback(new ResultCallback<BeaconStateResult>() {
- @Override
- public void onResult(@NonNull BeaconStateResult beaconStateResult) {
- if (!beaconStateResult.getStatus().isSuccess()) {
- Log.e("Test", "Could not get beacon state.");
- return;
- }
- BeaconState beaconState = beaconStateResult.getBeaconState();
- if( beaconState == null ) {
- Log.e("Tuts+", "beacon state is null");
- } else {
- for(BeaconState.BeaconInfo info : beaconState.getBeaconInfo()) {
- Log.e("Tuts+", new String(info.getContent()));
- }
- }
- }
- });
- }
- E/Tuts+: Oh hi tuts+
- E/Tuts+: Portable Beacon info
While the Snapshot API can grab information about the user's context at a particular time, the Fences API listens for specific conditions to be met before allowing an action to occur. The Fences API is optimized for efficient battery and data usage, so as to be courteous to your users.
There are five types of conditions that you can check for when creating fences:
- device conditions, such as user having headphones unplugged or plugged in
- location, similar to a standard geofence
- the presence of specific BLE beacons
- user activity, such as running or driving
- time
Create a BroadcastReceiver
Before you create your fence, you will need to have a key value representing each fence that your app will listen for. To finish off this tutorial, you will build a fence that detects when a user is sitting at a set location, such as their home.
- private final static String KEY_SITTING_AT_HOME = "sitting_at_home";
- public class FenceBroadcastReceiver extends BroadcastReceiver {
- @Override
- public void onReceive(Context context, Intent intent) {
- if(TextUtils.equals(ACTION_FENCE, intent.getAction())) {
- FenceState fenceState = FenceState.extract(intent);
- if( TextUtils.equals(KEY_SITTING_AT_HOME, fenceState.getFenceKey() ) ) {
- if( fenceState.getCurrentState() == FenceState.TRUE ) {
- Log.e("Tuts+", "You've been sitting at home for too long");
- }
- }
- }
- }
- }
Now that you have a receiver created to listen for user events, it's time to create your fences. The first AwarenessFence you will create will listen for when the user is in a STILL state.
- AwarenessFence activityFence = DetectedActivityFence.during(DetectedActivityFence.STILL);
- AwarenessFence homeFence = LocationFence.in(39.92, -105.7, 100000, 1000 );
- AwarenessFence sittingAtHomeFence = AwarenessFence.and(homeFence, activityFence);
- Intent intent = new Intent(ACTION_FENCE);
- PendingIntent fencePendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
- mFenceBroadcastReceiver = new FenceBroadcastReceiver();
- registerReceiver(mFenceBroadcastReceiver, new IntentFilter(ACTION_FENCE));
- FenceUpdateRequest.Builder builder = new FenceUpdateRequest.Builder();
- builder.addFence(KEY_SITTING_AT_HOME, sittingAtHomeFence, fencePendingIntent);
- Awareness.FenceApi.updateFences( mGoogleApiClient, builder.build() );
Conclusion
In this tutorial, you have learned about the Awareness API and how to gather current information about the user's environment. You have also learned how to register a listener for changes in the user's context and act when specific conditions have been met.
With this information, you should be able to expand your own apps and provide users with more amazing experiences based on their current location, activity, and other useful values.
Written by Paul Trebilcox-Ruiz
If you found this post interesting, follow and support us.
Suggest for you:
Android Application Programming - Build 20+ Android Apps
The Complete Android Developer Course: Beginner To Advanced!
Android: From Beginner to Paid Professional
The Complete Android Developer Course - Build 14 Apps
Python For Android Hacking Crash Course: Trojan Perspective
No comments:
Post a Comment