Java tutorial
package org.starfishrespect.myconsumption.android.ui; import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.Intent; import android.os.AsyncTask; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.*; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.starfishrespect.myconsumption.android.R; import org.starfishrespect.myconsumption.android.SingleInstance; import org.starfishrespect.myconsumption.android.adapters.SensorListAdapter; import org.starfishrespect.myconsumption.android.adapters.SpinnerDateAdapter; import org.starfishrespect.myconsumption.android.adapters.SpinnerFrequencyAdapter; import org.starfishrespect.myconsumption.android.dao.SensorValuesDao; import org.starfishrespect.myconsumption.android.data.FrequencyData; import org.starfishrespect.myconsumption.android.data.SensorData; import org.starfishrespect.myconsumption.android.data.SpinnerDateData; import org.springframework.http.converter.FormHttpMessageConverter; import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.web.client.RestTemplate; import org.starfishrespect.myconsumption.android.events.DateChangedEvent; import org.starfishrespect.myconsumption.android.events.FragmentsReadyEvent; import org.starfishrespect.myconsumption.android.events.ReloadUserEvent; import org.starfishrespect.myconsumption.android.events.UpdateMovingAverageEvent; import org.starfishrespect.myconsumption.android.util.CryptoUtils; import org.starfishrespect.myconsumption.android.util.MiscFunctions; import java.sql.SQLException; import java.text.SimpleDateFormat; import java.util.*; import de.greenrobot.event.EventBus; /** * Fragment that contains the settings of the graph (which dataset to show, which range, * colors) and allows to edit them (color, sensor settings, delete) * * S23Y (2015). Licensed under the Apache License, Version 2.0. * Adapted from Patrick by Thibaud Ledent */ public class ChartChoiceFragment extends Fragment { protected ChartActivity mActivity; private ListView listViewSensor; private LinearLayout mLinearLayout = null; private TextView mTextView = null; private SensorListAdapter sensorListAdapter; private Spinner spinnerDate, spinnerFrequency, spinnerPrecision; private List<FrequencyData> frequencies; private List<SensorData> sensors = null; private SeekBar seekBar; private int lastLongClickItem = -1; public static final int REQUEST_EDIT_SENSOR = 43; private int seekBarPosition; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_chart_choice, container, false); // Register to the EventBus EventBus.getDefault().register(this); listViewSensor = (ListView) view.findViewById(R.id.listViewSensors); mLinearLayout = (LinearLayout) view.findViewById(R.id.linearLayoutDateSelectionItems); mTextView = (TextView) view.findViewById(R.id.textViewUsername); spinnerDate = (Spinner) view.findViewById(R.id.spinnerDate); spinnerFrequency = (Spinner) view.findViewById(R.id.spinnerFrequency); spinnerPrecision = (Spinner) view.findViewById(R.id.spinnerPrecision); seekBar = (SeekBar) view.findViewById(R.id.seekBar); seekBarPosition = 0; seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { // Called when the slider moves to another value @Override public void onProgressChanged(SeekBar seekBar, int progresValue, boolean fromUser) { seekBarPosition = progresValue; } // Called when you start moving the slider @Override public void onStartTrackingTouch(SeekBar seekBar) { } // Called when it seems that you are done moving the slider @Override public void onStopTrackingTouch(SeekBar seekBar) { // Tell ChartViewFragment to update the graph EventBus.getDefault().post(new UpdateMovingAverageEvent(seekBarPosition)); } }); listViewSensor.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { @Override public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { lastLongClickItem = position; PopupMenu popup = new PopupMenu(mActivity, view); popup.inflate(R.menu.menu_sensor_dropdown); popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { switch (item.getItemId()) { case R.id.action_delete_sensor: if (!MiscFunctions.isOnline(mActivity)) { MiscFunctions.makeOfflineDialog(mActivity).show(); return false; } deleteSensor(lastLongClickItem); break; case R.id.action_edit_sensor: if (!MiscFunctions.isOnline(mActivity)) { MiscFunctions.makeOfflineDialog(mActivity).show(); return false; } editSensor(lastLongClickItem); break; } return false; } }); popup.show(); return false; } }); return view; } @Override public void onStart() { super.onStart(); EventBus.getDefault().post(new FragmentsReadyEvent(this.getClass(), true)); } @Override public void onAttach(Activity activity) { super.onAttach(activity); mActivity = (ChartActivity) activity; } @Override public void onDestroy() { // Unregister to the EventBus EventBus.getDefault().unregister(this); super.onDestroy(); } /** * Triggered when the user wants to reload data. * @param event A ReloadUser event */ public void onEvent(ReloadUserEvent event) { setUser(); refreshSpinnerFrequencies(); refreshSpinnerPrecision(); if ((SingleInstance.getUserController().getUser().getSensors().size() == 0) || event.refreshDataFromServer()) { refreshSpinnerDate(); } else { refreshSpinnerDate(); EventBus.getDefault().post(new DateChangedEvent(getDate(), getDateDelay(), getValueDelay())); } } private void editSensor(int index) { SensorData sensor = sensors.get(index); Intent intent = new Intent(mActivity, AddSensorActivity.class); intent.putExtra("edit", sensor.getSensorId()); startActivityForResult(intent, REQUEST_EDIT_SENSOR); } private void deleteSensor(int index) { AlertDialog.Builder builder = new AlertDialog.Builder(mActivity); builder.setTitle(R.string.dialog_title_confirmation); builder.setMessage( String.format(getResources().getString(R.string.dialog_message_confirmation_delete_sensor), sensors.get(lastLongClickItem).getName())); builder.setNegativeButton(R.string.button_no, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); builder.setPositiveButton(R.string.button_yes, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { new AsyncTask<Void, Boolean, Void>() { @Override protected Void doInBackground(Void... params) { RestTemplate template = new RestTemplate(); HttpHeaders httpHeaders = CryptoUtils.createHeadersCurrentUser(); template.getMessageConverters().add(new FormHttpMessageConverter()); template.getMessageConverters().add(new StringHttpMessageConverter()); String url = SingleInstance.getServerUrl() + "users/" + SingleInstance.getUserController().getUser().getName() + "/sensor/" + sensors.get(lastLongClickItem).getSensorId(); template.exchange(url, HttpMethod.DELETE, new HttpEntity<>(httpHeaders), String.class); try { SingleInstance.getDatabaseHelper().getSensorDao() .delete(sensors.get(lastLongClickItem)); new SensorValuesDao(SingleInstance.getDatabaseHelper()) .removeSensor(sensors.get(lastLongClickItem).getSensorId()); } catch (SQLException e) { publishProgress(false); } publishProgress(true); return null; } @Override protected void onProgressUpdate(Boolean... values) { for (boolean b : values) { if (b) { new AlertDialog.Builder(mActivity).setTitle(R.string.dialog_title_information) .setMessage(R.string.dialog_message_information_sensor_deleted) .setPositiveButton(R.string.button_ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { EventBus.getDefault().post(new ReloadUserEvent(false)); dialog.dismiss(); } }) .show(); } else { new AlertDialog.Builder(mActivity).setTitle(R.string.dialog_title_information) .setMessage("unknown error while deleting from DB").setPositiveButton( R.string.button_ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }) .show(); } } } }.execute(); dialog.dismiss(); } }); builder.show(); } public void setUser() { if (mTextView != null) mTextView.setText(SingleInstance.getUserController().getUser().getName()); sensors = SingleInstance.getUserController().getUser().getSensors(); sensorListAdapter = new SensorListAdapter(mActivity, sensors); if (listViewSensor != null) listViewSensor.setAdapter(sensorListAdapter); if (sensors.size() == 0) { if (mLinearLayout != null) mLinearLayout.setVisibility(View.GONE); } } public void refreshSpinnerFrequencies() { frequencies = new ArrayList<>(); frequencies.add(new FrequencyData("Day", FrequencyData.DELAY_DAY)); frequencies.add(new FrequencyData("Week", FrequencyData.DELAY_WEEK)); frequencies.add(new FrequencyData("Month", FrequencyData.DELAY_MONTH)); frequencies.add(new FrequencyData("Year", FrequencyData.DELAY_YEAR)); frequencies.add(new FrequencyData("Everything", FrequencyData.DELAY_EVERYTHING)); spinnerFrequency.setAdapter(new SpinnerFrequencyAdapter(mActivity, frequencies)); spinnerFrequency.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { refreshSpinnerPrecision(); refreshSpinnerDate(); } @Override public void onNothingSelected(AdapterView<?> parent) { } }); } public void refreshSpinnerPrecision() { int precision = frequencies.get(spinnerFrequency.getSelectedItemPosition()).getDelay(); ArrayList<FrequencyData> precisionData = new ArrayList<>(); switch (precision) { case FrequencyData.DELAY_DAY: precisionData.add(new FrequencyData("Minute", FrequencyData.DELAY_MINUTE)); precisionData.add(new FrequencyData("5 minutes", FrequencyData.DELAY_FIVE_MINUTES)); precisionData.add(new FrequencyData("15 minutes", FrequencyData.DELAY_15MIN)); precisionData.add(new FrequencyData("Hour", FrequencyData.DELAY_HOUR)); break; case FrequencyData.DELAY_WEEK: precisionData.add(new FrequencyData("15 minutes", FrequencyData.DELAY_15MIN)); precisionData.add(new FrequencyData("Hour", FrequencyData.DELAY_HOUR)); precisionData.add(new FrequencyData("Day", FrequencyData.DELAY_DAY)); break; case FrequencyData.DELAY_MONTH: precisionData.add(new FrequencyData("Hour", FrequencyData.DELAY_HOUR)); precisionData.add(new FrequencyData("Day", FrequencyData.DELAY_DAY)); break; case FrequencyData.DELAY_YEAR: precisionData.add(new FrequencyData("Day", FrequencyData.DELAY_DAY)); precisionData.add(new FrequencyData("Week", FrequencyData.DELAY_WEEK)); precisionData.add(new FrequencyData("Month", FrequencyData.DELAY_MONTH)); break; case FrequencyData.DELAY_EVERYTHING: precisionData.add(new FrequencyData("Minute", FrequencyData.DELAY_MINUTE)); precisionData.add(new FrequencyData("5 minutes", FrequencyData.DELAY_FIVE_MINUTES)); precisionData.add(new FrequencyData("15 minutes", FrequencyData.DELAY_15MIN)); precisionData.add(new FrequencyData("Hour", FrequencyData.DELAY_HOUR)); precisionData.add(new FrequencyData("Day", FrequencyData.DELAY_DAY)); precisionData.add(new FrequencyData("Week", FrequencyData.DELAY_WEEK)); precisionData.add(new FrequencyData("Month", FrequencyData.DELAY_MONTH)); precisionData.add(new FrequencyData("Year", FrequencyData.DELAY_YEAR)); break; default: precisionData.add(new FrequencyData("Minute", FrequencyData.DELAY_MINUTE)); break; } spinnerPrecision.setOnItemSelectedListener(null); spinnerPrecision.setAdapter(new SpinnerFrequencyAdapter(mActivity, precisionData)); if (precision == FrequencyData.DELAY_EVERYTHING) { spinnerPrecision.setSelection(precisionData.size() - 2); } spinnerPrecision.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { if (spinnerDate.getCount() == 0) { return; } FrequencyData f = frequencies.get(spinnerFrequency.getSelectedItemPosition()); FrequencyData precision = (FrequencyData) spinnerPrecision.getSelectedItem(); if (precision != null) EventBus.getDefault() .post(new DateChangedEvent(((SpinnerDateData) spinnerDate.getSelectedItem()).getDate(), f.getDelay(), precision.getDelay())); } @Override public void onNothingSelected(AdapterView<?> parent) { } }); } public void refreshSpinnerDate() { if (SingleInstance.getUserController().getUser() != null && SingleInstance.getUserController().getUser().getSensors().size() == 0) { mLinearLayout.setVisibility(View.GONE); return; } long start = Long.MAX_VALUE; long end = 0; for (SensorData sensor : SingleInstance.getUserController().getUser().getSensors()) { if (start > sensor.getFirstLocalValue().getTime()) { start = sensor.getFirstLocalValue().getTime(); } if (end < sensor.getLastLocalValue().getTime()) { end = sensor.getLastLocalValue().getTime(); } start = start - start % 86400000L; end = end - end % 86400000L; } final List<SpinnerDateData> dates = new ArrayList<>(); int precision = frequencies.get(spinnerFrequency.getSelectedItemPosition()).getDelay(); SimpleDateFormat formatter = null; if (precision == FrequencyData.DELAY_EVERYTHING) { dates.add(new SpinnerDateData(new Date(0), "Everything")); } else if (precision == FrequencyData.DELAY_MONTH) { formatter = new SimpleDateFormat("MMMM yyyy"); Calendar next = new GregorianCalendar(); next.setTimeInMillis(start); next.set(Calendar.DAY_OF_MONTH, 1); start = next.getTimeInMillis(); } else if (precision == FrequencyData.DELAY_YEAR) { formatter = new SimpleDateFormat("yyyy"); Calendar next = new GregorianCalendar(); next.setTimeInMillis(start); next.set(Calendar.DAY_OF_MONTH, 1); next.set(Calendar.MONTH, Calendar.JANUARY); start = next.getTimeInMillis(); } else { formatter = new SimpleDateFormat("dd MMMM yyyy"); } if (start == 0) { mLinearLayout.setVisibility(View.GONE); return; } long cur = start; while (cur <= end && precision != FrequencyData.DELAY_EVERYTHING) { Date d = new Date(cur); dates.add(new SpinnerDateData(d, formatter.format(d))); switch (precision) { case FrequencyData.DELAY_MONTH: { Calendar next = new GregorianCalendar(); next.setTimeInMillis(cur); next.add(Calendar.MONTH, 1); cur = next.getTimeInMillis(); break; } case FrequencyData.DELAY_YEAR: { Calendar next = new GregorianCalendar(); next.setTimeInMillis(cur); next.add(Calendar.YEAR, 1); cur = next.getTimeInMillis(); break; } case FrequencyData.DELAY_MINUTE: case FrequencyData.DELAY_DAY: case FrequencyData.DELAY_HOUR: case FrequencyData.DELAY_WEEK: default: cur += (long) precision * 1000; } } spinnerDate.setOnItemSelectedListener(null); //spinnerDate.setAdapter(new SpinnerDateAdapter(getActivity(), dates)); spinnerDate.setAdapter(new SpinnerDateAdapter(mActivity, dates)); spinnerDate.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { FrequencyData f = frequencies.get(spinnerFrequency.getSelectedItemPosition()); FrequencyData precision = (FrequencyData) spinnerPrecision.getSelectedItem(); if (precision != null) EventBus.getDefault().post(new DateChangedEvent(dates.get(position).getDate(), f.getDelay(), precision.getDelay())); } @Override public void onNothingSelected(AdapterView<?> parent) { } }); spinnerDate.setSelection(dates.size() - 1); mLinearLayout.setVisibility(View.VISIBLE); } public int getSmoothingValue() { return seekBarPosition; } public Date getDate() { if (spinnerDate.getSelectedItemPosition() < 0) { return null; } return ((SpinnerDateData) spinnerDate.getSelectedItem()).getDate(); } public int getDateDelay() { FrequencyData f = frequencies.get(spinnerFrequency.getSelectedItemPosition()); return f.getDelay(); } public int getValueDelay() { FrequencyData f = (FrequencyData) spinnerPrecision.getSelectedItem(); if (f != null) { return f.getDelay(); } else { return FrequencyData.DELAY_MINUTE; } } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == REQUEST_EDIT_SENSOR && resultCode == Activity.RESULT_OK) { mActivity.refreshData(); return; } super.onActivityResult(requestCode, resultCode, data); } }