Как обновить TextView на пользовательском интерфейсе из службы в AndroidStudio? - PullRequest
0 голосов
/ 07 сентября 2018

Для школьного проекта я пытаюсь создать приложение, которое использует датчик акселерометра моего телефона и вывод, если я стою, хожу или бегаю. У меня есть приложение, которое я пытаюсь изменить, чтобы оно соответствовало моим потребностям. Проблема в том, что я не понимаю, как я могу заставить сервис постоянно обновлять textView. Прямо сейчас он только обновляет textView всякий раз, когда я нажимаю «кнопку сбора». Так как я могу постоянно обновлять интерфейс? По сути, я хочу, чтобы эта строка кода [CollectorActivity.mCurrentLabel.setText (testLabel.get ((int) a));] непрерывно обновляла textView.

Вот код:

Моя деятельность:

public class CollectorActivity extends Activity {

private enum State {
    IDLE, COLLECTING, TRAINING, CLASSIFYING
};

private final String[] mLabels = { Globals.CLASS_LABEL_STANDING,
        Globals.CLASS_LABEL_WALKING, Globals.CLASS_LABEL_RUNNING,
        Globals.CLASS_LABEL_OTHER };

private RadioGroup radioGroup;
private final RadioButton[] radioBtns = new RadioButton[4];
private Intent mServiceIntent;
private File mFeatureFile;
public static TextView mCurrentLabel;

private State mState;
private Button btnDelete;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    radioGroup = (RadioGroup) findViewById(R.id.radioGroupLabels);
    radioBtns[0] = (RadioButton) findViewById(R.id.radioStanding);
    radioBtns[1] = (RadioButton) findViewById(R.id.radioWalking);
    radioBtns[2] = (RadioButton) findViewById(R.id.radioRunning);
    radioBtns[3] = (RadioButton) findViewById(R.id.radioOther);

    btnDelete = (Button) findViewById(R.id.btnDeleteData);
    mCurrentLabel = (TextView) findViewById(R.id.textView);

    mState = State.IDLE;
    mFeatureFile = new File(getExternalFilesDir(null),
            Globals.FEATURE_FILE_NAME);
    mServiceIntent = new Intent(this, SensorsService.class);
}

public void run() {

    CollectorActivity.mCurrentLabel.setText(SensorsService.y);
}

public void onCollectClicked(View view) {

    if (mState == State.IDLE) {
        mState = State.COLLECTING;
        ((Button) view).setText(R.string.ui_collector_button_stop_title);
        btnDelete.setEnabled(false);
        radioBtns[0].setEnabled(false);
        radioBtns[1].setEnabled(false);
        radioBtns[2].setEnabled(false);
        radioBtns[3].setEnabled(false);

        int acvitivtyId = radioGroup.indexOfChild(findViewById(radioGroup
                .getCheckedRadioButtonId()));
        String label = mLabels[acvitivtyId];

        Bundle extras = new Bundle();
        extras.putString(Globals.CLASS_LABEL_KEY, label);
        mServiceIntent.putExtras(extras);

        startService(mServiceIntent);

    } else if (mState == State.COLLECTING) {
        mState = State.IDLE;
        ((Button) view).setText(R.string.ui_collector_button_start_title);
        btnDelete.setEnabled(true);
        radioBtns[0].setEnabled(true);
        radioBtns[1].setEnabled(true);
        radioBtns[2].setEnabled(true);
        radioBtns[3].setEnabled(true);

        stopService(mServiceIntent);
        ((NotificationManager) getSystemService(NOTIFICATION_SERVICE)).cancelAll();
    }
}

public void onDeleteDataClicked(View view) {

    if (Environment.MEDIA_MOUNTED.equals(Environment
            .getExternalStorageState())) {
        if (mFeatureFile.exists()) {
            mFeatureFile.delete();
        }

        Toast.makeText(getApplicationContext(),
                R.string.ui_collector_toast_file_deleted,
                Toast.LENGTH_SHORT).show();
    }
}

@Override
public void onBackPressed() {

    if (mState == State.TRAINING) {
        return;
    } else if (mState == State.COLLECTING || mState == State.CLASSIFYING) {
        stopService(mServiceIntent);
        ((NotificationManager) getSystemService(NOTIFICATION_SERVICE))
                .cancel(Globals.NOTIFICATION_ID);
    }
    super.onBackPressed();
}

@Override
public void onDestroy() {
    // Stop the service and the notification.
    // Need to check whether the mSensorService is null or not.
    if (mState == State.TRAINING) {
        return;
    } else if (mState == State.COLLECTING || mState == State.CLASSIFYING) {
        stopService(mServiceIntent);
        ((NotificationManager) getSystemService(NOTIFICATION_SERVICE))
                .cancelAll();
    }
    finish();
    super.onDestroy();
}

}

Мой сервис:

 public class SensorsService extends Service implements SensorEventListener {

private static final int mFeatLen = Globals.ACCELEROMETER_BLOCK_CAPACITY + 2;

private File mFeatureFile;
private SensorManager mSensorManager;
private Sensor mAccelerometer;
private int mServiceTaskType;
private String mLabel;
private Instances mDataset;
private Attribute mClassAttribute;
private OnSensorChangedTask mAsyncTask;
private List<Double> testList = new ArrayList<Double>();
public static List<String> testLabel = new ArrayList<String>();
private TextView classLabel;

private static ArrayBlockingQueue<Double> mAccBuffer;
public static final DecimalFormat mdf = new DecimalFormat("#.##");
public static String y = "";
public double a;

@Override
public void onCreate() {
    super.onCreate();

    mAccBuffer = new ArrayBlockingQueue<Double>(
            Globals.ACCELEROMETER_BUFFER_CAPACITY);
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {

    mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
    mAccelerometer = mSensorManager
            .getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION);

    mSensorManager.registerListener(this, mAccelerometer,
            SensorManager.SENSOR_DELAY_FASTEST);

    Bundle extras = intent.getExtras();
    mLabel = extras.getString(Globals.CLASS_LABEL_KEY);

    mFeatureFile = new File(getExternalFilesDir(null), Globals.FEATURE_FILE_NAME);
    Log.d(Globals.TAG, mFeatureFile.getAbsolutePath());

    mServiceTaskType = Globals.SERVICE_TASK_TYPE_COLLECT;

    // Create the container for attributes
    ArrayList<Attribute> allAttr = new ArrayList<Attribute>();

    // Adding FFT coefficient attributes
    DecimalFormat df = new DecimalFormat("0000");

    for (int i = 0; i < Globals.ACCELEROMETER_BLOCK_CAPACITY; i++) {
        allAttr.add(new Attribute(Globals.FEAT_FFT_COEF_LABEL + df.format(i)));
    }
    // Adding the max feature
    allAttr.add(new Attribute(Globals.FEAT_MAX_LABEL));

    // Declare a nominal attribute along with its candidate values
    ArrayList<String> labelItems = new ArrayList<String>(3);
    labelItems.add(Globals.CLASS_LABEL_STANDING);
    labelItems.add(Globals.CLASS_LABEL_WALKING);
    labelItems.add(Globals.CLASS_LABEL_RUNNING);
    labelItems.add(Globals.CLASS_LABEL_OTHER);

    testLabel.add(Globals.CLASS_LABEL_STANDING);
    testLabel.add(Globals.CLASS_LABEL_WALKING);
    testLabel.add(Globals.CLASS_LABEL_RUNNING);

    mClassAttribute = new Attribute(Globals.CLASS_LABEL_KEY, labelItems);
    allAttr.add(mClassAttribute);

    // Construct the dataset with the attributes specified as allAttr and
    // capacity 10000
    mDataset = new Instances(Globals.FEAT_SET_NAME, allAttr, Globals.FEATURE_SET_CAPACITY);

    // Set the last column/attribute (standing/walking/running) as the class
    // index for classification
    mDataset.setClassIndex(mDataset.numAttributes() - 1);

    Intent i = new Intent(this, CollectorActivity.class);
    // Read:
    // http://developer.android.com/guide/topics/manifest/activity-element.html#lmode
    // IMPORTANT!. no re-create activity
    i.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);

    PendingIntent pi = PendingIntent.getActivity(this, 0, i, 0);

    Notification notification = new Notification.Builder(this)
            .setContentTitle(
                    getApplicationContext().getString(
                            R.string.ui_sensor_service_notification_title))
            .setContentText(
                    getResources()
                            .getString(
                                    R.string.ui_sensor_service_notification_content))
            .setSmallIcon(R.drawable.greend).setContentIntent(pi).build();
    NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    notification.flags = notification.flags
            | Notification.FLAG_ONGOING_EVENT;
    notificationManager.notify(0, notification);


    mAsyncTask = new OnSensorChangedTask();
    mAsyncTask.execute();


    return START_NOT_STICKY;
}

@Override
public void onDestroy() {
    mAsyncTask.cancel(true);
    try {
        Thread.sleep(100);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    mSensorManager.unregisterListener(this);
    Log.i("","");
    super.onDestroy();

}

private class OnSensorChangedTask extends AsyncTask<Void, Void, Void> {
    @Override
    protected Void doInBackground(Void... arg0) {

        Instance inst = new DenseInstance(mFeatLen);
        inst.setDataset(mDataset);
        Instance inst2 = new DenseInstance(65);
        int blockSize = 0;
        FFT fft = new FFT(Globals.ACCELEROMETER_BLOCK_CAPACITY);
        double[] accBlock = new double[Globals.ACCELEROMETER_BLOCK_CAPACITY];
        double[] re = accBlock;
        double[] im = new double[Globals.ACCELEROMETER_BLOCK_CAPACITY];

        double max = Double.MIN_VALUE;

        while (true) {
            try {
                // need to check if the AsyncTask is cancelled or not in the while loop
                if (isCancelled () == true)
                {
                    return null;
                }

                // Dumping buffer
                accBlock[blockSize++] = mAccBuffer.take().doubleValue();


                if (blockSize == Globals.ACCELEROMETER_BLOCK_CAPACITY) {
                    blockSize = 0;
                    testList = new ArrayList<Double>();

                    // time = System.currentTimeMillis();
                    max = .0;
                    for (double val : accBlock) {
                        if (max < val) {
                            max = val;
                        }
                    }

                    fft.fft(re, im);

                    for (int i = 0; i < re.length; i++) {
                        double mag = Math.sqrt(re[i] * re[i] + im[i]
                                * im[i]);
                        inst.setValue(i, mag);
                        testList.add(i,mag);
                        im[i] = .0; // Clear the field
                    }

                    // Append max after frequency component
                    inst.setValue(Globals.ACCELEROMETER_BLOCK_CAPACITY, max);
                    inst2.setValue(Globals.ACCELEROMETER_BLOCK_CAPACITY, max);
                    testList.add(max);
                     a = WekaClassifier.classify(testList.toArray());
                     testLabel.get((int) a);
                     y = testLabel.get(0);
                     CollectorActivity.mCurrentLabel.setText(testLabel.get((int) a));
                    Toast.makeText(getApplicationContext(), y,
                            Toast.LENGTH_SHORT).show();


                    inst.setValue(mClassAttribute, mLabel);
                    mDataset.add(inst);
                    Log.i("new instance", mDataset.size() + "");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    protected void onCancelled() {

        Log.e("123", mDataset.size()+"");

        if (mServiceTaskType == Globals.SERVICE_TASK_TYPE_CLASSIFY) {
            super.onCancelled();
            return;
        }
        Log.i("in the loop","still in the loop cancelled");
        String toastDisp;

        if (mFeatureFile.exists()) {

            // merge existing and delete the old dataset
            DataSource source;
            try {
                // Create a datasource from mFeatureFile where
                // mFeatureFile = new File(getExternalFilesDir(null),
                // "features.arff");
                source = new DataSource(new FileInputStream(mFeatureFile));
                // Read the dataset set out of this datasource
                Instances oldDataset = source.getDataSet();
                oldDataset.setClassIndex(mDataset.numAttributes() - 1);
                // Sanity checking if the dataset format matches.
                if (!oldDataset.equalHeaders(mDataset)) {
                    // Log.d(Globals.TAG,
                    // oldDataset.equalHeadersMsg(mDataset));
                    throw new Exception(
                            "The two datasets have different headers:\n");
                }

                // Move all items over manually
                for (int i = 0; i < mDataset.size(); i++) {
                    oldDataset.add(mDataset.get(i));
                }

                mDataset = oldDataset;
                // Delete the existing old file.
                mFeatureFile.delete();
                Log.i("delete","delete the file");
            } catch (Exception e) {
                e.printStackTrace();
            }
            toastDisp = getString(R.string.ui_sensor_service_toast_success_file_updated);

        } else {
            toastDisp = getString(R.string.ui_sensor_service_toast_success_file_created)   ;
        }
        Log.i("save","create saver here");
        // create new Arff file
        ArffSaver saver = new ArffSaver();
        // Set the data source of the file content
        saver.setInstances(mDataset);
        Log.e("1234", mDataset.size()+"");
        try {
            // Set the destination of the file.
            // mFeatureFile = new File(getExternalFilesDir(null),
            // "features.arff");
            saver.setFile(mFeatureFile);
            // Write into the file
            saver.writeBatch();
            Log.i("batch","write batch here");
            Toast.makeText(getApplicationContext(), toastDisp,
                    Toast.LENGTH_SHORT).show();
        } catch (IOException e) {
            toastDisp = getString(R.string.ui_sensor_service_toast_error_file_saving_failed);
            e.printStackTrace();
        }

        Log.i("toast","toast here");
        super.onCancelled();
    }

}

public void onSensorChanged(SensorEvent event) {

    if (event.sensor.getType() == Sensor.TYPE_LINEAR_ACCELERATION) {

        double m = Math.sqrt(event.values[0] * event.values[0]
                + event.values[1] * event.values[1] + event.values[2]
                * event.values[2]);

        // Inserts the specified element into this queue if it is possible
        // to do so immediately without violating capacity restrictions,
        // returning true upon success and throwing an IllegalStateException
        // if no space is currently available. When using a
        // capacity-restricted queue, it is generally preferable to use
        // offer.

        try {
            mAccBuffer.add(new Double(m));
        } catch (IllegalStateException e) {

            // Exception happens when reach the capacity.
            // Doubling the buffer. ListBlockingQueue has no such issue,
            // But generally has worse performance
            ArrayBlockingQueue<Double> newBuf = new ArrayBlockingQueue<Double>(
                    mAccBuffer.size() * 2);

            mAccBuffer.drainTo(newBuf);
            mAccBuffer = newBuf;
            mAccBuffer.add(new Double(m));


        }
    }
}

public void onAccuracyChanged(Sensor sensor, int accuracy) {
}

@Override
public IBinder onBind(Intent intent) {
    return null;
}

}

...