This is a just a simple example of how to use GooglePlay Service's ActivityRecognitionApi. Although this is a great library, it does not work on devices that do not have Google Play Services installed.
Docs for ActivityRecognition API
Manifest
<!-- This is needed to use Activity Recognition! -->
<uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION" />
<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <receiver android:name=".ActivityReceiver" />
</application>
MainActivity.java
public class MainActivity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
    private GoogleApiClient apiClient;
    private LocalBroadcastManager localBroadcastManager;
    private BroadcastReceiver localActivityReceiver;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        apiClient = new GoogleApiClient.Builder(this)
                .addApi(ActivityRecognition.API)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build();
        //This just gets the activity intent from the ActivityReceiver class
        localBroadcastManager = LocalBroadcastManager.getInstance(this);
        localActivityReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                ActivityRecognitionResult recognitionResult = ActivityRecognitionResult.extractResult(intent);
                TextView textView = (TextView) findViewById(R.id.activityText);
                
                //This is just to get the activity name. Use at your own risk.
                textView.setText(DetectedActivity.zzkf(recognitionResult.getMostProbableActivity().getType()));
            }
        };
    }
    @Override
    protected void onResume() {
        super.onResume();
        //Register local broadcast receiver
        localBroadcastManager.registerReceiver(localActivityReceiver, new IntentFilter("activity"));
        //Connect google api client
        apiClient.connect();
    }
    @Override
    protected void onPause() {
        super.onPause();
        //Unregister for activity recognition
        ActivityRecognition.ActivityRecognitionApi.removeActivityUpdates(apiClient, PendingIntent.getBroadcast(this, 0, new Intent(this, ActivityReceiver.class), PendingIntent.FLAG_UPDATE_CURRENT));
        //Disconnects api client
        apiClient.disconnect();
        //Unregister local receiver
        localBroadcastManager.unregisterReceiver(localActivityReceiver);
    }
    @Override
    public void onConnected(@Nullable Bundle bundle) {
        //Only register for activity recognition if google api client has connected
        ActivityRecognition.ActivityRecognitionApi.requestActivityUpdates(apiClient, 0, PendingIntent.getBroadcast(this, 0, new Intent(this, ActivityReceiver.class), PendingIntent.FLAG_UPDATE_CURRENT));
    }
    @Override
    public void onConnectionSuspended(int i) {
    }
    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
    }
}
ActivityReceiver
public class ActivityReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        LocalBroadcastManager.getInstance(context).sendBroadcast(intent.setAction("activity"));
    }
}
PathSense activity recognition is another good library for devices which don't have Google Play Services, as they have built their own activity recognition model, but requires developers register at http://developer.pathsense.com to get an API key and Client ID.
Manifest
<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <receiver android:name=".ActivityReceiver" />
    <!-- You need to acquire these from their website (http://developer.pathsense.com) -->
    <meta-data
        android:name="com.pathsense.android.sdk.CLIENT_ID"
        android:value="YOUR_CLIENT_ID" />
    <meta-data
        android:name="com.pathsense.android.sdk.API_KEY"
        android:value="YOUR_API_KEY" />
</application>
MainActivity.java
public class MainActivity extends AppCompatActivity {
    private PathsenseLocationProviderApi pathsenseLocationProviderApi;
    private LocalBroadcastManager localBroadcastManager;
    private BroadcastReceiver localActivityReceiver;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        pathsenseLocationProviderApi = PathsenseLocationProviderApi.getInstance(this);
        //This just gets the activity intent from the ActivityReceiver class
        localBroadcastManager = LocalBroadcastManager.getInstance(this);
        localActivityReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                //The detectedActivities object is passed as a serializable
                PathsenseDetectedActivities detectedActivities = (PathsenseDetectedActivities) intent.getSerializableExtra("ps");
                TextView textView = (TextView) findViewById(R.id.activityText);
                textView.setText(detectedActivities.getMostProbableActivity().getDetectedActivity().name());
            }
        };
    }
    @Override
    protected void onResume() {
        super.onResume();
        //Register local broadcast receiver
        localBroadcastManager.registerReceiver(localActivityReceiver, new IntentFilter("activity"));
        //This gives an update everytime it receives one, even if it was the same as the last update
        pathsenseLocationProviderApi.requestActivityUpdates(ActivityReceiver.class);
//        This gives updates only when it changes (ON_FOOT -> IN_VEHICLE for example)
//        pathsenseLocationProviderApi.requestActivityChanges(ActivityReceiver.class);
    }
    @Override
    protected void onPause() {
        super.onPause();
        pathsenseLocationProviderApi.removeActivityUpdates();
//        pathsenseLocationProviderApi.removeActivityChanges();
        //Unregister local receiver
        localBroadcastManager.unregisterReceiver(localActivityReceiver);
    }
}
ActivityReceiver.java
// You don't have to use their broadcastreceiver, but it's best to do so, and just pass the result
// as needed to another class.
public class ActivityReceiver extends PathsenseActivityRecognitionReceiver {
    @Override
    protected void onDetectedActivities(Context context, PathsenseDetectedActivities pathsenseDetectedActivities) {
        Intent intent = new Intent("activity").putExtra("ps", pathsenseDetectedActivities);
        LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
    }
}