package de.graeb.adsbsniffer; import android.content.Context; import android.content.SharedPreferences; import android.database.sqlite.SQLiteDatabase; import android.location.Location; import android.os.Environment; import android.preference.PreferenceManager; import android.util.Log; import android.widget.Toast; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.GooglePlayServicesUtil; import com.google.android.gms.location.LocationListener; import java.io.File; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Iterator; import java.util.LinkedList; import de.graeb.adsbsniffer.adbsreceiver.GNSReceiver; import de.graeb.adsbsniffer.adbsreceiver.Packet; import de.graeb.adsbsniffer.adbsreceiver.exceptions.NoUsbDeviceFound; /** * Singleton used for Recording ADS-B Messages */ public class Recorder implements SharedPreferences.OnSharedPreferenceChangeListener { private static Recorder instance = null; private final Context context; private int timeoutFlight; private GNSReceiver gns = null; private DatabaseHelper recordingDb = null; private String currentRecording = null; private RecordingStatistics recordingStatistics; private boolean positionTracking; private Location lastLocation = null; private LocationTracking locationTracking = null; private boolean storeDatabaseExtern; private LinkedList<Packet> packetBuffer1; private LinkedList<Long> packetBuffer2; Recorder(final Context context) { this.context = context; instance = this; SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); preferences.registerOnSharedPreferenceChangeListener(this); reattach(); recordingStatistics = new RecordingStatistics(timeoutFlight, recordingDb); } public static Recorder getInstance() { return instance; } public void startRecording() { setUp(); packetBuffer1 = new LinkedList<>(); packetBuffer2 = new LinkedList<>(); // create filename SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH-mm"); String date = dateFormat.format(new Date()); String prefix = null; if (storeDatabaseExtern) { File directory = new File(Environment.getExternalStorageDirectory(), "ADSB-Sniffer"); if (!directory.exists()) { directory.mkdirs(); } prefix = directory.getAbsolutePath(); } currentRecording = (prefix == null?"":prefix + "/") + date + ".sqlite3"; recordingDb = new DatabaseHelper(context, currentRecording); recordingStatistics = new RecordingStatistics(timeoutFlight, recordingDb); // check if gps tracking enabled if (positionTracking) { int resp = GooglePlayServicesUtil.isGooglePlayServicesAvailable(context); if (resp == ConnectionResult.SUCCESS) { locationTracking = new LocationTracking(context, new LocationListener() { @Override public void onLocationChanged(Location location) { lastLocation = location; if (recordingDb != null) { recordingDb.storePosition(location); } } }); } else { Toast.makeText(context, "Google Play Service Error " + resp, Toast.LENGTH_LONG) .show(); } } } /** * Tries to connect to a usb receiver * <p /> * The USB device lost the connection and was inserted again * The current recording will be continued. */ public void reattach () { try { gns = new GNSReceiver(context, new GNSReceiver.PacketReceivedHandler() { @Override public void incoming(Packet packet) { synchronized (Recorder.this) { if (recordingDb != null) { long id = recordingStatistics.add(packet); if (packet.isAdsb) { packetBuffer1.add(packet); packetBuffer2.add(id); if (packetBuffer1.size() > 100) { flushPacketBuffer(); } } } } } }); setUp(); } catch (NoUsbDeviceFound e) { Toast.makeText(context, context.getText(R.string.no_device_found), Toast.LENGTH_LONG) .show(); } } private synchronized void flushPacketBuffer() { final Iterator<Packet> iterator1 = packetBuffer1.iterator(); final Iterator<Long> iterator2 = packetBuffer2.iterator(); final SQLiteDatabase db= recordingDb.getWritableDatabase(); db.beginTransaction(); while (iterator1.hasNext()) { recordingDb.storePacket(db, iterator1.next(), iterator2.next()); } db.setTransactionSuccessful(); db.endTransaction(); packetBuffer1.clear(); packetBuffer2.clear(); } public Location getLastLocation() { return lastLocation; } public void stopRecording() { currentRecording = null; recordingStatistics.writeBack(); if (recordingDb != null) { synchronized (this) { flushPacketBuffer(); recordingDb.createIndex(); recordingDb.close(); recordingDb = null; } } if (locationTracking != null) { locationTracking.stop(); locationTracking = null; } setUp(); } public boolean isRecording() { return currentRecording != null; } /** * Read preference settings and configure the receiver */ private void setUp() { SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context); int mode = Integer.valueOf(sharedPreferences.getString("settings_gns_mode", "0")); boolean timestamp = sharedPreferences.getBoolean("settings_gns_timestamp", false); boolean heartbeat = sharedPreferences.getBoolean("settings_gns_heartbeat", false); if (gns != null) { gns.setUp(mode, heartbeat, timestamp); } timeoutFlight = sharedPreferences.getInt("settings_flight_timeout", 10); positionTracking = sharedPreferences.getBoolean("settings_position_tracking", false); storeDatabaseExtern = sharedPreferences.getBoolean("settings_store_extern", false); } @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { Log.d("Recorder", "onSharedPreferenceChanged()"); setUp(); } public RecordingStatistics getRecordingStatistics() { return recordingStatistics; } public boolean isAvailable() { return gns != null; } public String getCurrentRecording() { return currentRecording; } }