I am trying to store the time at which a BLE scanner successfully scans for broadcasted advertisement packets. So far i am using the
Date CurrentTime = Calendar.getInstance().getTime();
Function which successfully allows me to print the time of scans.
I am also using SharedPreferences() to store the information recieved from the scanned data such as RSSI and hex stream. However, i want to be able to be able to store the time of the scan also. I have made a code that compiles with no errors but when i try to run the app on my phone it crashes. How would i be able to store the Time using shared preferences?
(All i need is the time of scan not the date and time so if there is a better function than the calendar one that would be great!)
Code:
//Edit to JoelWasserman BLE scanner by Joshua Gascoigne package com.example.joelwasserman.androidbletutorial; import android.Manifest; import android.app.AlertDialog; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothManager; import android.bluetooth.le.BluetoothLeScanner; import android.bluetooth.le.ScanCallback; import android.bluetooth.le.ScanFilter; import android.bluetooth.le.ScanRecord; import android.bluetooth.le.ScanResult; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.location.Location; import android.location.LocationManager; import android.os.AsyncTask; import android.os.Environment; import android.os.ParcelUuid; import android.provider.ContactsContract; import android.renderscript.Sampler; import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.text.method.ScrollingMovementMethod; import android.util.Log; import android.util.SparseArray; import android.view.View; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import java.io.BufferedWriter; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.io.StringReader; import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.Date; import java.util.List; import java.util.Set; import java.util.UUID; import java.util.Vector; import java.lang.*; import java.io.File; import java.io.FileWriter; import java.nio.ByteBuffer; import static android.R.attr.value; import static java.lang.String.valueOf; import java.util.concurrent.TimeUnit; import java.util.Calendar; public class MainActivity extends AppCompatActivity { BluetoothManager btManager; BluetoothAdapter btAdapter; BluetoothLeScanner btScanner; Button startScanningButton; Button stopScanningButton; Button DataBtn; TextView peripheralTextView; private final static int REQUEST_ENABLE_BT = 1; private static final int PERMISSION_REQUEST_COARSE_LOCATION = 1; SharedPreferences sharedPreferences; int RSSI1; int RSSI2; Date CurrentTime1; Date CurrentTime2; StringBuilder X = new StringBuilder(); StringBuilder Y = new StringBuilder(); long startTime; long stopTime; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); peripheralTextView = (TextView) findViewById(R.id.PeripheralTextView); peripheralTextView.setMovementMethod(new ScrollingMovementMethod()); sharedPreferences=getSharedPreferences("mypref", Context.MODE_PRIVATE); startScanningButton = (Button) findViewById(R.id.StartScanButton); startScanningButton.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { startScanning(); } }); stopScanningButton = (Button) findViewById(R.id.StopScanButton); stopScanningButton.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { stopScanning(); } }); stopScanningButton.setVisibility(View.INVISIBLE); DataBtn = (Button) findViewById(R.id.Databtn); DataBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { GetData(); } }); btManager = (BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE); btAdapter = btManager.getAdapter(); btScanner = btAdapter.getBluetoothLeScanner(); if (btAdapter != null && !btAdapter.isEnabled()) { Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableIntent,REQUEST_ENABLE_BT); } // Make sure we have access coarse location enabled, if not, prompt the user to enable it if (this.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { final AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("This app needs location access"); builder.setMessage("Please grant location access so this app can detect peripherals."); builder.setPositiveButton(android.R.string.ok, null); builder.setOnDismissListener(new DialogInterface.OnDismissListener() { @Override public void onDismiss(DialogInterface dialog) { requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, PERMISSION_REQUEST_COARSE_LOCATION); } }); builder.show(); } } // Device scan callback. private ScanCallback leScanCallback = new ScanCallback() { @Override public void onScanResult(int callbackType, ScanResult result) { // gets data from the BLE scan for broadcasting packets ScanRecord Scanned = result.getScanRecord(); String address = btAdapter.getAddress(); int Rssi = result.getRssi(); //Gets advertised packets in a byte array byte[] packetData = Scanned.getBytes(); //gtes length of packet data int PacketLength = packetData.length; StringBuilder x = new StringBuilder(); String[] data = new String[PacketLength]; //conversion to a hex stream from the byte array for (byte hex : packetData) { x.append(String.format("%02X", hex)); } for (int i =0;i<PacketLength;i++) { data[i] = (String.format("%02X", packetData[i])); } //Filters the scan by nameed device, easily changable if (new String("SimpleBLEBroadcaster1").equals(result.getDevice().getName())) { Date CurrentTime = Calendar.getInstance().getTime(); long startTime = System.nanoTime(); peripheralTextView.append("Device Name: " + result.getDevice().getName() + " Rssi: " + Rssi + " Packet length: " + PacketLength + "n" + " Packet Data: " + "0x" + Arrays.toString(data) + "Scan complete on: " + CurrentTime + "n"); //Prints data for the first broadcaster X =x; //Shared Preferences for Broadcaster 1 SharedPreferences.Editor editor= sharedPreferences.edit(); //Allows the advertised data packets to be stored within the app for future use RSSI1 = result.getRssi(); editor.putInt("Rssi", RSSI1 ); CurrentTime1 = CurrentTime; editor.putStringSet("Current Time", (Set<String>) CurrentTime1); //commits your edits editor.commit(); } //filter for second device (required for my Chip design) if (new String("SimpleBLEBroadcaster2").equals(result.getDevice().getName())) { Date CurrentTime = Calendar.getInstance().getTime(); long stopTime = System.nanoTime(); StringBuilder y = new StringBuilder(); y=x; // Changes the Hex stream detected for the second device to a new variable for storage purposes peripheralTextView.append("Device Name: " + result.getDevice().getName() + " Rssi: " + Rssi + " Packet length: " + PacketLength + "n" + " Packet Data: " + "0x" + Arrays.toString(data) + "Scan complete on: " + CurrentTime + "n");//Prints data for the second broadcaster Y=y; //Shared Preferences for Broadcaster 2 SharedPreferences.Editor editor= sharedPreferences.edit(); //Allows the advertised data packets to be stored within the app for future use RSSI2 = result.getRssi(); editor.putInt("Rssi", RSSI2 ); CurrentTime2 = CurrentTime; editor.putStringSet("Current Time", (Set<String>) CurrentTime2); //commits your edits editor.commit(); } } }; @Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { switch (requestCode) { case PERMISSION_REQUEST_COARSE_LOCATION: { if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { System.out.println("coarse location permission granted"); } else { final AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("Functionality limited"); builder.setMessage("Since location access has not been granted, this app will not be able to discover beacons when in the background."); builder.setPositiveButton(android.R.string.ok, null); builder.setOnDismissListener(new DialogInterface.OnDismissListener() { @Override public void onDismiss(DialogInterface dialog) { } }); builder.show(); } return; } } } //get data function that accesses the most recent scan of the devices to re-display their RSSI and Hex stream public void GetData(){ peripheralTextView.setText(" "); long TimeElapsed = stopTime - startTime; SharedPreferences.Editor editor= sharedPreferences.edit(); int Rssi1 = sharedPreferences.getInt("Rssi", RSSI1); Date MeasuredTime1 = (Date) sharedPreferences.getStringSet("Current Time", (Set<String>) CurrentTime1); int Rssi2 = sharedPreferences.getInt("Rssi", RSSI2); Date MeasuredTime2 = (Date) sharedPreferences.getStringSet("Current Time", (Set<String>) CurrentTime2); peripheralTextView.append("n" +"Broadcaster 1: " +"n" + " Signal strength is " + RSSI1 + "Measured at: " + CurrentTime1 + "n" + "Broadcaster 2: " + "n" + " Signal strength is " + RSSI2 + "Measured at: " + CurrentTime2 + " Time between Scans: " + TimeElapsed + "n"); } public void startScanning() { System.out.println("start scanning"); peripheralTextView.setText(""); startScanningButton.setVisibility(View.INVISIBLE); stopScanningButton.setVisibility(View.VISIBLE); AsyncTask.execute(new Runnable() { @Override public void run() { btScanner.startScan(leScanCallback); } }); } public void stopScanning() { System.out.println("stopping scanning"); peripheralTextView.append("Stopped Scanning"); startScanningButton.setVisibility(View.VISIBLE); stopScanningButton.setVisibility(View.INVISIBLE); AsyncTask.execute(new Runnable() { @Override public void run() { btScanner.stopScan(leScanCallback); } }); } }
Advertisement
Answer
You are explicitly casting Date
to Set<String>
in the following line:
editor.putStringSet("Current Time", (Set<String>) CurrentTime2);
and it obviously will cause ClassCastException
like class java.util.Date cannot be cast to class java.util.Set
You should use some different way to transform this Date
object to String
(or Set<String>
if you need this for some reason) like
new SimpleDateFormat().format(CurrentTime)
or similar.
IMHO you should think again about whole this mechanism and probably instead of String date keep in preferences some kind of ‘timestamp’ or another standard format for keeping the data and share it between systems
Read more here: