diff --git a/src/main/java/com/nutomic/syncthingandroid/fragments/DeviceFragment.java b/src/main/java/com/nutomic/syncthingandroid/fragments/DeviceFragment.java index 978a17a5..111ee38b 100644 --- a/src/main/java/com/nutomic/syncthingandroid/fragments/DeviceFragment.java +++ b/src/main/java/com/nutomic/syncthingandroid/fragments/DeviceFragment.java @@ -1,6 +1,7 @@ package com.nutomic.syncthingandroid.fragments; import android.app.Fragment; +import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.graphics.drawable.Drawable; @@ -27,6 +28,7 @@ import com.nutomic.syncthingandroid.syncthing.RestApi; import com.nutomic.syncthingandroid.syncthing.SyncthingService; import com.nutomic.syncthingandroid.util.Compression; import com.nutomic.syncthingandroid.util.TextWatcherAdapter; +import com.nutomic.syncthingandroid.util.Util; import java.util.Arrays; import java.util.Collections; @@ -322,7 +324,7 @@ public class DeviceFragment extends Fragment implements getActivity().finish(); return true; case R.id.share_device_id: - RestApi.shareDeviceId(getActivity(), mDevice.deviceID); + shareDeviceId(getActivity(), mDevice.deviceID); return true; case R.id.remove: new AlertDialog.Builder(getActivity()) @@ -417,7 +419,19 @@ public class DeviceFragment extends Fragment implements IntentIntegrator integrator = new IntentIntegrator(DeviceFragment.this); integrator.initiateScan(); } else if (v.equals(mIdContainer)) { - mSyncthingService.getApi().copyDeviceId(mDevice.deviceID); + Util.copyDeviceId(getActivity(), mDevice.deviceID); } } + + /** + * Shares the given device ID via Intent. Must be called from an Activity. + */ + private void shareDeviceId(Context context, String id) { + Intent shareIntent = new Intent(); + shareIntent.setAction(Intent.ACTION_SEND); + shareIntent.setType("text/plain"); + shareIntent.putExtra(android.content.Intent.EXTRA_TEXT, id); + context.startActivity(Intent.createChooser( + shareIntent, context.getString(R.string.send_device_id_to))); + } } diff --git a/src/main/java/com/nutomic/syncthingandroid/fragments/DrawerFragment.java b/src/main/java/com/nutomic/syncthingandroid/fragments/DrawerFragment.java index 71fc348a..f506ba39 100644 --- a/src/main/java/com/nutomic/syncthingandroid/fragments/DrawerFragment.java +++ b/src/main/java/com/nutomic/syncthingandroid/fragments/DrawerFragment.java @@ -15,6 +15,7 @@ import com.nutomic.syncthingandroid.activities.SettingsActivity; import com.nutomic.syncthingandroid.activities.WebGuiActivity; import com.nutomic.syncthingandroid.syncthing.RestApi; import com.nutomic.syncthingandroid.syncthing.SyncthingService; +import com.nutomic.syncthingandroid.util.Util; import java.text.NumberFormat; import java.util.Locale; @@ -156,11 +157,11 @@ public class DrawerFragment extends Fragment implements RestApi.OnReceiveSystemI return; mDeviceId.setText(info.myID); - mDeviceId.setOnClickListener(v -> mActivity.getApi().copyDeviceId(mDeviceId.getText().toString())); + mDeviceId.setOnClickListener(v -> Util.copyDeviceId(getActivity(), mDeviceId.getText().toString())); NumberFormat percentFormat = NumberFormat.getPercentInstance(); percentFormat.setMaximumFractionDigits(2); mCpuUsage.setText(percentFormat.format(info.cpuPercent / 100)); - mRamUsage.setText(RestApi.readableFileSize(mActivity, info.sys)); + mRamUsage.setText(Util.readableFileSize(mActivity, info.sys)); int announceTotal = info.discoveryMethods; int announceConnected = announceTotal - info.discoveryErrors.size(); mAnnounceServer.setText(String.format(Locale.getDefault(), "%1$d/%2$d", @@ -188,8 +189,8 @@ public class DrawerFragment extends Fragment implements RestApi.OnReceiveSystemI @Override public void onReceiveConnections(Map connections) { RestApi.Connection c = connections.get(RestApi.TOTAL_STATS); - mDownload.setText(RestApi.readableTransferRate(mActivity, c.inBits)); - mUpload.setText(RestApi.readableTransferRate(mActivity, c.outBits)); + mDownload.setText(Util.readableTransferRate(mActivity, c.inBits)); + mUpload.setText(Util.readableTransferRate(mActivity, c.outBits)); } @Override diff --git a/src/main/java/com/nutomic/syncthingandroid/syncthing/RestApi.java b/src/main/java/com/nutomic/syncthingandroid/syncthing/RestApi.java index 4feb6c19..1544cc26 100644 --- a/src/main/java/com/nutomic/syncthingandroid/syncthing/RestApi.java +++ b/src/main/java/com/nutomic/syncthingandroid/syncthing/RestApi.java @@ -2,15 +2,12 @@ package com.nutomic.syncthingandroid.syncthing; import android.app.Activity; import android.app.NotificationManager; -import android.content.ClipData; -import android.content.ClipboardManager; import android.content.Context; import android.content.Intent; import android.os.AsyncTask; import android.support.annotation.NonNull; import android.text.TextUtils; import android.util.Log; -import android.widget.Toast; import com.google.gson.Gson; import com.google.gson.JsonArray; @@ -19,7 +16,6 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.google.gson.JsonSyntaxException; import com.nutomic.syncthingandroid.BuildConfig; -import com.nutomic.syncthingandroid.R; import com.nutomic.syncthingandroid.activities.RestartActivity; import com.nutomic.syncthingandroid.http.GetTask; import com.nutomic.syncthingandroid.http.PostTask; @@ -32,7 +28,6 @@ import org.json.JSONObject; import java.io.Serializable; import java.net.URL; -import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -459,34 +454,6 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener, } } - /** - * Converts a number of bytes to a human readable file size (eg 3.5 GiB). - * - * Based on http://stackoverflow.com/a/5599842 - */ - public static String readableFileSize(Context context, long bytes) { - final String[] units = context.getResources().getStringArray(R.array.file_size_units); - if (bytes <= 0) return "0 " + units[0]; - int digitGroups = (int) (Math.log10(bytes) / Math.log10(1024)); - return new DecimalFormat("#,##0.#") - .format(bytes / Math.pow(1024, digitGroups)) + " " + units[digitGroups]; - } - - /** - * Converts a number of bytes to a human readable transfer rate in bytes per second - * (eg 100 KiB/s). - * - * Based on http://stackoverflow.com/a/5599842 - */ - public static String readableTransferRate(Context context, long bits) { - final String[] units = context.getResources().getStringArray(R.array.transfer_rate_units); - long bytes = bits / 8; - if (bytes <= 0) return "0 " + units[0]; - int digitGroups = (int) (Math.log10(bytes) / Math.log10(1024)); - return new DecimalFormat("#,##0.#") - .format(bytes / Math.pow(1024, digitGroups)) + " " + units[digitGroups]; - } - /** * Listener for {@link #getConnections}. */ @@ -907,32 +874,6 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener, }.execute("id", id); } - /** - * Shares the given device ID via Intent. Must be called from an Activity. - */ - public static void shareDeviceId(Context context, String id) { - Intent shareIntent = new Intent(); - shareIntent.setAction(Intent.ACTION_SEND); - shareIntent.setType("text/plain"); - shareIntent.putExtra(android.content.Intent.EXTRA_TEXT, id); - context.startActivity(Intent.createChooser( - shareIntent, context.getString(R.string.send_device_id_to))); - } - - /** - * Copies the given device ID to the clipboard (and shows a Toast telling about it). - * - * @param id The device ID to copy. - */ - public void copyDeviceId(String id) { - ClipboardManager clipboard = (ClipboardManager) - mContext.getSystemService(Context.CLIPBOARD_SERVICE); - ClipData clip = ClipData.newPlainText(mContext.getString(R.string.device_id), id); - clipboard.setPrimaryClip(clip); - Toast.makeText(mContext, R.string.device_id_copied_to_clipboard, Toast.LENGTH_SHORT) - .show(); - } - /** * Force a rescan of the given subdirectory in folder. */ diff --git a/src/main/java/com/nutomic/syncthingandroid/syncthing/SyncthingService.java b/src/main/java/com/nutomic/syncthingandroid/syncthing/SyncthingService.java index 1bf37c36..2774f1f3 100644 --- a/src/main/java/com/nutomic/syncthingandroid/syncthing/SyncthingService.java +++ b/src/main/java/com/nutomic/syncthingandroid/syncthing/SyncthingService.java @@ -20,6 +20,7 @@ import android.util.Log; import android.util.Pair; import android.widget.Toast; +import com.google.common.io.Files; import com.nutomic.syncthingandroid.R; import com.nutomic.syncthingandroid.activities.MainActivity; import com.nutomic.syncthingandroid.http.PollWebGuiAvailableTask; @@ -548,12 +549,16 @@ public class SyncthingService extends Service implements */ public void exportConfig() { EXPORT_PATH.mkdirs(); - copyFile(new File(getFilesDir(), ConfigXml.CONFIG_FILE), - new File(EXPORT_PATH, ConfigXml.CONFIG_FILE)); - copyFile(new File(getFilesDir(), PRIVATE_KEY_FILE), - new File(EXPORT_PATH, PRIVATE_KEY_FILE)); - copyFile(new File(getFilesDir(), PUBLIC_KEY_FILE), - new File(EXPORT_PATH, PUBLIC_KEY_FILE)); + try { + Files.copy(new File(getFilesDir(), ConfigXml.CONFIG_FILE), + new File(EXPORT_PATH, ConfigXml.CONFIG_FILE)); + Files.copy(new File(getFilesDir(), PRIVATE_KEY_FILE), + new File(EXPORT_PATH, PRIVATE_KEY_FILE)); + Files.copy(new File(getFilesDir(), PUBLIC_KEY_FILE), + new File(EXPORT_PATH, PUBLIC_KEY_FILE)); + } catch (IOException e) { + Log.w(TAG, "Failed to export config", e); + } } /** @@ -570,35 +575,15 @@ public class SyncthingService extends Service implements if (!config.exists() || !privateKey.exists() || !publicKey.exists()) return false; - copyFile(config, new File(getFilesDir(), ConfigXml.CONFIG_FILE)); - copyFile(privateKey, new File(getFilesDir(), PRIVATE_KEY_FILE)); - copyFile(publicKey, new File(getFilesDir(), PUBLIC_KEY_FILE)); + try { + Files.copy(config, new File(getFilesDir(), ConfigXml.CONFIG_FILE)); + Files.copy(privateKey, new File(getFilesDir(), PRIVATE_KEY_FILE)); + Files.copy(publicKey, new File(getFilesDir(), PUBLIC_KEY_FILE)); + } catch (IOException e) { + Log.w(TAG, "Failed to import config", e); + } mCurrentState = State.INIT; updateState(); return true; } - - /** - * Copies files between different storage devices. - */ - private void copyFile(File source, File dest) { - FileChannel is = null; - FileChannel os = null; - try { - is = new FileInputStream(source).getChannel(); - os = new FileOutputStream(dest).getChannel(); - is.transferTo(0, is.size(), os); - } catch (IOException e) { - Log.w(TAG, "Failed to copy file", e); - } finally { - try { - if (is != null) - is.close(); - if (os != null) - os.close(); - } catch (IOException e) { - Log.w(TAG, "Failed to close stream", e); - } - } - } } diff --git a/src/main/java/com/nutomic/syncthingandroid/util/DevicesAdapter.java b/src/main/java/com/nutomic/syncthingandroid/util/DevicesAdapter.java index cc4b4b79..e3432049 100644 --- a/src/main/java/com/nutomic/syncthingandroid/util/DevicesAdapter.java +++ b/src/main/java/com/nutomic/syncthingandroid/util/DevicesAdapter.java @@ -57,12 +57,12 @@ public class DevicesAdapter extends ArrayAdapter status.setText(r.getString(R.string.device_syncing, conn.completion)); status.setTextColor(ContextCompat.getColor(getContext(), R.color.text_blue)); } - download.setText(RestApi.readableTransferRate(getContext(), conn.inBits)); - upload.setText(RestApi.readableTransferRate(getContext(), conn.outBits)); + download.setText(Util.readableTransferRate(getContext(), conn.inBits)); + upload.setText(Util.readableTransferRate(getContext(), conn.outBits)); } else { - download.setText(RestApi.readableTransferRate(getContext(), 0)); - upload.setText(RestApi.readableTransferRate(getContext(), 0)); + download.setText(Util.readableTransferRate(getContext(), 0)); + upload.setText(Util.readableTransferRate(getContext(), 0)); status.setText(r.getString(R.string.device_disconnected)); status.setTextColor(ContextCompat.getColor(getContext(), R.color.text_red)); } diff --git a/src/main/java/com/nutomic/syncthingandroid/util/FoldersAdapter.java b/src/main/java/com/nutomic/syncthingandroid/util/FoldersAdapter.java index 49ed156e..762e134b 100644 --- a/src/main/java/com/nutomic/syncthingandroid/util/FoldersAdapter.java +++ b/src/main/java/com/nutomic/syncthingandroid/util/FoldersAdapter.java @@ -19,7 +19,6 @@ import java.util.HashMap; import static android.view.View.GONE; import static android.view.View.VISIBLE; -import static com.nutomic.syncthingandroid.syncthing.RestApi.readableFileSize; /** * Generates item views for folder items. @@ -63,8 +62,8 @@ public class FoldersAdapter extends ArrayAdapter .getString(R.string.files, model.inSyncFiles, model.globalFiles)); size.setVisibility(VISIBLE); size.setText(getContext().getString(R.string.folder_size_format, - readableFileSize(getContext(), model.inSyncBytes), - readableFileSize(getContext(), model.globalBytes))); + Util.readableFileSize(getContext(), model.inSyncBytes), + Util.readableFileSize(getContext(), model.globalBytes))); setTextOrHide(invalid, model.invalid); } else { items.setVisibility(GONE); diff --git a/src/main/java/com/nutomic/syncthingandroid/util/Util.java b/src/main/java/com/nutomic/syncthingandroid/util/Util.java new file mode 100644 index 00000000..c88750a1 --- /dev/null +++ b/src/main/java/com/nutomic/syncthingandroid/util/Util.java @@ -0,0 +1,58 @@ +package com.nutomic.syncthingandroid.util; + +import android.content.ClipData; +import android.content.ClipboardManager; +import android.content.Context; +import android.widget.Toast; + +import com.nutomic.syncthingandroid.R; + +import java.text.DecimalFormat; + +public class Util { + + private Util() { + } + + /** + * Copies the given device ID to the clipboard (and shows a Toast telling about it). + * + * @param id The device ID to copy. + */ + public static void copyDeviceId(Context context, String id) { + ClipboardManager clipboard = (ClipboardManager) + context.getSystemService(Context.CLIPBOARD_SERVICE); + ClipData clip = ClipData.newPlainText(context.getString(R.string.device_id), id); + clipboard.setPrimaryClip(clip); + Toast.makeText(context, R.string.device_id_copied_to_clipboard, Toast.LENGTH_SHORT) + .show(); + } + + /** + * Converts a number of bytes to a human readable file size (eg 3.5 GiB). + * + * Based on http://stackoverflow.com/a/5599842 + */ + public static String readableFileSize(Context context, long bytes) { + final String[] units = context.getResources().getStringArray(R.array.file_size_units); + if (bytes <= 0) return "0 " + units[0]; + int digitGroups = (int) (Math.log10(bytes) / Math.log10(1024)); + return new DecimalFormat("#,##0.#") + .format(bytes / Math.pow(1024, digitGroups)) + " " + units[digitGroups]; + } + + /** + * Converts a number of bytes to a human readable transfer rate in bytes per second + * (eg 100 KiB/s). + * + * Based on http://stackoverflow.com/a/5599842 + */ + public static String readableTransferRate(Context context, long bits) { + final String[] units = context.getResources().getStringArray(R.array.transfer_rate_units); + long bytes = bits / 8; + if (bytes <= 0) return "0 " + units[0]; + int digitGroups = (int) (Math.log10(bytes) / Math.log10(1024)); + return new DecimalFormat("#,##0.#") + .format(bytes / Math.pow(1024, digitGroups)) + " " + units[digitGroups]; + } +}