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