Skip to content

How can i save the date and time of a task using shared preferences?

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);
            }
        });
    }






}

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: