DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Because the DevOps movement has redefined engineering responsibilities, SREs now have to become stewards of observability strategy.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Related

  • How to Build a React Native Chat App for Android
  • The 12 Biggest Android App Development Trends in 2023
  • Android Cloud Apps with Azure
  • Implement Real-time Locating in an Android App

Trending

  • Introducing Graph Concepts in Java With Eclipse JNoSQL, Part 3: Understanding Janus
  • Memory Leak Due to Time-Taking finalize() Method
  • The Ultimate Guide to Code Formatting: Prettier vs ESLint vs Biome
  • How Large Tech Companies Architect Resilient Systems for Millions of Users
  1. DZone
  2. Testing, Deployment, and Maintenance
  3. Deployment
  4. Android Activity Recognition

Android Activity Recognition

By 
Tony Siciliani user avatar
Tony Siciliani
·
Sep. 30, 13 · Interview
Likes (0)
Comment
Save
Tweet
Share
32.5K Views

Join the DZone community and get the full member experience.

Join For Free

activity recognition gives our android device the ability to detect a number of our physical activities like walking, riding a bicycle, driving a car or standing idle. all that can be detected by simply using an api to access  google play services  , an increasingly crucial piece of software available to all android versions.

as in the article on geofencing , we will download  the sample app  (  activityrecognition.zip  ) at the android developer’s site and start playing with it, eventually modifying parts of it to fit our purposes. we will show here only the most relevant code sections.

the first thing to note is that we need a specific permission to use activity recognition:

<!-- inside manifest file -->
 <uses-permission
    android:name="com.google.android.gms.permission.activity_recognition"/>

as with geofencing or location updates, we use the api to request google play services to analyse our data and provide us with the results. the chain of method calls for requesting updates is similar to that of geofencing:

  1. make sure that google play services is available.
  2. as an activity recognition client, request a connection.
  3. once connected, location services calls back the  onconnected()  method in our app.
  4. proceed with the updates request via a  pending intent  pointing to an  intentservice  we have written.
  5. google location services sends out its activity recognition updates as intent objects, using the pendingintent we provided. get and process the updates in our intentservice’s  onhandleintent()  method.

the sample app writes all the updates in a log file, and that is ok if we like that sort of thing … though a closer look at the data makes us realize that most of it is garbage. do we really need to know that we have a 27 percent chance of being driving a vehicle and a 7 percent chance of riding a bicycle when we are in fact sitting idle at our desk? not really. what we want is the most significant data, and in this case, that would be the most probable activity:

//..
import com.google.android.gms.location.activityrecognitionresult;
import com.google.android.gms.location.detectedactivity;

/**
 * service that receives activityrecognition updates. it receives updates
 * in the background, even if the main activity is not visible.
 */
public class activityrecognitionintentservice extends intentservice { 
  //..
  /**
     * called when a new activity detection update is available.
     */
    @override
    protected void onhandleintent(intent intent) {
         //...
          // if the intent contains an update
        if (activityrecognitionresult.hasresult(intent)) {
            // get the update
            activityrecognitionresult result =
              activityrecognitionresult.extractresult(intent);

             detectedactivity mostprobableactivity
                    = result.getmostprobableactivity();

             // get the confidence % (probability)
            int confidence = mostprobableactivity.getconfidence();

            // get the type
            int activitytype = mostprobableactivity.gettype();
           /* types:
            * detectedactivity.in_vehicle
            * detectedactivity.on_bicycle
            * detectedactivity.on_foot
            * detectedactivity.still
            * detectedactivity.unknown
            * detectedactivity.tilting
            */
            // process
        }
    }
}

instead of writing the updates to a log file, it is simpler to just store them in memory (e.g. in a static  list  in a dedicated class) and display them to the user of our app. one way to do this would be by using a  fragment  to display the updates on top of a google map. as commented in previous articles, fragments were introduced in  honeycomb  but are also available to older android versions through the  support library  .

<?xml version="1.0" encoding="utf-8"?>
<framelayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/lay_map"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:orientation="vertical">

<fragment
 android:id="@+id/map"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 class="com.google.android.gms.maps.supportmapfragment"/>

<!-- activity recognition -->
<fragment
 android:id="@+id/ar_fragment"
 android:name="package.to.our.fragment.actreconfragment"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"/>

</framelayout>

once we define our own xml layout for the  actreconfragment  and give it a transparent background (left to the reader as an exercise), we will get a nice overlaid display like this:

pic1

since we have chosen to show the most probable activity to the users of our app, we need the display to be dynamic, like a  live feed  . for that, we can add a  local broadcast  in our service:

//inside activityrecognitionintentservice 's onhandleintent
intent broadcastintent = new intent();

// give it the category for all intents sent by the intent service
broadcastintent.addcategory(activityutils.category_location_services);
// set the action and content for the broadcast intent
broadcastintent.setaction(activityutils.action_refresh_status_list);

// broadcast *locally* to other components in this app
localbroadcastmanager.getinstance(this).sendbroadcast(broadcastintent);

we are using a  localbroadcastmanager  (included in android 3.0 and above, and in the support library v4 for early releases). apart from providing our own layout to position the activity detection panel on top of a map, the only new code snippet we wrote is the above local broadcast. for the remainder below, we have simply re-positioned the sample app’s code in a fragment and use in-memory storage of the activity updates instead of using a log file. the receiver on that local broadcast is in our fragment:

//...
public class actreconfragment extends fragment{

 // intent filter for incoming broadcasts from the intentservice
 intentfilter mbroadcastfilter;

 // instance of a local broadcast manager
 private localbroadcastmanager mbroadcastmanager;

//...
/**
 * called when the corresponding map activity's
 * oncreate() method has completed.
 */
 @override
public void onactivitycreated(bundle savedinstancestate) {
   super.onactivitycreated(savedinstancestate);     

  // set the broadcast receiver intent filer
  mbroadcastmanager = localbroadcastmanager.getinstance(getactivity());

  // create a new intent filter for the broadcast receiver
  mbroadcastfilter = new intentfilter(activityutils.action_refresh_status_list);
  mbroadcastfilter.addcategory(activityutils.category_location_services);

  //...     
}

/**
* broadcast receiver that receives activity update intents
* this receiver is local only. it can't read broadcast intents from other apps.
*/
broadcastreceiver updatelistreceiver = new broadcastreceiver() {
   @override
   public void onreceive(context context, intent intent) {
     // when an intent is received from the update listener intentservice,
     // update the display.
     updateactivityhistory();
   }
};
//...
}

live feed shots:

pic2

once we have taken care of the display, we need to move on to other important aspects like what to do with those activity updates. the sample app gives us one example of that in the  activityrecognitionintentservice  :

if(
   // if the current type is "moving" i.e on foot, bicycle or vehicle
   ismoving(activitytype)
   &&
  // the activity has changed from the previous activity
  activitychanged(activitytype)
  // the confidence level for the current activity is >= 50%
  && (confidence >= 50)) {

  // do something useful
}

simply getting the most probable activity might be ok for displaying purposes, but might not be enough for an app to act on it and do something useful. we need to make sure that the type of activity and the corresponding confidence level (i.e. probability) are adequate for our purposes. while a detected activity type of “unknown” with a confidence level of 52% is next to useless, knowing that the user is moving in a vehicle as opposed to walking can be put to good use: increase the frequency of location updates, enlarge the map area of available points of interest, etc …

activity recognition has been added as an experimental feature to this  geofencing app  . check it out and feel free to post any feedback.


Android (robot) app Google Play Services

Published at DZone with permission of Tony Siciliani, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • How to Build a React Native Chat App for Android
  • The 12 Biggest Android App Development Trends in 2023
  • Android Cloud Apps with Azure
  • Implement Real-time Locating in an Android App

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!