package com.androsz.electricsleepbeta.content; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayList; import java.util.List; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.net.Uri; import com.androsz.electricsleepbeta.app.SettingsActivity; import com.androsz.electricsleepbeta.app.SleepMonitoringService; import com.androsz.electricsleepbeta.db.SleepSession; import com.androsz.electricsleepbeta.util.PointD; public class SaveSleepReceiver extends BroadcastReceiver { public static final String EXTRA_IO_EXCEPTION = "IOException"; public static final String EXTRA_NOTE = "note"; public static final String EXTRA_RATING = "rating"; public static final String EXTRA_URI = "uri"; public static final String EXTRA_SUCCESS = "success"; public static final String SAVE_SLEEP_COMPLETED = "com.androsz.electricsleepbeta.SAVE_SLEEP_COMPLETED"; @Override public void onReceive(final Context context, final Intent intent) { new Thread(new Runnable() { @Override public void run() { final float alarm = intent.getFloatExtra(StartSleepReceiver.EXTRA_ALARM, SettingsActivity.DEFAULT_ALARM_SENSITIVITY); final String name = intent.getStringExtra(SleepMonitoringService.EXTRA_NAME); final int rating = intent.getIntExtra(EXTRA_RATING, 5); final String note = intent.getStringExtra(EXTRA_NOTE); FileInputStream fis; // RandomAccessFile raFile; List<PointD> originalData = null; try { final File dataFile = context .getFileStreamPath(SleepMonitoringService.SLEEP_DATA); // raFile = new RandomAccessFile(dataFile, "r"); fis = context.openFileInput(SleepMonitoringService.SLEEP_DATA); final long length = dataFile.length(); final int chunkSize = 16; if (length % chunkSize != 0) { context.sendBroadcast(new Intent(SAVE_SLEEP_COMPLETED).putExtra( EXTRA_IO_EXCEPTION, "corrupt file")); return; } originalData = new ArrayList<PointD>((int) (length / chunkSize / 2)); if (length >= chunkSize) { final byte[] wholeFile = new byte[(int) length]; final byte[] buffer = new byte[8192]; int bytesRead = 0; int dstPos = 0; while ((bytesRead = fis.read(buffer)) != -1) { System.arraycopy(buffer, 0, wholeFile, dstPos, bytesRead); dstPos += bytesRead; } fis.close(); final byte[] chunk = new byte[chunkSize]; for (int i = 0; i < wholeFile.length; i += chunkSize) { System.arraycopy(wholeFile, i, chunk, 0, chunkSize); originalData.add(PointD.fromByteArray(chunk)); } } } catch (final FileNotFoundException e) { context.sendBroadcast(new Intent(SAVE_SLEEP_COMPLETED).putExtra( EXTRA_IO_EXCEPTION, e.getMessage())); return; } catch (final IOException e) { context.sendBroadcast(new Intent(SAVE_SLEEP_COMPLETED).putExtra( EXTRA_IO_EXCEPTION, e.getMessage())); return; } context.deleteFile(SleepMonitoringService.SLEEP_DATA); final int numberOfPointsOriginal = originalData.size(); // List<Double> mX = (List<Double>) intent // .getSerializableExtra("currentSeriesX"); // List<Double> mY = (List<Double>) intent // .getSerializableExtra("currentSeriesY"); if (numberOfPointsOriginal == 0) { context.sendBroadcast(new Intent(SAVE_SLEEP_COMPLETED)); return; } final int numberOfDesiredGroupedPoints = SleepMonitoringService.MAX_POINTS_IN_A_GRAPH; // numberOfDesiredGroupedPoints = numberOfPointsOriginal > // numberOfDesiredGroupedPoints ? numberOfDesiredGroupedPoints // : numberOfPointsOriginal; Uri createdUri = null; if (numberOfDesiredGroupedPoints <= numberOfPointsOriginal) { final int pointsPerGroup = numberOfPointsOriginal / numberOfDesiredGroupedPoints + 1; final List<PointD> lessDetailedData = new ArrayList<PointD>( numberOfDesiredGroupedPoints); int numberOfPointsInThisGroup = pointsPerGroup; double maxYForThisGroup; double totalForThisGroup; int numberOfSpikes = 0; int numberOfConsecutiveNonSpikes = 0; long timeOfFirstSleep = 0; for (int i = 0; i < numberOfDesiredGroupedPoints; i++) { maxYForThisGroup = 0; totalForThisGroup = 0; final int startIndexForThisGroup = i * pointsPerGroup; for (int j = 0; j < pointsPerGroup; j++) { try { final double currentY = originalData .get(startIndexForThisGroup + j).y; if (currentY > maxYForThisGroup) { maxYForThisGroup = currentY; } totalForThisGroup += currentY; } catch (final IndexOutOfBoundsException ioobe) { // lower the number of points // (and thereby signify that we are done) numberOfPointsInThisGroup = j - 1; break; } } final double averageForThisGroup = totalForThisGroup / numberOfPointsInThisGroup; if (numberOfPointsInThisGroup < pointsPerGroup) { // we are done final int lastIndex = numberOfPointsOriginal - 1; lessDetailedData.add(originalData.get(lastIndex)); break; } else { if (maxYForThisGroup < alarm) { maxYForThisGroup = averageForThisGroup; if (timeOfFirstSleep == 0 && ++numberOfConsecutiveNonSpikes > 4) { final int lastIndex = lessDetailedData.size() - 1; timeOfFirstSleep = Math.round(lessDetailedData.get(lastIndex).x); } } else { numberOfConsecutiveNonSpikes = 0; numberOfSpikes++; } lessDetailedData.add(new PointD(originalData .get(startIndexForThisGroup).x, maxYForThisGroup)); } } final long endTime = Math.round(lessDetailedData.get(lessDetailedData.size() - 1).x); final long startTime = Math.round(lessDetailedData.get(0).x); final SleepSession session = new SleepSession(startTime, endTime, lessDetailedData, SettingsActivity.DEFAULT_MIN_SENSITIVITY, alarm, rating, endTime - startTime, numberOfSpikes, timeOfFirstSleep, note); createdUri = context.getContentResolver().insert(SleepSession.CONTENT_URI, session.toContentValues()); } else { final long endTime = Math.round(originalData.get(numberOfPointsOriginal - 1).x); final long startTime = Math.round(originalData.get(0).x); int numberOfSpikes = 0; int numberOfConsecutiveNonSpikes = 0; long timeOfFirstSleep = 0; for (int i = 0; i < numberOfPointsOriginal; i++) { final double currentY = originalData.get(i).y; if (currentY < alarm) { if (timeOfFirstSleep == 0 && ++numberOfConsecutiveNonSpikes > 4) { final int lastIndex = originalData.size() - 1; timeOfFirstSleep = Math.round(originalData.get(lastIndex).x); } } else { numberOfConsecutiveNonSpikes = 0; numberOfSpikes++; } } final SleepSession session = new SleepSession( startTime, endTime, originalData, SettingsActivity.DEFAULT_MIN_SENSITIVITY, alarm, rating, endTime - startTime, numberOfSpikes, timeOfFirstSleep, note); createdUri = context.getContentResolver().insert(SleepSession.CONTENT_URI, session.toContentValues()); } final Intent saveSleepCompletedIntent = new Intent(SAVE_SLEEP_COMPLETED); saveSleepCompletedIntent.putExtra(EXTRA_SUCCESS, true); saveSleepCompletedIntent.putExtra(EXTRA_URI, createdUri.toString()); context.sendBroadcast(saveSleepCompletedIntent); } }).start(); } }