Fixed CSV sharing
This commit is contained in:
@@ -1,28 +1,13 @@
|
||||
package uk.co.alt236.btlescan.containers;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import uk.co.alt236.bluetoothlelib.device.BluetoothLeDevice;
|
||||
import uk.co.alt236.bluetoothlelib.device.beacon.BeaconType;
|
||||
import uk.co.alt236.bluetoothlelib.device.beacon.BeaconUtils;
|
||||
import uk.co.alt236.bluetoothlelib.device.beacon.ibeacon.IBeaconDevice;
|
||||
import uk.co.alt236.bluetoothlelib.util.ByteUtils;
|
||||
import uk.co.alt236.btlescan.R;
|
||||
import uk.co.alt236.btlescan.util.CsvWriterHelper;
|
||||
import uk.co.alt236.btlescan.util.TimeFormatter;
|
||||
import uk.co.alt236.easycursor.objectcursor.EasyObjectCursor;
|
||||
|
||||
public class BluetoothLeDeviceStore {
|
||||
@@ -65,117 +50,4 @@ public class BluetoothLeDeviceStore {
|
||||
|
||||
return methodResult;
|
||||
}
|
||||
|
||||
private String getListAsCsv() {
|
||||
final List<BluetoothLeDevice> list = getDeviceList();
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append(CsvWriterHelper.addStuff("mac"));
|
||||
sb.append(CsvWriterHelper.addStuff("name"));
|
||||
sb.append(CsvWriterHelper.addStuff("firstTimestamp"));
|
||||
sb.append(CsvWriterHelper.addStuff("firstRssi"));
|
||||
sb.append(CsvWriterHelper.addStuff("currentTimestamp"));
|
||||
sb.append(CsvWriterHelper.addStuff("currentRssi"));
|
||||
sb.append(CsvWriterHelper.addStuff("adRecord"));
|
||||
sb.append(CsvWriterHelper.addStuff("iBeacon"));
|
||||
sb.append(CsvWriterHelper.addStuff("uuid"));
|
||||
sb.append(CsvWriterHelper.addStuff("major"));
|
||||
sb.append(CsvWriterHelper.addStuff("minor"));
|
||||
sb.append(CsvWriterHelper.addStuff("txPower"));
|
||||
sb.append(CsvWriterHelper.addStuff("distance"));
|
||||
sb.append(CsvWriterHelper.addStuff("accuracy"));
|
||||
sb.append('\n');
|
||||
|
||||
for (final BluetoothLeDevice device : list) {
|
||||
sb.append(CsvWriterHelper.addStuff(device.getAddress()));
|
||||
sb.append(CsvWriterHelper.addStuff(device.getName()));
|
||||
sb.append(CsvWriterHelper.addStuff(TimeFormatter.getIsoDateTime(device.getFirstTimestamp())));
|
||||
sb.append(CsvWriterHelper.addStuff(device.getFirstRssi()));
|
||||
sb.append(CsvWriterHelper.addStuff(TimeFormatter.getIsoDateTime(device.getTimestamp())));
|
||||
sb.append(CsvWriterHelper.addStuff(device.getRssi()));
|
||||
sb.append(CsvWriterHelper.addStuff(ByteUtils.byteArrayToHexString(device.getScanRecord())));
|
||||
final boolean isIBeacon = BeaconUtils.getBeaconType(device) == BeaconType.IBEACON;
|
||||
final String uuid;
|
||||
final String minor;
|
||||
final String major;
|
||||
final String txPower;
|
||||
final String distance;
|
||||
final String accuracy;
|
||||
|
||||
if (isIBeacon) {
|
||||
final IBeaconDevice beacon = new IBeaconDevice(device);
|
||||
uuid = String.valueOf(beacon.getUUID());
|
||||
minor = String.valueOf(beacon.getMinor());
|
||||
major = String.valueOf(beacon.getMajor());
|
||||
txPower = String.valueOf(beacon.getCalibratedTxPower());
|
||||
distance = beacon.getDistanceDescriptor().toString().toLowerCase(Locale.US);
|
||||
accuracy = String.valueOf(beacon.getAccuracy());
|
||||
} else {
|
||||
uuid = "";
|
||||
minor = "";
|
||||
major = "";
|
||||
txPower = "";
|
||||
distance = "";
|
||||
accuracy = "";
|
||||
}
|
||||
|
||||
sb.append(CsvWriterHelper.addStuff(isIBeacon));
|
||||
sb.append(CsvWriterHelper.addStuff(uuid));
|
||||
sb.append(CsvWriterHelper.addStuff(minor));
|
||||
sb.append(CsvWriterHelper.addStuff(major));
|
||||
sb.append(CsvWriterHelper.addStuff(txPower));
|
||||
sb.append(CsvWriterHelper.addStuff(distance));
|
||||
sb.append(CsvWriterHelper.addStuff(accuracy));
|
||||
|
||||
sb.append('\n');
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public void shareDataAsEmail(final Context context) {
|
||||
final long timeInMillis = System.currentTimeMillis();
|
||||
|
||||
final String to = null;
|
||||
final String subject = context.getString(
|
||||
R.string.exporter_email_device_list_subject,
|
||||
TimeFormatter.getIsoDateTime(timeInMillis));
|
||||
|
||||
final String message = context.getString(R.string.exporter_email_device_list_body);
|
||||
|
||||
final Intent i = new Intent(Intent.ACTION_SEND);
|
||||
i.setType("plain/text");
|
||||
try {
|
||||
final File outputDir = context.getCacheDir();
|
||||
final File outputFile = File.createTempFile("bluetooth_le_" + timeInMillis, ".csv", outputDir);
|
||||
outputFile.setReadable(true, false);
|
||||
generateFile(outputFile, getListAsCsv());
|
||||
i.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(outputFile));
|
||||
i.putExtra(Intent.EXTRA_EMAIL, new String[]{to});
|
||||
i.putExtra(Intent.EXTRA_SUBJECT, subject);
|
||||
i.putExtra(Intent.EXTRA_TEXT, message);
|
||||
context.startActivity(Intent.createChooser(i, context.getString(R.string.exporter_email_device_list_picker_text)));
|
||||
|
||||
} catch (final IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static FileWriter generateFile(final File file, final String contents) {
|
||||
FileWriter writer = null;
|
||||
try {
|
||||
writer = new FileWriter(file);
|
||||
writer.append(contents);
|
||||
writer.flush();
|
||||
|
||||
} catch (final IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
try {
|
||||
writer.close();
|
||||
} catch (final IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,11 @@ package uk.co.alt236.btlescan.ui.common;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
|
||||
import uk.co.alt236.bluetoothlelib.device.BluetoothLeDevice;
|
||||
import uk.co.alt236.btlescan.R;
|
||||
import uk.co.alt236.btlescan.ui.control.DeviceControlActivity;
|
||||
import uk.co.alt236.btlescan.ui.details.DeviceDetailsActivity;
|
||||
|
||||
@@ -28,6 +30,20 @@ public class Navigation {
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
public void shareFileViaEmail(final Uri fileUri, final String[] recipient, final String subject, final String message) {
|
||||
final Intent intent = new Intent(Intent.ACTION_SEND);
|
||||
|
||||
intent.setType("plain/text");
|
||||
intent.putExtra(Intent.EXTRA_STREAM, fileUri);
|
||||
intent.putExtra(Intent.EXTRA_EMAIL, recipient);
|
||||
intent.putExtra(Intent.EXTRA_SUBJECT, subject);
|
||||
intent.putExtra(Intent.EXTRA_TEXT, message);
|
||||
|
||||
startActivity(Intent.createChooser(intent,
|
||||
mActivity.getString(R.string.exporter_email_device_list_picker_text)));
|
||||
}
|
||||
|
||||
|
||||
private void startActivity(final Intent intent) {
|
||||
ActivityCompat.startActivity(mActivity, intent, null);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package uk.co.alt236.btlescan.util;
|
||||
package uk.co.alt236.btlescan.ui.main;
|
||||
|
||||
public class CsvWriterHelper {
|
||||
/*package*/ class CsvWriterHelper {
|
||||
private static final String QUOTE = "\"";
|
||||
|
||||
public static String addStuff(final Integer text) {
|
||||
@@ -132,7 +132,7 @@ public class MainActivity extends AppCompatActivity implements AdapterView.OnIte
|
||||
DialogFactory.createAboutDialog(this).show();
|
||||
break;
|
||||
case R.id.menu_share:
|
||||
mDeviceStore.shareDataAsEmail(this);
|
||||
new Sharer().shareDataAsEmail(this, mDeviceStore);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
package uk.co.alt236.btlescan.ui.main;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import uk.co.alt236.bluetoothlelib.device.BluetoothLeDevice;
|
||||
import uk.co.alt236.bluetoothlelib.device.beacon.BeaconType;
|
||||
import uk.co.alt236.bluetoothlelib.device.beacon.BeaconUtils;
|
||||
import uk.co.alt236.bluetoothlelib.device.beacon.ibeacon.IBeaconDevice;
|
||||
import uk.co.alt236.bluetoothlelib.util.ByteUtils;
|
||||
import uk.co.alt236.btlescan.R;
|
||||
import uk.co.alt236.btlescan.containers.BluetoothLeDeviceStore;
|
||||
import uk.co.alt236.btlescan.ui.common.Navigation;
|
||||
import uk.co.alt236.btlescan.util.TimeFormatter;
|
||||
|
||||
/*package*/ class Sharer {
|
||||
private static final String CSV_FILENAME_PREFIX = "bluetooth_le_%d";
|
||||
private static final String CSV_FILENAME_SUFFIX = ".csv";
|
||||
|
||||
private static File getExternalCacheDir(final Context context) {
|
||||
final File[] files = ContextCompat.getExternalCacheDirs(context);
|
||||
final File retVal;
|
||||
|
||||
if (files == null || files.length == 0 || files[0] == null) {
|
||||
retVal = null;
|
||||
} else {
|
||||
retVal = files[0];
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private static String getListAsCsv(List<BluetoothLeDevice> deviceList) {
|
||||
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append(CsvWriterHelper.addStuff("mac"));
|
||||
sb.append(CsvWriterHelper.addStuff("name"));
|
||||
sb.append(CsvWriterHelper.addStuff("firstTimestamp"));
|
||||
sb.append(CsvWriterHelper.addStuff("firstRssi"));
|
||||
sb.append(CsvWriterHelper.addStuff("currentTimestamp"));
|
||||
sb.append(CsvWriterHelper.addStuff("currentRssi"));
|
||||
sb.append(CsvWriterHelper.addStuff("adRecord"));
|
||||
sb.append(CsvWriterHelper.addStuff("iBeacon"));
|
||||
sb.append(CsvWriterHelper.addStuff("uuid"));
|
||||
sb.append(CsvWriterHelper.addStuff("major"));
|
||||
sb.append(CsvWriterHelper.addStuff("minor"));
|
||||
sb.append(CsvWriterHelper.addStuff("txPower"));
|
||||
sb.append(CsvWriterHelper.addStuff("distance"));
|
||||
sb.append(CsvWriterHelper.addStuff("accuracy"));
|
||||
sb.append('\n');
|
||||
|
||||
for (final BluetoothLeDevice device : deviceList) {
|
||||
sb.append(CsvWriterHelper.addStuff(device.getAddress()));
|
||||
sb.append(CsvWriterHelper.addStuff(device.getName()));
|
||||
sb.append(CsvWriterHelper.addStuff(TimeFormatter.getIsoDateTime(device.getFirstTimestamp())));
|
||||
sb.append(CsvWriterHelper.addStuff(device.getFirstRssi()));
|
||||
sb.append(CsvWriterHelper.addStuff(TimeFormatter.getIsoDateTime(device.getTimestamp())));
|
||||
sb.append(CsvWriterHelper.addStuff(device.getRssi()));
|
||||
sb.append(CsvWriterHelper.addStuff(ByteUtils.byteArrayToHexString(device.getScanRecord())));
|
||||
final boolean isIBeacon = BeaconUtils.getBeaconType(device) == BeaconType.IBEACON;
|
||||
final String uuid;
|
||||
final String minor;
|
||||
final String major;
|
||||
final String txPower;
|
||||
final String distance;
|
||||
final String accuracy;
|
||||
|
||||
if (isIBeacon) {
|
||||
final IBeaconDevice beacon = new IBeaconDevice(device);
|
||||
uuid = String.valueOf(beacon.getUUID());
|
||||
minor = String.valueOf(beacon.getMinor());
|
||||
major = String.valueOf(beacon.getMajor());
|
||||
txPower = String.valueOf(beacon.getCalibratedTxPower());
|
||||
distance = beacon.getDistanceDescriptor().toString().toLowerCase(Locale.US);
|
||||
accuracy = String.valueOf(beacon.getAccuracy());
|
||||
} else {
|
||||
uuid = "";
|
||||
minor = "";
|
||||
major = "";
|
||||
txPower = "";
|
||||
distance = "";
|
||||
accuracy = "";
|
||||
}
|
||||
|
||||
sb.append(CsvWriterHelper.addStuff(isIBeacon));
|
||||
sb.append(CsvWriterHelper.addStuff(uuid));
|
||||
sb.append(CsvWriterHelper.addStuff(minor));
|
||||
sb.append(CsvWriterHelper.addStuff(major));
|
||||
sb.append(CsvWriterHelper.addStuff(txPower));
|
||||
sb.append(CsvWriterHelper.addStuff(distance));
|
||||
sb.append(CsvWriterHelper.addStuff(accuracy));
|
||||
|
||||
sb.append('\n');
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static FileWriter saveToFile(final File file, final String contents) {
|
||||
FileWriter writer = null;
|
||||
try {
|
||||
writer = new FileWriter(file);
|
||||
writer.append(contents);
|
||||
writer.flush();
|
||||
|
||||
} catch (final IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
try {
|
||||
if (writer != null) {
|
||||
writer.close();
|
||||
}
|
||||
} catch (final IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return writer;
|
||||
}
|
||||
|
||||
public void shareDataAsEmail(final Activity activity,
|
||||
final BluetoothLeDeviceStore store) {
|
||||
final long timeInMillis = System.currentTimeMillis();
|
||||
final String filename = String.format(Locale.US, CSV_FILENAME_PREFIX, timeInMillis);
|
||||
|
||||
final String to = null;
|
||||
final String subject = activity.getString(
|
||||
R.string.exporter_email_device_list_subject,
|
||||
TimeFormatter.getIsoDateTime(timeInMillis));
|
||||
|
||||
final String message = activity.getString(R.string.exporter_email_device_list_body);
|
||||
|
||||
final String contents = getListAsCsv(store.getDeviceList());
|
||||
final File outputDir = getExternalCacheDir(activity);
|
||||
|
||||
if (outputDir == null) {
|
||||
Toast.makeText(activity, R.string.error_unable_to_access_external_storage, Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
try {
|
||||
|
||||
final File outputFile = File.createTempFile(filename, CSV_FILENAME_SUFFIX, outputDir);
|
||||
saveToFile(outputFile, contents);
|
||||
|
||||
final Uri uri = Uri.fromFile(outputFile);
|
||||
new Navigation(activity)
|
||||
.shareFileViaEmail(uri, new String[]{to}, subject, message);
|
||||
|
||||
} catch (final IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -75,5 +75,6 @@
|
||||
<string name="label_updated">Updated:</string>
|
||||
<string name="label_decriptor">Descriptor:</string>
|
||||
|
||||
<string name="error_unable_to_access_external_storage">"Could not access external storage!"</string>
|
||||
<string name="permission_not_granted_coarse_location">The ACCESS_COARSE_LOCATION permission is needed to receive bluetooth scan results</string>
|
||||
</resources>
|
||||
Reference in New Issue
Block a user