Please note that the contents of this offline web site may be out of date. To access the most recent documentation visit the online version .
Note that links that point to online resources are green in color and will open in a new window.
We would love it if you could give us feedback about this material by filling this form (You have to be online to fill it)
BatchStepSensor / src / com.example.android.batchstepsensor /

BatchStepSensorFragment.java

       
        1
       
       
        /*
       
       
        2
       
       
        * Copyright 2014 The Android Open Source Project
       
       
        3
       
       
        *
       
       
        4
       
       
        * Licensed under the Apache License, Version 2.0 (the "License");
       
       
        5
       
       
        * you may not use this file except in compliance with the License.
       
       
        6
       
       
        * You may obtain a copy of the License at
       
       
        7
       
       
        *
       
       
        8
       
       
        *     http://www.apache.org/licenses/LICENSE-2.0
       
       
        9
       
       
        *
       
       
        10
       
       
        * Unless required by applicable law or agreed to in writing, software
       
       
        11
       
       
        * distributed under the License is distributed on an "AS IS" BASIS,
       
       
        12
       
       
        * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       
       
        13
       
       
        * See the License for the specific language governing permissions and
       
       
        14
       
       
        * limitations under the License.
       
       
        15
       
       
        */
       
       
        16
       
       
       
       
        17
       
       
        package com.example.android.batchstepsensor;
       
       
        18
       
       
       
       
        19
       
       
        import android.app.Activity;
       
       
        20
       
       
        import android.content.pm.PackageManager;
       
       
        21
       
       
        import android.hardware.Sensor;
       
       
        22
       
       
        import android.hardware.SensorEvent;
       
       
        23
       
       
        import android.hardware.SensorEventListener;
       
       
        24
       
       
        import android.hardware.SensorManager;
       
       
        25
       
       
        import android.os.Bundle;
       
       
        26
       
       
        import android.support.v4.app.Fragment;
       
       
        27
       
       
       
       
        28
       
       
        import com.example.android.common.logger.Log;
       
       
        29
       
       
        import com.example.android.batchstepsensor.cardstream.Card;
       
       
        30
       
       
        import com.example.android.batchstepsensor.cardstream.CardStream;
       
       
        31
       
       
        import com.example.android.batchstepsensor.cardstream.CardStreamFragment;
       
       
        32
       
       
        import com.example.android.batchstepsensor.cardstream.OnCardClickListener;
       
       
        33
       
       
       
       
        34
       
       
        public class BatchStepSensorFragment extends Fragment implements OnCardClickListener {
       
       
        35
       
       
       
       
        36
       
       
        public static final String TAG = "StepSensorSample";
       
       
        37
       
       
        // Cards
       
       
        38
       
       
        private CardStreamFragment mCards = null;
       
       
        39
       
       
       
       
        40
       
       
        // Card tags
       
       
        41
       
       
        public static final String CARD_INTRO = "intro";
       
       
        42
       
       
        public static final String CARD_REGISTER_DETECTOR = "register_detector";
       
       
        43
       
       
        public static final String CARD_REGISTER_COUNTER = "register_counter";
       
       
        44
       
       
        public static final String CARD_BATCHING_DESCRIPTION = "register_batching_description";
       
       
        45
       
       
        public static final String CARD_COUNTING = "counting";
       
       
        46
       
       
        public static final String CARD_EXPLANATION = "explanation";
       
       
        47
       
       
        public static final String CARD_NOBATCHSUPPORT = "error";
       
       
        48
       
       
       
       
        49
       
       
        // Actions from REGISTER cards
       
       
        50
       
       
        public static final int ACTION_REGISTER_DETECT_NOBATCHING = 10;
       
       
        51
       
       
        public static final int ACTION_REGISTER_DETECT_BATCHING_5s = 11;
       
       
        52
       
       
        public static final int ACTION_REGISTER_DETECT_BATCHING_10s = 12;
       
       
        53
       
       
        public static final int ACTION_REGISTER_COUNT_NOBATCHING = 21;
       
       
        54
       
       
        public static final int ACTION_REGISTER_COUNT_BATCHING_5s = 22;
       
       
        55
       
       
        public static final int ACTION_REGISTER_COUNT_BATCHING_10s = 23;
       
       
        56
       
       
        // Action from COUNTING card
       
       
        57
       
       
        public static final int ACTION_UNREGISTER = 1;
       
       
        58
       
       
        // Actions from description cards
       
       
        59
       
       
        private static final int ACTION_BATCHING_DESCRIPTION_DISMISS = 2;
       
       
        60
       
       
        private static final int ACTION_EXPLANATION_DISMISS = 3;
       
       
        61
       
       
       
       
        62
       
       
        // State of application, used to register for sensors when app is restored
       
       
        63
       
       
        public static final int STATE_OTHER = 0;
       
       
        64
       
       
        public static final int STATE_COUNTER = 1;
       
       
        65
       
       
        public static final int STATE_DETECTOR = 2;
       
       
        66
       
       
       
       
        67
       
       
        // Bundle tags used to store data when restoring application state
       
       
        68
       
       
        private static final String BUNDLE_STATE = "state";
       
       
        69
       
       
        private static final String BUNDLE_LATENCY = "latency";
       
       
        70
       
       
        private static final String BUNDLE_STEPS = "steps";
       
       
        71
       
       
       
       
        72
       
       
        // max batch latency is specified in microseconds
       
       
        73
       
       
        private static final int BATCH_LATENCY_0 = 0; // no batching
       
       
        74
       
       
        private static final int BATCH_LATENCY_10s = 10000000;
       
       
        75
       
       
        private static final int BATCH_LATENCY_5s = 5000000;
       
       
        76
       
       
       
       
        77
       
       
        /*
       
       
        78
       
       
        For illustration we keep track of the last few events and show their delay from when the
       
       
        79
       
       
        event occurred until it was received by the event listener.
       
       
        80
       
       
        These variables keep track of the list of timestamps and the number of events.
       
       
        81
       
       
        */
       
       
        82
       
       
        // Number of events to keep in queue and display on card
       
       
        83
       
       
        private static final int EVENT_QUEUE_LENGTH = 10;
       
       
        84
       
       
        // List of timestamps when sensor events occurred
       
       
        85
       
       
        private float[] mEventDelays = new float[EVENT_QUEUE_LENGTH];
       
       
        86
       
       
       
       
        87
       
       
        // number of events in event list
       
       
        88
       
       
        private int mEventLength = 0;
       
       
        89
       
       
        // pointer to next entry in sensor event list
       
       
        90
       
       
        private int mEventData = 0;
       
       
        91
       
       
       
       
        92
       
       
        // Steps counted in current session
       
       
        93
       
       
        private int mSteps = 0;
       
       
        94
       
       
        // Value of the step counter sensor when the listener was registered.
       
       
        95
       
       
        // (Total steps are calculated from this value.)
       
       
        96
       
       
        private int mCounterSteps = 0;
       
       
        97
       
       
        // Steps counted by the step counter previously. Used to keep counter consistent across rotation
       
       
        98
       
       
        // changes
       
       
        99
       
       
        private int mPreviousCounterSteps = 0;
       
       
        100
       
       
        // State of the app (STATE_OTHER, STATE_COUNTER or STATE_DETECTOR)
       
       
        101
       
       
        private int mState = STATE_OTHER;
       
       
        102
       
       
        // When a listener is registered, the batch sensor delay in microseconds
       
       
        103
       
       
        private int mMaxDelay = 0;
       
       
        104
       
       
       
       
        105
       
       
        @Override
       
       
        106
       
       
        public void onResume() {
       
       
        107
       
       
        super.onResume();
       
       
        108
       
       
       
       
        109
       
       
        CardStreamFragment stream = getCardStream();
       
       
        110
       
       
        if (stream.getVisibleCardCount() < 1) {
       
       
        111
       
       
        // No cards are visible, started for the first time
       
       
        112
       
       
        // Prepare all cards and show the intro card.
       
       
        113
       
       
        initialiseCards();
       
       
        114
       
       
        showIntroCard();
       
       
        115
       
       
        // Show the registration card if the hardware is supported, show an error otherwise
       
       
        116
       
       
        if (isKitkatWithStepSensor()) {
       
       
        117
       
       
        showRegisterCard();
       
       
        118
       
       
        } else {
       
       
        119
       
       
        showErrorCard();
       
       
        120
       
       
        }
       
       
        121
       
       
        }
       
       
        122
       
       
        }
       
       
        123
       
       
       
       
        124
       
       
        @Override
       
       
        125
       
       
        public void onPause() {
       
       
        126
       
       
        super.onPause();
       
       
        128
       
       
        // Unregister the listener when the application is paused
       
       
        129
       
       
        unregisterListeners();
       
       
        131
       
       
        }
       
       
        132
       
       
       
       
        133
       
       
        /**
       
       
        134
       
       
        * Returns true if this device is supported. It needs to be running Android KitKat (4.4) or
       
       
        135
       
       
        * higher and has a step counter and step detector sensor.
       
       
        136
       
       
        * This check is useful when an app provides an alternative implementation or different
       
       
        137
       
       
        * functionality if the step sensors are not available or this code runs on a platform version
       
       
        138
       
       
        * below Android KitKat. If this functionality is required, then the minSDK parameter should
       
       
        139
       
       
        * be specified appropriately in the AndroidManifest.
       
       
        140
       
       
        *
       
       
        141
       
       
        * @return True iff the device can run this sample
       
       
        142
       
       
        */
       
       
        143
       
       
        private boolean isKitkatWithStepSensor() {
       
       
        145
       
       
        // Require at least Android KitKat
       
       
        146
       
       
        int currentApiVersion = android.os.Build.VERSION.SDK_INT;
       
       
        147
       
       
        // Check that the device supports the step counter and detector sensors
       
       
        148
       
       
        PackageManager packageManager = getActivity().getPackageManager();
       
       
        149
       
       
        return currentApiVersion >= android.os.Build.VERSION_CODES.KITKAT
       
       
        150
       
       
        && packageManager.hasSystemFeature(PackageManager.FEATURE_SENSOR_STEP_COUNTER)
       
       
        151
       
       
        && packageManager.hasSystemFeature(PackageManager.FEATURE_SENSOR_STEP_DETECTOR);
       
       
        153
       
       
        }
       
       
        154
       
       
       
       
        155
       
       
        /**
       
       
        156
       
       
        * Handles a click on a card action.
       
       
        157
       
       
        * Registers a SensorEventListener (see {@link #registerEventListener(int, int)}) with the
       
       
        158
       
       
        * selected delay, dismisses cards and unregisters the listener
       
       
        159
       
       
        * (see {@link #unregisterListeners()}).
       
       
        160
       
       
        * Actions are defined when a card is created.
       
       
        161
       
       
        *
       
       
        162
       
       
        * @param cardActionId
       
       
        163
       
       
        * @param cardTag
       
       
        164
       
       
        */
       
       
        165
       
       
        @Override
       
       
        166
       
       
        public void onCardClick(int cardActionId, String cardTag) {
       
       
        167
       
       
       
       
        168
       
       
        switch (cardActionId) {
       
       
        170
       
       
        // Register Step Counter card
       
       
        171
       
       
        case ACTION_REGISTER_COUNT_NOBATCHING:
       
       
        172
       
       
        registerEventListener(BATCH_LATENCY_0, Sensor.TYPE_STEP_COUNTER);
       
       
        173
       
       
        break;
       
       
        174
       
       
        case ACTION_REGISTER_COUNT_BATCHING_5s:
       
       
        175
       
       
        registerEventListener(BATCH_LATENCY_5s, Sensor.TYPE_STEP_COUNTER);
       
       
        176
       
       
        break;
       
       
        177
       
       
        case ACTION_REGISTER_COUNT_BATCHING_10s:
       
       
        178
       
       
        registerEventListener(BATCH_LATENCY_10s, Sensor.TYPE_STEP_COUNTER);
       
       
        179
       
       
        break;
       
       
        180
       
       
       
       
        181
       
       
        // Register Step Detector card
       
       
        182
       
       
        case ACTION_REGISTER_DETECT_NOBATCHING:
       
       
        183
       
       
        registerEventListener(BATCH_LATENCY_0, Sensor.TYPE_STEP_DETECTOR);
       
       
        184
       
       
        break;
       
       
        185
       
       
        case ACTION_REGISTER_DETECT_BATCHING_5s:
       
       
        186
       
       
        registerEventListener(BATCH_LATENCY_5s, Sensor.TYPE_STEP_DETECTOR);
       
       
        187
       
       
        break;
       
       
        188
       
       
        case ACTION_REGISTER_DETECT_BATCHING_10s:
       
       
        189
       
       
        registerEventListener(BATCH_LATENCY_10s, Sensor.TYPE_STEP_DETECTOR);
       
       
        190
       
       
        break;
       
       
        191
       
       
       
       
        192
       
       
        // Unregister card
       
       
        193
       
       
        case ACTION_UNREGISTER:
       
       
        194
       
       
        showRegisterCard();
       
       
        195
       
       
        unregisterListeners();
       
       
        196
       
       
        // reset the application state when explicitly unregistered
       
       
        197
       
       
        mState = STATE_OTHER;
       
       
        198
       
       
        break;
       
       
        200
       
       
        // Explanation cards
       
       
        201
       
       
        case ACTION_BATCHING_DESCRIPTION_DISMISS:
       
       
        202
       
       
        // permanently remove the batch description card, it will not be shown again
       
       
        203
       
       
        getCardStream().removeCard(CARD_BATCHING_DESCRIPTION);
       
       
        204
       
       
        break;
       
       
        205
       
       
        case ACTION_EXPLANATION_DISMISS:
       
       
        206
       
       
        // permanently remove the explanation card, it will not be shown again
       
       
        207
       
       
        getCardStream().removeCard(CARD_EXPLANATION);
       
       
        208
       
       
        }
       
       
        209
       
       
       
       
        210
       
       
        // For register cards, display the counting card
       
       
        211
       
       
        if (cardTag.equals(CARD_REGISTER_COUNTER) || cardTag.equals(CARD_REGISTER_DETECTOR)) {
       
       
        212
       
       
        showCountingCards();
       
       
        213
       
       
        }
       
       
        214
       
       
        }
       
       
        215
       
       
       
       
        216
       
       
        /**
       
       
        217
       
       
        * Register a {@link android.hardware.SensorEventListener} for the sensor and max batch delay.
       
       
        218
       
       
        * The maximum batch delay specifies the maximum duration in microseconds for which subsequent
       
       
        219
       
       
        * sensor events can be temporarily stored by the sensor before they are delivered to the
       
       
        220
       
       
        * registered SensorEventListener. A larger delay allows the system to handle sensor events more
       
       
        221
       
       
        * efficiently, allowing the system to switch to a lower power state while the sensor is
       
       
        222
       
       
        * capturing events. Once the max delay is reached, all stored events are delivered to the
       
       
        223
       
       
        * registered listener. Note that this value only specifies the maximum delay, the listener may
       
       
        224
       
       
        * receive events quicker. A delay of 0 disables batch mode and registers the listener in
       
       
        225
       
       
        * continuous mode.
       
       
        226
       
       
        * The optimium batch delay depends on the application. For example, a delay of 5 seconds or
       
       
        227
       
       
        * higher may be appropriate for an  application that does not update the UI in real time.
       
       
        228
       
       
        *
       
       
        229
       
       
        * @param maxdelay
       
       
        230
       
       
        * @param sensorType
       
       
        231
       
       
        */
       
       
        232
       
       
        private void registerEventListener(int maxdelay, int sensorType) {
       
       
        234
       
       
       
       
        235
       
       
        // Keep track of state so that the correct sensor type and batch delay can be set up when
       
       
        236
       
       
        // the app is restored (for example on screen rotation).
       
       
        237
       
       
        mMaxDelay = maxdelay;
       
       
        238
       
       
        if (sensorType == Sensor.TYPE_STEP_COUNTER) {
       
       
        239
       
       
        mState = STATE_COUNTER;
       
       
        240
       
       
        /*
       
       
        241
       
       
        Reset the initial step counter value, the first event received by the event listener is
       
       
        242
       
       
        stored in mCounterSteps and used to calculate the total number of steps taken.
       
       
        243
       
       
        */
       
       
        244
       
       
        mCounterSteps = 0;
       
       
        245
       
       
        Log.i(TAG, "Event listener for step counter sensor registered with a max delay of "
       
       
        246
       
       
        + mMaxDelay);
       
       
        247
       
       
        } else {
       
       
        248
       
       
        mState = STATE_DETECTOR;
       
       
        249
       
       
        Log.i(TAG, "Event listener for step detector sensor registered with a max delay of "
       
       
        250
       
       
        + mMaxDelay);
       
       
        251
       
       
        }
       
       
        252
       
       
       
       
        253
       
       
        // Get the default sensor for the sensor type from the SenorManager
       
       
        254
       
       
        SensorManager sensorManager =
       
       
        255
       
       
        (SensorManager) getActivity().getSystemService(Activity.SENSOR_SERVICE);
       
       
        256
       
       
        // sensorType is either Sensor.TYPE_STEP_COUNTER or Sensor.TYPE_STEP_DETECTOR
       
       
        257
       
       
        Sensor sensor = sensorManager.getDefaultSensor(sensorType);
       
       
        258
       
       
       
       
        259
       
       
        // Register the listener for this sensor in batch mode.
       
       
        260
       
       
        // If the max delay is 0, events will be delivered in continuous mode without batching.
       
       
        261
       
       
        final boolean batchMode = sensorManager.registerListener(
       
       
        262
       
       
        mListener, sensor, SensorManager.SENSOR_DELAY_NORMAL, maxdelay);
       
       
        263
       
       
       
       
        264
       
       
        if (!batchMode) {
       
       
        265
       
       
        // Batch mode could not be enabled, show a warning message and switch to continuous mode
       
       
        266
       
       
        getCardStream().getCard(CARD_NOBATCHSUPPORT)
       
       
        267
       
       
        .setDescription(getString(R.string.warning_nobatching));
       
       
        268
       
       
        getCardStream().showCard(CARD_NOBATCHSUPPORT);
       
       
        269
       
       
        Log.w(TAG, "Could not register sensor listener in batch mode, " +
       
       
        270
       
       
        "falling back to continuous mode.");
       
       
        271
       
       
        }
       
       
        272
       
       
       
       
        273
       
       
        if (maxdelay > 0 && batchMode) {
       
       
        274
       
       
        // Batch mode was enabled successfully, show a description card
       
       
        275
       
       
        getCardStream().showCard(CARD_BATCHING_DESCRIPTION);
       
       
        276
       
       
        }
       
       
        277
       
       
       
       
        278
       
       
        // Show the explanation card
       
       
        279
       
       
        getCardStream().showCard(CARD_EXPLANATION);
       
       
        280
       
       
       
       
        282
       
       
       
       
        283
       
       
        }
       
       
        284
       
       
       
       
        285
       
       
        /**
       
       
        286
       
       
        * Unregisters the sensor listener if it is registered.
       
       
        287
       
       
        */
       
       
        288
       
       
        private void unregisterListeners() {
       
       
        290
       
       
        SensorManager sensorManager =
       
       
        291
       
       
        (SensorManager) getActivity().getSystemService(Activity.SENSOR_SERVICE);
       
       
        292
       
       
        sensorManager.unregisterListener(mListener);
       
       
        293
       
       
        Log.i(TAG, "Sensor listener unregistered.");
       
       
        294
       
       
       
       
        296
       
       
        }
       
       
        297
       
       
       
       
        298
       
       
        /**
       
       
        299
       
       
        * Resets the step counter by clearing all counting variables and lists.
       
       
        300
       
       
        */
       
       
        301
       
       
        private void resetCounter() {
       
       
        303
       
       
        mSteps = 0;
       
       
        304
       
       
        mCounterSteps = 0;
       
       
        305
       
       
        mEventLength = 0;
       
       
        306
       
       
        mEventDelays = new float[EVENT_QUEUE_LENGTH];
       
       
        307
       
       
        mPreviousCounterSteps = 0;
       
       
        309
       
       
        }
       
       
        310
       
       
       
       
        311
       
       
       
       
        312
       
       
        /**
       
       
        313
       
       
        * Listener that handles step sensor events for step detector and step counter sensors.
       
       
        314
       
       
        */
       
       
        315
       
       
        private final SensorEventListener mListener = new SensorEventListener() {
       
       
        316
       
       
        @Override
       
       
        317
       
       
        public void onSensorChanged(SensorEvent event) {
       
       
        319
       
       
        // store the delay of this event
       
       
        320
       
       
        recordDelay(event);
       
       
        321
       
       
        final String delayString = getDelayString();
       
       
        322
       
       
       
       
        323
       
       
        if (event.sensor.getType() == Sensor.TYPE_STEP_DETECTOR) {
       
       
        324
       
       
        // A step detector event is received for each step.
       
       
        325
       
       
        // This means we need to count steps ourselves
       
       
        326
       
       
       
       
        327
       
       
        mSteps += event.values.length;
       
       
        328
       
       
       
       
        329
       
       
        // Update the card with the latest step count
       
       
        330
       
       
        getCardStream().getCard(CARD_COUNTING)
       
       
        331
       
       
        .setTitle(getString(R.string.counting_title, mSteps))
       
       
        332
       
       
        .setDescription(getString(R.string.counting_description,
       
       
        333
       
       
        getString(R.string.sensor_detector), mMaxDelay, delayString));
       
       
        334
       
       
       
       
        335
       
       
        Log.i(TAG,
       
       
        336
       
       
        "New step detected by STEP_DETECTOR sensor. Total step count: " + mSteps);
       
       
        337
       
       
       
       
        338
       
       
        } else if (event.sensor.getType() == Sensor.TYPE_STEP_COUNTER) {
       
       
        339
       
       
       
       
        340
       
       
        /*
       
       
        341
       
       
        A step counter event contains the total number of steps since the listener
       
       
        342
       
       
        was first registered. We need to keep track of this initial value to calculate the
       
       
        343
       
       
        number of steps taken, as the first value a listener receives is undefined.
       
       
        344
       
       
        */
       
       
        345
       
       
        if (mCounterSteps < 1) {
       
       
        346
       
       
        // initial value
       
       
        347
       
       
        mCounterSteps = (int) event.values[0];
       
       
        348
       
       
        }
       
       
        349
       
       
       
       
        350
       
       
        // Calculate steps taken based on first counter value received.
       
       
        351
       
       
        mSteps = (int) event.values[0] - mCounterSteps;
       
       
        352
       
       
       
       
        353
       
       
        // Add the number of steps previously taken, otherwise the counter would start at 0.
       
       
        354
       
       
        // This is needed to keep the counter consistent across rotation changes.
       
       
        355
       
       
        mSteps = mSteps + mPreviousCounterSteps;
       
       
        356
       
       
       
       
        357
       
       
        // Update the card with the latest step count
       
       
        358
       
       
        getCardStream().getCard(CARD_COUNTING)
       
       
        359
       
       
        .setTitle(getString(R.string.counting_title, mSteps))
       
       
        360
       
       
        .setDescription(getString(R.string.counting_description,
       
       
        361
       
       
        getString(R.string.sensor_counter), mMaxDelay, delayString));
       
       
        362
       
       
        Log.i(TAG, "New step detected by STEP_COUNTER sensor. Total step count: " + mSteps);
       
       
        364
       
       
        }
       
       
        365
       
       
        }
       
       
        366
       
       
       
       
        367
       
       
        @Override
       
       
        368
       
       
        public void onAccuracyChanged(Sensor sensor, int accuracy) {
       
       
        369
       
       
       
       
        370
       
       
        }
       
       
        371
       
       
        };
       
       
        372
       
       
       
       
        373
       
       
        /**
       
       
        374
       
       
        * Records the delay for the event.
       
       
        375
       
       
        *
       
       
        376
       
       
        * @param event
       
       
        377
       
       
        */
       
       
        378
       
       
        private void recordDelay(SensorEvent event) {
       
       
        379
       
       
        // Calculate the delay from when event was recorded until it was received here in ms
       
       
        380
       
       
        // Event timestamp is recorded in us accuracy, but ms accuracy is sufficient here
       
       
        381
       
       
        mEventDelays[mEventData] = System.currentTimeMillis() - (event.timestamp / 1000000L);
       
       
        382
       
       
       
       
        383
       
       
        // Increment length counter
       
       
        384
       
       
        mEventLength = Math.min(EVENT_QUEUE_LENGTH, mEventLength + 1);
       
       
        385
       
       
        // Move pointer to the next (oldest) location
       
       
        386
       
       
        mEventData = (mEventData + 1) % EVENT_QUEUE_LENGTH;
       
       
        387
       
       
        }
       
       
        388
       
       
       
       
        389
       
       
        private final StringBuffer mDelayStringBuffer = new StringBuffer();
       
       
        390
       
       
       
       
        391
       
       
        /**
       
       
        392
       
       
        * Returns a string describing the sensor delays recorded in
       
       
        393
       
       
        * {@link #recordDelay(android.hardware.SensorEvent)}.
       
       
        394
       
       
        *
       
       
        395
       
       
        * @return
       
       
        396
       
       
        */
       
       
        397
       
       
        private String getDelayString() {
       
       
        398
       
       
        // Empty the StringBuffer
       
       
        399
       
       
        mDelayStringBuffer.setLength(0);
       
       
        400
       
       
       
       
        401
       
       
        // Loop over all recorded delays and append them to the buffer as a decimal
       
       
        402
       
       
        for (int i = 0; i < mEventLength; i++) {
       
       
        403
       
       
        if (i > 0) {
       
       
        404
       
       
        mDelayStringBuffer.append(", ");
       
       
        405
       
       
        }
       
       
        406
       
       
        final int index = (mEventData + i) % EVENT_QUEUE_LENGTH;
       
       
        407
       
       
        final float delay = mEventDelays[index] / 1000f; // convert delay from ms into s
       
       
        408
       
       
        mDelayStringBuffer.append(String.format("%1.1f", delay));
       
       
        409
       
       
        }
       
       
        410
       
       
       
       
        411
       
       
        return mDelayStringBuffer.toString();
       
       
        412
       
       
        }
       
       
        413
       
       
       
       
        414
       
       
        /**
       
       
        415
       
       
        * Records the state of the application into the {@link android.os.Bundle}.
       
       
        416
       
       
        *
       
       
        417
       
       
        * @param outState
       
       
        418
       
       
        */
       
       
        419
       
       
        @Override
       
       
        420
       
       
        public void onSaveInstanceState(Bundle outState) {
       
       
        422
       
       
        super.onSaveInstanceState(outState);
       
       
        423
       
       
        // Store all variables required to restore the state of the application
       
       
        424
       
       
        outState.putInt(BUNDLE_LATENCY, mMaxDelay);
       
       
        425
       
       
        outState.putInt(BUNDLE_STATE, mState);
       
       
        426
       
       
        outState.putInt(BUNDLE_STEPS, mSteps);
       
       
        428
       
       
        }
       
       
        429
       
       
       
       
        430
       
       
        @Override
       
       
        431
       
       
        public void onActivityCreated(Bundle savedInstanceState) {
       
       
        432
       
       
        super.onActivityCreated(savedInstanceState);
       
       
        434
       
       
        // Fragment is being restored, reinitialise its state with data from the bundle
       
       
        435
       
       
        if (savedInstanceState != null) {
       
       
        436
       
       
        resetCounter();
       
       
        437
       
       
        mSteps = savedInstanceState.getInt(BUNDLE_STEPS);
       
       
        438
       
       
        mState = savedInstanceState.getInt(BUNDLE_STATE);
       
       
        439
       
       
        mMaxDelay = savedInstanceState.getInt(BUNDLE_LATENCY);
       
       
        440
       
       
       
       
        441
       
       
        // Register listeners again if in detector or counter states with restored delay
       
       
        442
       
       
        if (mState == STATE_DETECTOR) {
       
       
        443
       
       
        registerEventListener(mMaxDelay, Sensor.TYPE_STEP_DETECTOR);
       
       
        444
       
       
        } else if (mState == STATE_COUNTER) {
       
       
        445
       
       
        // store the previous number of steps to keep  step counter count consistent
       
       
        446
       
       
        mPreviousCounterSteps = mSteps;
       
       
        447
       
       
        registerEventListener(mMaxDelay, Sensor.TYPE_STEP_COUNTER);
       
       
        448
       
       
        }
       
       
        449
       
       
        }
       
       
        451
       
       
        }
       
       
        452
       
       
       
       
        453
       
       
        /**
       
       
        454
       
       
        * Hides the registration cards, reset the counter and show the step counting card.
       
       
        455
       
       
        */
       
       
        456
       
       
        private void showCountingCards() {
       
       
        457
       
       
        // Hide the registration cards
       
       
        458
       
       
        getCardStream().hideCard(CARD_REGISTER_DETECTOR);
       
       
        459
       
       
        getCardStream().hideCard(CARD_REGISTER_COUNTER);
       
       
        460
       
       
       
       
        461
       
       
        // Show the explanation card if it has not been dismissed
       
       
        462
       
       
        getCardStream().showCard(CARD_EXPLANATION);
       
       
        463
       
       
       
       
        464
       
       
        // Reset the step counter, then show the step counting card
       
       
        465
       
       
        resetCounter();
       
       
        466
       
       
       
       
        467
       
       
        // Set the inital text for the step counting card before a step is recorded
       
       
        468
       
       
        String sensor = "-";
       
       
        469
       
       
        if (mState == STATE_COUNTER) {
       
       
        470
       
       
        sensor = getString(R.string.sensor_counter);
       
       
        471
       
       
        } else if (mState == STATE_DETECTOR) {
       
       
        472
       
       
        sensor = getString(R.string.sensor_detector);
       
       
        473
       
       
        }
       
       
        474
       
       
        // Set initial text
       
       
        475
       
       
        getCardStream().getCard(CARD_COUNTING)
       
       
        476
       
       
        .setTitle(getString(R.string.counting_title, 0))
       
       
        477
       
       
        .setDescription(getString(R.string.counting_description, sensor, mMaxDelay, "-"));
       
       
        478
       
       
       
       
        479
       
       
        // Show the counting card and make it undismissable
       
       
        480
       
       
        getCardStream().showCard(CARD_COUNTING, false);
       
       
        481
       
       
       
       
        482
       
       
        }
       
       
        483
       
       
       
       
        484
       
       
        /**
       
       
        485
       
       
        * Show the introduction card
       
       
        486
       
       
        */
       
       
        487
       
       
        private void showIntroCard() {
       
       
        488
       
       
        Card c = new Card.Builder(this, CARD_INTRO)
       
       
        489
       
       
        .setTitle(getString(R.string.intro_title))
       
       
        490
       
       
        .setDescription(getString(R.string.intro_message))
       
       
        491
       
       
        .build(getActivity());
       
       
        492
       
       
        getCardStream().addCard(c, true);
       
       
        493
       
       
        }
       
       
        494
       
       
       
       
        495
       
       
        /**
       
       
        496
       
       
        * Show two registration cards, one for the step detector and counter sensors.
       
       
        497
       
       
        */
       
       
        498
       
       
        private void showRegisterCard() {
       
       
        499
       
       
        // Hide the counting and explanation cards
       
       
        500
       
       
        getCardStream().hideCard(CARD_BATCHING_DESCRIPTION);
       
       
        501
       
       
        getCardStream().hideCard(CARD_EXPLANATION);
       
       
        502
       
       
        getCardStream().hideCard(CARD_COUNTING);
       
       
        503
       
       
       
       
        504
       
       
        // Show two undismissable registration cards, one for each step sensor
       
       
        505
       
       
        getCardStream().showCard(CARD_REGISTER_DETECTOR, false);
       
       
        506
       
       
        getCardStream().showCard(CARD_REGISTER_COUNTER, false);
       
       
        507
       
       
        }
       
       
        508
       
       
       
       
        509
       
       
        /**
       
       
        510
       
       
        * Show the error card.
       
       
        511
       
       
        */
       
       
        512
       
       
        private void showErrorCard() {
       
       
        513
       
       
        getCardStream().showCard(CARD_NOBATCHSUPPORT, false);
       
       
        514
       
       
        }
       
       
        515
       
       
       
       
        516
       
       
        /**
       
       
        517
       
       
        * Initialise Cards.
       
       
        518
       
       
        */
       
       
        519
       
       
        private void initialiseCards() {
       
       
        520
       
       
        // Step counting
       
       
        521
       
       
        Card c = new Card.Builder(this, CARD_COUNTING)
       
       
        522
       
       
        .setTitle("Steps")
       
       
        523
       
       
        .setDescription("")
       
       
        524
       
       
        .addAction("Unregister Listener", ACTION_UNREGISTER, Card.ACTION_NEGATIVE)
       
       
        525
       
       
        .build(getActivity());
       
       
        526
       
       
        getCardStream().addCard(c);
       
       
        527
       
       
       
       
        528
       
       
        // Register step detector listener
       
       
        529
       
       
        c = new Card.Builder(this, CARD_REGISTER_DETECTOR)
       
       
        530
       
       
        .setTitle(getString(R.string.register_detector_title))
       
       
        531
       
       
        .setDescription(getString(R.string.register_detector_description))
       
       
        532
       
       
        .addAction(getString(R.string.register_0),
       
       
        533
       
       
        ACTION_REGISTER_DETECT_NOBATCHING, Card.ACTION_NEUTRAL)
       
       
        534
       
       
        .addAction(getString(R.string.register_5),
       
       
        535
       
       
        ACTION_REGISTER_DETECT_BATCHING_5s, Card.ACTION_NEUTRAL)
       
       
        536
       
       
        .addAction(getString(R.string.register_10),
       
       
        537
       
       
        ACTION_REGISTER_DETECT_BATCHING_10s, Card.ACTION_NEUTRAL)
       
       
        538
       
       
        .build(getActivity());
       
       
        539
       
       
        getCardStream().addCard(c);
       
       
        540
       
       
       
       
        541
       
       
        // Register step counter listener
       
       
        542
       
       
        c = new Card.Builder(this, CARD_REGISTER_COUNTER)
       
       
        543
       
       
        .setTitle(getString(R.string.register_counter_title))
       
       
        544
       
       
        .setDescription(getString(R.string.register_counter_description))
       
       
        545
       
       
        .addAction(getString(R.string.register_0),
       
       
        546
       
       
        ACTION_REGISTER_COUNT_NOBATCHING, Card.ACTION_NEUTRAL)
       
       
        547
       
       
        .addAction(getString(R.string.register_5),
       
       
        548
       
       
        ACTION_REGISTER_COUNT_BATCHING_5s, Card.ACTION_NEUTRAL)
       
       
        549
       
       
        .addAction(getString(R.string.register_10),
       
       
        550
       
       
        ACTION_REGISTER_COUNT_BATCHING_10s, Card.ACTION_NEUTRAL)
       
       
        551
       
       
        .build(getActivity());
       
       
        552
       
       
        getCardStream().addCard(c);
       
       
        553
       
       
       
       
        554
       
       
       
       
        555
       
       
        // Batching description
       
       
        556
       
       
        c = new Card.Builder(this, CARD_BATCHING_DESCRIPTION)
       
       
        557
       
       
        .setTitle(getString(R.string.batching_queue_title))
       
       
        558
       
       
        .setDescription(getString(R.string.batching_queue_description))
       
       
        559
       
       
        .addAction(getString(R.string.action_notagain),
       
       
        560
       
       
        ACTION_BATCHING_DESCRIPTION_DISMISS, Card.ACTION_POSITIVE)
       
       
        561
       
       
        .build(getActivity());
       
       
        562
       
       
        getCardStream().addCard(c);
       
       
        563
       
       
       
       
        564
       
       
        // Explanation
       
       
        565
       
       
        c = new Card.Builder(this, CARD_EXPLANATION)
       
       
        566
       
       
        .setDescription(getString(R.string.explanation_description))
       
       
        567
       
       
        .addAction(getString(R.string.action_notagain),
       
       
        568
       
       
        ACTION_EXPLANATION_DISMISS, Card.ACTION_POSITIVE)
       
       
        569
       
       
        .build(getActivity());
       
       
        570
       
       
        getCardStream().addCard(c);
       
       
        571
       
       
       
       
        572
       
       
        // Error
       
       
        573
       
       
        c = new Card.Builder(this, CARD_NOBATCHSUPPORT)
       
       
        574
       
       
        .setTitle(getString(R.string.error_title))
       
       
        575
       
       
        .setDescription(getString(R.string.error_nosensor))
       
       
        576
       
       
        .build(getActivity());
       
       
        577
       
       
        getCardStream().addCard(c);
       
       
        578
       
       
        }
       
       
        579
       
       
       
       
        580
       
       
        /**
       
       
        581
       
       
        * Returns the cached CardStreamFragment used to show cards.
       
       
        582
       
       
        *
       
       
        583
       
       
        * @return
       
       
        584
       
       
        */
       
       
        585
       
       
        private CardStreamFragment getCardStream() {
       
       
        586
       
       
        if (mCards == null) {
       
       
        587
       
       
        mCards = ((CardStream) getActivity()).getCardStream();
       
       
        588
       
       
        }
       
       
        589
       
       
        return mCards;
       
       
        590
       
       
        }
       
       
        591
       
       
       
       
        592
       
       
        }