androidgoogle-play-servicesactivity-recognition

ActivityRecognitionIntentService onHandleIntent only occasionally fires


I am trying to get Activity Recognition updates for my app but it only seems to be partially working. First I thought it wasn't working but every once in a while the debug log shows an activity type which means the ActivityRecognitionIntentService onHandleIntent() was hit but it never makes it to the ActivityBroadCastReceiver

I have the following code in MainActivity

    Intent i = new Intent(this, ActivityRecognitionIntentService.class);
    i.setAction("ActivityRecognitionIntentService");
    PendingIntent activityRecognitionPendingIntent = PendingIntent.getService(this, 7422, i, PendingIntent.FLAG_UPDATE_CURRENT);
    ActivityRecognitionApi rec = ActivityRecognition.ActivityRecognitionApi;
    rec.requestActivityUpdates(mClient, 5000, activityRecognitionPendingIntent)
            .setResultCallback(new ResultCallback<Status>() {
                @Override
                public void onResult(Status status) {
                    if (status.isSuccess()) {
                        Log.i(TAG, "Successfully registered updates");
                    } else {
                        Log.i(TAG, "Failed to register updates");
                    }
                }
            });;

That should fire every 5 seconds if I did it right. The associated IntentService is:

public class ActivityRecognitionIntentService extends IntentService {

ActivityRecognitionResult result;
Intent i;
DetectedActivity mpactivity;

public ActivityRecognitionIntentService() {
    super("ActivityRecognitionIntentService");
    i = new Intent("ACTIVITY_RECOGNITION_DATA");
    Log.d(MainActivity.TAG, "ActivityRecognitionIntentService created");
}

private String getTypes(int type) {
    Log.d(MainActivity.TAG, "type = " + type);
    if(type == DetectedActivity.UNKNOWN)
        return "Unknown";
    else if(type == DetectedActivity.IN_VEHICLE)
        return "In Vehicle";
    else if(type == DetectedActivity.ON_BICYCLE)
        return "On Bicycle";
    else if(type == DetectedActivity.RUNNING)
        return "Running";
    else if(type == DetectedActivity.ON_FOOT)
        return "On Foot";
    else if(type == DetectedActivity.STILL)
        return "Still";
    else if(type == DetectedActivity.TILTING)
        return "Tilting";
    else if(type == DetectedActivity.WALKING)
        return "Walking";
    else
        return "";
}

@Override
protected void onHandleIntent(Intent intent) {
    Log.d(MainActivity.TAG, "onHandleIntent");
    if (intent.getAction() == "ActivityRecognitionIntentService") {
        if(ActivityRecognitionResult.hasResult(intent)){
            result = ActivityRecognitionResult.extractResult(intent);
            mpactivity = result.getMostProbableActivity();
            i.putExtra("Activity", getTypes(mpactivity.getType()));
            i.putExtra("Confidence", mpactivity.getConfidence());
            LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(i);
        }
    }
}

and my manifest shows:

    <service android:name=".ActivityRecognitionIntentService" android:exported="false"></service>

    <receiver android:name=".ActivityBroadcastReceiver" android:exported="false">
        <intent-filter>
            <action android:name="ACTIVITY_RECOGNITION_DATA"/>
        </intent-filter>
    </receiver>
    <meta-data android:name="com.google.android.gms.version"
        android:value="@integer/google_play_services_version" />

with the BroadcastReceiver:

public class ActivityBroadcastReceiver extends android.content.BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
    Log.d(MainActivity.TAG, "BroadcastReceiver");
    Toast.makeText(context, "Service received", Toast.LENGTH_SHORT).show();
}

Why would it only work occasionally? The phone isn't allowed to sleep while debugging (N6). Additionally, why does it not make it to the BroadcastReceiver?


Solution

  • The detectionIntervalMillis will not be exact. If the phone is still it may not report anything until the activity is changing. In my experience, the interval is longer when the current activity is not changing.

    To quote from the docs, To conserve battery, activity reporting may stop when the device is 'STILL' for an extended period of time. It will resume once the device moves again. Is your device sitting still? Try shaking or walking around a bit to test.