Moved common functionality to new Util class

This commit is contained in:
Felix Ableitner 2016-10-15 16:18:31 +09:00
parent 3dffc4c900
commit e74c5b8c47
7 changed files with 103 additions and 105 deletions

View File

@ -1,6 +1,7 @@
package com.nutomic.syncthingandroid.fragments; package com.nutomic.syncthingandroid.fragments;
import android.app.Fragment; import android.app.Fragment;
import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.graphics.drawable.Drawable; 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.syncthing.SyncthingService;
import com.nutomic.syncthingandroid.util.Compression; import com.nutomic.syncthingandroid.util.Compression;
import com.nutomic.syncthingandroid.util.TextWatcherAdapter; import com.nutomic.syncthingandroid.util.TextWatcherAdapter;
import com.nutomic.syncthingandroid.util.Util;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
@ -322,7 +324,7 @@ public class DeviceFragment extends Fragment implements
getActivity().finish(); getActivity().finish();
return true; return true;
case R.id.share_device_id: case R.id.share_device_id:
RestApi.shareDeviceId(getActivity(), mDevice.deviceID); shareDeviceId(getActivity(), mDevice.deviceID);
return true; return true;
case R.id.remove: case R.id.remove:
new AlertDialog.Builder(getActivity()) new AlertDialog.Builder(getActivity())
@ -417,7 +419,19 @@ public class DeviceFragment extends Fragment implements
IntentIntegrator integrator = new IntentIntegrator(DeviceFragment.this); IntentIntegrator integrator = new IntentIntegrator(DeviceFragment.this);
integrator.initiateScan(); integrator.initiateScan();
} else if (v.equals(mIdContainer)) { } 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)));
}
} }

View File

@ -15,6 +15,7 @@ import com.nutomic.syncthingandroid.activities.SettingsActivity;
import com.nutomic.syncthingandroid.activities.WebGuiActivity; import com.nutomic.syncthingandroid.activities.WebGuiActivity;
import com.nutomic.syncthingandroid.syncthing.RestApi; import com.nutomic.syncthingandroid.syncthing.RestApi;
import com.nutomic.syncthingandroid.syncthing.SyncthingService; import com.nutomic.syncthingandroid.syncthing.SyncthingService;
import com.nutomic.syncthingandroid.util.Util;
import java.text.NumberFormat; import java.text.NumberFormat;
import java.util.Locale; import java.util.Locale;
@ -156,11 +157,11 @@ public class DrawerFragment extends Fragment implements RestApi.OnReceiveSystemI
return; return;
mDeviceId.setText(info.myID); 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(); NumberFormat percentFormat = NumberFormat.getPercentInstance();
percentFormat.setMaximumFractionDigits(2); percentFormat.setMaximumFractionDigits(2);
mCpuUsage.setText(percentFormat.format(info.cpuPercent / 100)); 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 announceTotal = info.discoveryMethods;
int announceConnected = announceTotal - info.discoveryErrors.size(); int announceConnected = announceTotal - info.discoveryErrors.size();
mAnnounceServer.setText(String.format(Locale.getDefault(), "%1$d/%2$d", mAnnounceServer.setText(String.format(Locale.getDefault(), "%1$d/%2$d",
@ -188,8 +189,8 @@ public class DrawerFragment extends Fragment implements RestApi.OnReceiveSystemI
@Override @Override
public void onReceiveConnections(Map<String, RestApi.Connection> connections) { public void onReceiveConnections(Map<String, RestApi.Connection> connections) {
RestApi.Connection c = connections.get(RestApi.TOTAL_STATS); RestApi.Connection c = connections.get(RestApi.TOTAL_STATS);
mDownload.setText(RestApi.readableTransferRate(mActivity, c.inBits)); mDownload.setText(Util.readableTransferRate(mActivity, c.inBits));
mUpload.setText(RestApi.readableTransferRate(mActivity, c.outBits)); mUpload.setText(Util.readableTransferRate(mActivity, c.outBits));
} }
@Override @Override

View File

@ -2,15 +2,12 @@ package com.nutomic.syncthingandroid.syncthing;
import android.app.Activity; import android.app.Activity;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import android.widget.Toast;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.JsonArray; import com.google.gson.JsonArray;
@ -19,7 +16,6 @@ import com.google.gson.JsonObject;
import com.google.gson.JsonParser; import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException; import com.google.gson.JsonSyntaxException;
import com.nutomic.syncthingandroid.BuildConfig; import com.nutomic.syncthingandroid.BuildConfig;
import com.nutomic.syncthingandroid.R;
import com.nutomic.syncthingandroid.activities.RestartActivity; import com.nutomic.syncthingandroid.activities.RestartActivity;
import com.nutomic.syncthingandroid.http.GetTask; import com.nutomic.syncthingandroid.http.GetTask;
import com.nutomic.syncthingandroid.http.PostTask; import com.nutomic.syncthingandroid.http.PostTask;
@ -32,7 +28,6 @@ import org.json.JSONObject;
import java.io.Serializable; import java.io.Serializable;
import java.net.URL; import java.net.URL;
import java.text.DecimalFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; 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}. * Listener for {@link #getConnections}.
*/ */
@ -907,32 +874,6 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
}.execute("id", id); }.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. * Force a rescan of the given subdirectory in folder.
*/ */

View File

@ -20,6 +20,7 @@ import android.util.Log;
import android.util.Pair; import android.util.Pair;
import android.widget.Toast; import android.widget.Toast;
import com.google.common.io.Files;
import com.nutomic.syncthingandroid.R; import com.nutomic.syncthingandroid.R;
import com.nutomic.syncthingandroid.activities.MainActivity; import com.nutomic.syncthingandroid.activities.MainActivity;
import com.nutomic.syncthingandroid.http.PollWebGuiAvailableTask; import com.nutomic.syncthingandroid.http.PollWebGuiAvailableTask;
@ -548,12 +549,16 @@ public class SyncthingService extends Service implements
*/ */
public void exportConfig() { public void exportConfig() {
EXPORT_PATH.mkdirs(); EXPORT_PATH.mkdirs();
copyFile(new File(getFilesDir(), ConfigXml.CONFIG_FILE), try {
Files.copy(new File(getFilesDir(), ConfigXml.CONFIG_FILE),
new File(EXPORT_PATH, ConfigXml.CONFIG_FILE)); new File(EXPORT_PATH, ConfigXml.CONFIG_FILE));
copyFile(new File(getFilesDir(), PRIVATE_KEY_FILE), Files.copy(new File(getFilesDir(), PRIVATE_KEY_FILE),
new File(EXPORT_PATH, PRIVATE_KEY_FILE)); new File(EXPORT_PATH, PRIVATE_KEY_FILE));
copyFile(new File(getFilesDir(), PUBLIC_KEY_FILE), Files.copy(new File(getFilesDir(), PUBLIC_KEY_FILE),
new File(EXPORT_PATH, 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()) if (!config.exists() || !privateKey.exists() || !publicKey.exists())
return false; return false;
copyFile(config, new File(getFilesDir(), ConfigXml.CONFIG_FILE)); try {
copyFile(privateKey, new File(getFilesDir(), PRIVATE_KEY_FILE)); Files.copy(config, new File(getFilesDir(), ConfigXml.CONFIG_FILE));
copyFile(publicKey, new File(getFilesDir(), PUBLIC_KEY_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; mCurrentState = State.INIT;
updateState(); updateState();
return true; 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);
}
}
}
} }

View File

@ -57,12 +57,12 @@ public class DevicesAdapter extends ArrayAdapter<RestApi.Device>
status.setText(r.getString(R.string.device_syncing, conn.completion)); status.setText(r.getString(R.string.device_syncing, conn.completion));
status.setTextColor(ContextCompat.getColor(getContext(), R.color.text_blue)); status.setTextColor(ContextCompat.getColor(getContext(), R.color.text_blue));
} }
download.setText(RestApi.readableTransferRate(getContext(), conn.inBits)); download.setText(Util.readableTransferRate(getContext(), conn.inBits));
upload.setText(RestApi.readableTransferRate(getContext(), conn.outBits)); upload.setText(Util.readableTransferRate(getContext(), conn.outBits));
} }
else { else {
download.setText(RestApi.readableTransferRate(getContext(), 0)); download.setText(Util.readableTransferRate(getContext(), 0));
upload.setText(RestApi.readableTransferRate(getContext(), 0)); upload.setText(Util.readableTransferRate(getContext(), 0));
status.setText(r.getString(R.string.device_disconnected)); status.setText(r.getString(R.string.device_disconnected));
status.setTextColor(ContextCompat.getColor(getContext(), R.color.text_red)); status.setTextColor(ContextCompat.getColor(getContext(), R.color.text_red));
} }

View File

@ -19,7 +19,6 @@ import java.util.HashMap;
import static android.view.View.GONE; import static android.view.View.GONE;
import static android.view.View.VISIBLE; import static android.view.View.VISIBLE;
import static com.nutomic.syncthingandroid.syncthing.RestApi.readableFileSize;
/** /**
* Generates item views for folder items. * Generates item views for folder items.
@ -63,8 +62,8 @@ public class FoldersAdapter extends ArrayAdapter<Folder>
.getString(R.string.files, model.inSyncFiles, model.globalFiles)); .getString(R.string.files, model.inSyncFiles, model.globalFiles));
size.setVisibility(VISIBLE); size.setVisibility(VISIBLE);
size.setText(getContext().getString(R.string.folder_size_format, size.setText(getContext().getString(R.string.folder_size_format,
readableFileSize(getContext(), model.inSyncBytes), Util.readableFileSize(getContext(), model.inSyncBytes),
readableFileSize(getContext(), model.globalBytes))); Util.readableFileSize(getContext(), model.globalBytes)));
setTextOrHide(invalid, model.invalid); setTextOrHide(invalid, model.invalid);
} else { } else {
items.setVisibility(GONE); items.setVisibility(GONE);

View File

@ -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];
}
}