Smartphones accept become one of those essentials that we backpack with us everywhere, so your archetypal adaptable app is action to be acclimated in all kinds of situations and locations.
The added your app knows about this alteration context, the bigger it can acclimate to clothing the user’s current context. Whether your app detects the user’s area and displays this advice on a map; reverse-geocodes the device’s coordinates into a artery address; or uses accouterments sensors to acknowledge to changes in ablaze levels or user proximity, there’s a huge ambit of contextual advice that your app can access, and again use to accommodate a added agreeable user experience.
The Action Acceptance API is a altered way of abacus contextual acquaintance to your application, by absolution you ascertain whether the user is currently walking, running, cycling, travelling in a car, or affianced in a ambit of added concrete activities.
This advice is essential for abounding fettle applications, but alike if you don’t dream of acquisition Google Play’s Health & Fettle category, this is still admired advice that you can use in a huge ambit of applications.
In this article, I’m action to appearance you how to body an appliance that uses the Action Acceptance API to ascertain a ambit of concrete activities, and again affectation this advice to the user.
The Action Acceptance API is an interface that periodically wakes the device, reads bursts of abstracts from the device’s sensors, and again analyzes this abstracts appliance able apparatus acquirements models.
Activity apprehension isn’t an exact science, so rather than abiding a distinct action that the user is definitely performing, the Action Acceptance API allotment a account of activities that the user may be performing, with a aplomb acreage for anniversary activity. This aplomb acreage is consistently an integer, alignment from 0 to 100. If an action is accompanied by a aplomb acreage of 75% or higher, again it’s about safe to accept that the user is assuming this activity, and acclimatize your application’s behaviour appropriately (although it’s not impossible for assorted activities to accept a aerial aplomb percentage, abnormally activities that are carefully related, such as active and walking).
We’re action to affectation this aplomb allotment in our application’s UI, so you’ll be able to see exactly how this acreage updates, in acknowledgment to alteration user activity.
The Action Acceptance API can ascertain the afterward activities:
Google Play’s Health & Fitness chic is arranged with apps committed to barometer and allegory your circadian concrete activities, which makes it a abundant abode to get some afflatus about how you ability use Action Acceptance in your own projects. For example, you could use the Action Acceptance API to actualize an app that motivates the user to get up and amplitude back they’ve been anchored for an continued aeon of time, or an appliance that advance the user’s circadian run and prints their avenue on a map, accessible for them to column to Facebook (because if Facebook isn’t acquainted that you got up aboriginal and went for a run afore work, again did it alike absolutely happen?)
While you could bear the aforementioned functionality afterwards the Action Acceptance API, this would crave the user to acquaint your app whenever they’re about to alpha a accordant activity. You can accommodate a abundant bigger user acquaintance by ecology these activities, and again assuming the adapted action automatically.
Although fettle applications are the accessible choice, there’s lots of means that you can use Action Acceptance in applications that don’t abatement into the Health & Fettle category. For example, your app ability about-face to a “hands-free” approach whenever it detects that the user is cycling; appeal area updates added frequently back the user is walking or running; or affectation the quickest way to ability a destination by alley back the user is travelling in a vehicle.
We’re action to body an appliance that uses the Action Acceptance API to retrieve a account of accessible activities and percentages, and again affectation this advice to the user.
The Action Acceptance API requires Google Play Services. To advice accumulate the cardinal of methods in our action beneath control, I’m alone abacus the area of this library that’s appropriate to bear the Action Acceptance functionality. I’m additionally abacus Gson as a dependency, as we’ll be appliance this library throughout the project:
Next, add the com.google.android.gms.permission.ACTIVITY_RECOGNITION permission to your Manifest:
Let’s get the accessible actuality out of the way and actualize the layouts we’ll be appliance throughout this project:
Open the automatically-generated main_activity.xml file, and add the following:
Next, actualize a detected_activity file:
Open this book and ascertain the blueprint for anniversary account in our abstracts set:
These layouts advertence a few altered resources, so accessible your project’s strings.xml book and ascertain the button’s label, added all the strings we’ll eventually affectation in our ListView:
We additionally charge to ascertain a few dimens.xml values. If your action doesn’t already accommodate a res/values/dimens.xml file, again you’ll charge to actualize one:
Open your dimens.xml book and add the following:
Many applications use the Action Acceptance API to adviser activities in the accomplishments and again accomplish an action whenever a assertive action is detected.
Since abrogation a account active in the accomplishments is a acceptable way to use up adored arrangement resources, the Action Acceptance API delivers its abstracts via an intent, which contains a account of activities the user may be assuming at this authentic time. By creating a PendingIntent that’s alleged whenever your app receives this intent, you can adviser the user’s activities afterwards accepting to actualize a agilely active service. Your app can again abstract the ActivityRecognitionResult from this intent, and catechumen this abstracts into a added convenient string, accessible to affectation in your UI.
Create a new chic (I’m appliance ActivityIntentService) and again apparatus the account that’ll accept these Action Acceptance updates:
Don’t balloon to annals the account in your Manifest:
Next, you charge to adjudge how frequently your app should accept new action acceptance data.
Longer amend intervals will abbreviate the appulse your appliance has on the device’s battery, but if you set these intervals too far afar again it could aftereffect in your appliance assuming accomplishments based on significantly age-old information.
Smaller amend intervals beggarly your appliance can acknowledge to action changes added quickly, but it additionally increases the bulk of array your appliance consumes. And if a user identifies your appliance as actuality a bit of a array hog, again they may adjudge to uninstall it.
Note that the Action Acceptance API will try to abbreviate array use automatically by suspending advertisement if it detects that the accessory has been anchored for an continued aeon of time, on accessories that abutment the Sensor.TYPE_SIGNIFICANT_MOTION hardware.
Your project’s amend breach additionally affects the bulk of abstracts your app has to assignment with. Frequent apprehension contest will accommodate added data, which increases your app’s affairs of accurately anecdotic user activity. If added bottomward the band you ascertain that your app’s action apprehension isn’t as authentic as you’d like, again you may appetite to try abbreviation this amend interval.
Finally, you should be acquainted that assorted factors can baffle with your app’s amend interval, so there’s no agreement that your app will accept every distinct amend at this exact frequency. Your app may accept updates advanced of agenda if the API has acumen to accept the action accompaniment is about to change, for archetype if the accessory has aloof been accessible from a charger. At the added end of the scale, your app ability accept updates afterwards the requested breach if the Action Acceptance API requires added abstracts in adjustment to accomplish a added authentic assessment.
I’m action to ascertain this amend breach (alongside some added functionality) in the MainActivity class:
In this class, we’re action to retrieve the aplomb allotment for anniversary activity, by calling getConfidence() on the DetectedActivity instance. We’ll again abide the detected_activity blueprint with the abstracts retrieved from anniversary DetectedActivity object.
Since anniversary activity’s aplomb allotment will change over time, we charge to abide our blueprint at runtime, appliance an Adapter. This Adapter will retrieve abstracts from the Action Acceptance API, acknowledgment a TextView for anniversary access in the abstracts set, and again admit these TextViews into our ListView.
Create a new class, alleged ActivitiesAdapter, and add the following:
It’s time to put this app to the test! Install your action on an Android accessory and tap the ‘Track Activity’ button to alpha accepting action updates.
Since this abstracts is never action to change while your Android accessory is sat on your desk, now’s the absolute time to get up and go for a airing (even if it is aloof about your house!) Accumulate in apperception that it’s not abnormal to see percentages beyond assorted activities, for archetype the afterward screenshot was taken while I was walking.
Although there’s allegedly a 2-3% adventitious that I’m stationary, running, travelling in a vehicle, on a bicycle, or assuming some alien activity, the accomplished allotment is walking/on foot, so the app has detected the accepted action successfully.
In this tutorial we’ve congenital an appliance that retrieves action acceptance abstracts and displays a anticipation allotment for anniversary activity. However, this API allotment far added abstracts than best applications absolutely need, so back you use Action Acceptance in your own projects you’ll about appetite to clarify this abstracts in some way.
One method, is to retrieve the action that has the accomplished anticipation percentage:
Alternatively, you may appetite your app to acknowledge to specific activities only, for archetype requesting area updates added frequently back the user is walking or running. To accomplish abiding your app doesn’t accomplish this action every distinct time there’s a 1% or college anticipation that the user is on foot, you should specify a minimum allotment that this action charge meet, afore your appliance responds:
In this article, we created an appliance that uses the Action Acceptance API to adviser user activity, and affectation this advice in a ListView. We additionally covered some abeyant means of clarification this data, accessible for you to use in your applications.
What is the Action Acceptance API?
How can I use the Action Acceptance API?
Create your project
Create your user interface
Create your IntentService
Retrieving Action Acceptance updates
Displaying the action data
Testing your app
Using the Action Acceptance API in real-life projects
Wrapping up
- IN_VEHICLE. The accessory is in a vehicle, such as a car or bus. The user may be the one abaft the wheel, or they could be the passenger.
- ON_BICYLE. The accessory is on a bicycle.
- ON_FOOT. The accessory is actuality agitated by addition who is walking or running.
- WALKING. The accessory is actuality agitated by addition who is walking. WALKING is a sub-activity of ON_FOOT.
- RUNNING. The accessory is actuality agitated by addition who is running. RUNNING is a sub-activity of ON_FOOT.
- TILTING. The device’s bend about to force has afflicted significantly. This action is generally detected back the accessory is aerial from a collapsed apparent such as a desk, or back it’s central someone’s pocket, and that actuality has aloof confused from a sitting to a continuing position.
- STILL. The accessory is stationary.
- UNKNOWN. The Action Acceptance API is clumsy to ascertain the accepted activity.
- main_activity. This blueprint contains a button that the user will columnist back they appetite to alpha recording their activity.
- detected_activity. Eventually, we’ll affectation anniversary detected action in a ListView, so this blueprint provides a Appearance bureaucracy that the adapter can use for anniversary abstracts entry.
- Control-click your project’s ‘res/layout’ folder.
- Select ‘New > Blueprint ability file.’
- Name this book ‘detected_activity’ and bang ‘OK.’
- Control-click your ‘res/values’ folder.
- Select ‘New > Ethics ability file.’
- Enter the name ‘dimens’ and again bang ‘OK.’
dependencies { abridge 'com.google.android.gms:play-services-location:11.8.0' abridge 'com.google.code.gson:gson:2.8.1' ... ... ...
Activity Recognition Track Activity %1$d%% On a bicycle On foot Running Still Tilting Unknown activity In a vehicle Walking
20dp 10dp
import java.util.ArrayList; import java.lang.reflect.Type; import android.content.Context; import com.google.gson.Gson; import android.content.Intent; import android.app.IntentService; import android.preference.PreferenceManager; import android.content.res.Resources; import com.google.gson.reflect.TypeToken; import com.google.android.gms.location.ActivityRecognitionResult; import com.google.android.gms.location.DetectedActivity; //Extend IntentService// public chic ActivityIntentService extends IntentService { adequate changeless final Cord TAG = "Activity"; //Call the cool IntentService architect with the name for the artisan thread// accessible ActivityIntentService() { super(TAG); } @Override accessible abandoned onCreate() { super.onCreate(); } //Define an onHandleIntent() method, which will be alleged whenever an action apprehension amend is available// @Override adequate abandoned onHandleIntent(Intent intent) { //Check whether the Absorbed contains action acceptance data// if (ActivityRecognitionResult.hasResult(intent)) { //If abstracts is available, again abstract the ActivityRecognitionResult from the Intent// ActivityRecognitionResult aftereffect = ActivityRecognitionResult.extractResult(intent); //Get an arrangement of DetectedActivity objects// ArrayListSee Also: hack facebook messengerdetectedActivities = (ArrayList) result.getProbableActivities(); PreferenceManager.getDefaultSharedPreferences(this) .edit() .putString(MainActivity.DETECTED_ACTIVITY, detectedActivitiesToJson(detectedActivities)) .apply(); } } //Convert the cipher for the detected action type, into the agnate string// changeless Cord getActivityString(Context context, int detectedActivityType) { Assets assets = context.getResources(); switch(detectedActivityType) { case DetectedActivity.ON_BICYCLE: acknowledgment resources.getString(R.string.bicycle); case DetectedActivity.ON_FOOT: acknowledgment resources.getString(R.string.foot); case DetectedActivity.RUNNING: acknowledgment resources.getString(R.string.running); case DetectedActivity.STILL: acknowledgment resources.getString(R.string.still); case DetectedActivity.TILTING: acknowledgment resources.getString(R.string.tilting); case DetectedActivity.WALKING: acknowledgment resources.getString(R.string.walking); case DetectedActivity.IN_VEHICLE: acknowledgment resources.getString(R.string.vehicle); default: acknowledgment resources.getString(R.string.unknown_activity, detectedActivityType); } } changeless final int[] POSSIBLE_ACTIVITIES = { DetectedActivity.STILL, DetectedActivity.ON_FOOT, DetectedActivity.WALKING, DetectedActivity.RUNNING, DetectedActivity.IN_VEHICLE, DetectedActivity.ON_BICYCLE, DetectedActivity.TILTING, DetectedActivity.UNKNOWN }; changeless Cord detectedActivitiesToJson(ArrayList detectedActivitiesList) { Blazon blazon = new TypeToken >() {}.getType(); acknowledgment new Gson().toJson(detectedActivitiesList, type); } changeless ArrayList detectedActivitiesFromJson(String jsonArray) { Blazon listType = new TypeToken >(){}.getType(); ArrayList detectedActivities = new Gson().fromJson(jsonArray, listType); if (detectedActivities == null) { detectedActivities = new ArrayList<>(); } acknowledgment detectedActivities; } }
import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.content.Context; import android.content.Intent; import android.widget.ListView; import android.app.PendingIntent; import android.preference.PreferenceManager; import android.content.SharedPreferences; import android.view.View; import com.google.android.gms.location.ActivityRecognitionClient; import com.google.android.gms.location.DetectedActivity; import com.google.android.gms.tasks.OnSuccessListener; import com.google.android.gms.tasks.Task; import java.util.ArrayList; public chic MainActivity extends AppCompatActivity accouterments SharedPreferences.OnSharedPreferenceChangeListener { clandestine Ambience mContext; accessible changeless final Cord DETECTED_ACTIVITY = ".DETECTED_ACTIVITY"; //Define an ActivityRecognitionClient// clandestine ActivityRecognitionClient mActivityRecognitionClient; clandestine ActivitiesAdapter mAdapter; @Override accessible abandoned onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mContext = this; //Retrieve the ListView area we’ll affectation our action data// ListView detectedActivitiesListView = (ListView) findViewById(R.id.activities_listview); ArrayListdetectedActivities = ActivityIntentService.detectedActivitiesFromJson( PreferenceManager.getDefaultSharedPreferences(this).getString( DETECTED_ACTIVITY, "")); //Bind the adapter to the ListView// mAdapter = new ActivitiesAdapter(this, detectedActivities); detectedActivitiesListView.setAdapter(mAdapter); mActivityRecognitionClient = new ActivityRecognitionClient(this); } @Override adequate abandoned onResume() { super.onResume(); PreferenceManager.getDefaultSharedPreferences(this) .registerOnSharedPreferenceChangeListener(this); updateDetectedActivitiesList(); } @Override adequate abandoned onPause() { PreferenceManager.getDefaultSharedPreferences(this) .unregisterOnSharedPreferenceChangeListener(this); super.onPause(); } accessible abandoned requestUpdatesHandler(View view) { //Set the action apprehension interval. I’m appliance 3 seconds// Task assignment = mActivityRecognitionClient.requestActivityUpdates( 3000, getActivityDetectionPendingIntent()); task.addOnSuccessListener(new OnSuccessListener () { @Override accessible abandoned onSuccess(Void result) { updateDetectedActivitiesList(); } }); } //Get a PendingIntent// clandestine PendingIntent getActivityDetectionPendingIntent() { //Send the action abstracts to our DetectedActivitiesIntentService class// Absorbed absorbed = new Intent(this, ActivityIntentService.class); acknowledgment PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); } //Process the account of activities// adequate abandoned updateDetectedActivitiesList() { ArrayList detectedActivities = ActivityIntentService.detectedActivitiesFromJson( PreferenceManager.getDefaultSharedPreferences(mContext) .getString(DETECTED_ACTIVITY, "")); mAdapter.updateActivities(detectedActivities); } @Override accessible abandoned onSharedPreferenceChanged(SharedPreferences sharedPreferences, Cord s) { if (s.equals(DETECTED_ACTIVITY)) { updateDetectedActivitiesList(); } } }
import android.support.annotation.NonNull; import android.support.annotation.Nullable; import java.util.ArrayList; import java.util.HashMap; import android.widget.ArrayAdapter; import android.content.Context; import android.view.LayoutInflater; import android.widget.TextView; import android.view.View; import android.view.ViewGroup; import com.google.android.gms.location.DetectedActivity; class ActivitiesAdapter extends ArrayAdapter{ ActivitiesAdapter(Context context, ArrayList detectedActivities) { super(context, 0, detectedActivities); } @NonNull @Override accessible Appearance getView(int position, @Nullable Appearance view, @NonNull ViewGroup parent) { //Retrieve the abstracts item// DetectedActivity detectedActivity = getItem(position); if (view == null) { appearance = LayoutInflater.from(getContext()).inflate( R.layout.detected_activity, parent, false); } //Retrieve the TextViews area we’ll affectation the action type, and percentage// TextView activityName = (TextView) view.findViewById(R.id.activity_type); TextView activityConfidenceLevel = (TextView) view.findViewById( R.id.confidence_percentage); //If an action is detected...// if (detectedActivity != null) { activityName.setText(ActivityIntentService.getActivityString(getContext(), //...get the action type...// detectedActivity.getType())); //..and the aplomb percentage// activityConfidenceLevel.setText(getContext().getString(R.string.percentage, detectedActivity.getConfidence())); } acknowledgment view; } //Process the account of detected activities// abandoned updateActivities(ArrayList detectedActivities) { HashMap detectedActivitiesMap = new HashMap<>(); for (DetectedActivity action : detectedActivities) { detectedActivitiesMap.put(activity.getType(), activity.getConfidence()); } ArrayList temporaryList = new ArrayList<>(); for (int i = 0; i < ActivityIntentService.POSSIBLE_ACTIVITIES.length; i ) { int aplomb = detectedActivitiesMap.containsKey(ActivityIntentService.POSSIBLE_ACTIVITIES[i]) ? detectedActivitiesMap.get(ActivityIntentService.POSSIBLE_ACTIVITIES[i]) : 0; //Add the commodity to a temporaryList// temporaryList.add(new DetectedActivity(ActivityIntentService.POSSIBLE_ACTIVITIES[i], confidence)); } //Remove all elements from the temporaryList// this.clear(); //Refresh the View// for (DetectedActivity detectedActivity: temporaryList) { this.add(detectedActivity); } } }
@Override adequate abandoned onHandleIntent(Intent intent) { //Check whether the Absorbed contains action acceptance data// if (ActivityRecognitionResult.hasResult(intent)) { //If abstracts is available, again abstract the ActivityRecognitionResult from the Intent// ActivityRecognitionResult aftereffect = ActivityRecognitionResult.extractResult(intent); DetectedActivity mostProbableActivity = result.getMostProbableActivity(); //Get the aplomb percentage// int aplomb = mostProbableActivity.getConfidence(); //Get the action type// int activityType = mostProbableActivity.getType(); //Do something// ... ... ...
//If ON_FOOT has an 80% or college anticipation percentage...// if(DetectedActivity == “On_Foot” && result.getConfidence()> 80) { //...then do something// }
Comments
Post a Comment