/** Copyright 2015 Tim Engler, Rareventure LLC This file is part of Tiny Travel Tracker. Tiny Travel Tracker is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Tiny Travel Tracker is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Tiny Travel Tracker. If not, see <http://www.gnu.org/licenses/>. */ package com.rareventure.gps2; import java.io.DataOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.List; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteStatement; import android.net.wifi.ScanResult; import android.os.Looper; import com.rareventure.android.DbUtil; import com.rareventure.android.GpsReader; import com.rareventure.android.IntentTimer; import com.rareventure.android.ProcessThread; import com.rareventure.android.TestUtil; import com.rareventure.android.ThreadedBufferedOutputStream; import com.rareventure.android.WirelessAdapter; import com.rareventure.android.WriteConstants; import com.rareventure.gps2.bootup.GpsTrailerReceiver; import com.rareventure.gps2.database.cachecreator.GpsTrailerCacheCreator; public class GpsTrailerManager implements GpsReader.GpsProcessor, WirelessAdapter.Listener { private GpsReader gpsReader; private GpsTrailerDataHandler dataHandler; private GpsTrailerGpsStrategy strategy; private ProcessThread processThread; private DataOutputStream os; // private CompassDirectionCalculator compassDirectionCalculator; private WirelessAdapter wirelessAdapter; public GpsTrailerManager(File dataFile, Context ctx, String tag, Looper looper) throws FileNotFoundException { //TODO 4: deal with debugging crap TestUtil.modesToSuppress.add(WriteConstants.MODE_WRITE_SENSOR_DATA); //for saving data to a test file to replay later if(dataFile != null) { //the threaded buffer output stream guarantees the write won't block os = new DataOutputStream(new ThreadedBufferedOutputStream(2048,1024, new FileOutputStream(dataFile))); //os = new DataOutputStream(new FileOutputStream(dataFile)); } gpsReader = new GpsReader(os, ctx, this, tag, looper); // compassDirectionCalculator = new CompassDirectionCalculator(); dataHandler = new GpsTrailerDataHandler(); IntentTimer intentTimer = new IntentTimer(ctx, GpsTrailerReceiver.class); //TODO 3: it sucks passing os everywhere, and catching io exceptions and specifying a mode for everything. wah! strategy = new GpsTrailerGpsStrategy(os, gpsReader, intentTimer); processThread = new ProcessThread(ctx, tag, gpsReader); //co because I think this uses a lot of batteries //wirelessAdapter = new WirelessAdapter(ctx, this); } public void start() { strategy.start(); processThread.start(); } @Override public void processGpsData(double lon, double lat, double alt, long time) { strategy.gotReading(); dataHandler.processGpsData((int)Math.round(lon*1000000), (int)Math.round(lat*1000000), alt, time); //notify the cache creator that we got another point GpsTrailerCacheCreator localCacheCreator = GTG.cacheCreator; if(localCacheCreator != null) { synchronized(localCacheCreator) { localCacheCreator.notify(); } } if(wirelessAdapter != null) wirelessAdapter.doScan(); } public void shutdown() { strategy.shutdown(); processThread.notifyShutdown(); processThread.waitUntilShutdown(); if(wirelessAdapter != null) wirelessAdapter.shutdown(); if(os != null) try { os.close(); } catch (IOException e) { e.printStackTrace(); } } @Override public void notifyWifiScan(long timeMs, List<ScanResult> scanResults) { SQLiteDatabase db = GTG.db; SQLiteStatement stmt = DbUtil.createOrGetStatement(db, "insert into WIFI_SCAN_RESULT (time,ssid,bssid,capabilities,level,frequency) values (?,?,?,?,?,?)"); //it's a little faster in a transaction db.beginTransaction(); try { for(ScanResult sr : scanResults) { stmt.bindLong(1, timeMs); stmt.bindString(2, sr.SSID); stmt.bindString(3, sr.BSSID); stmt.bindString(4, sr.capabilities); stmt.bindLong(5, sr.level); stmt.bindLong(6, sr.frequency); stmt.execute(); } db.setTransactionSuccessful(); } finally { if(db.inTransaction()) db.endTransaction(); } } public void notifyWoken() { strategy.notifyWoken(); } }