diff --git a/ui/src/main/java/com/wireguard/android/util/ClipboardUtils.java b/ui/src/main/java/com/wireguard/android/util/ClipboardUtils.java deleted file mode 100644 index e9f65c59..00000000 --- a/ui/src/main/java/com/wireguard/android/util/ClipboardUtils.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright © 2017-2019 WireGuard LLC. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0 - */ - -package com.wireguard.android.util; - -import android.content.ClipData; -import android.content.ClipboardManager; -import android.content.Context; -import android.view.View; -import android.widget.TextView; - -import com.google.android.material.snackbar.Snackbar; -import com.wireguard.util.NonNullForAll; - -/** - * Standalone utilities for interacting with the system clipboard. - */ - -@NonNullForAll -public final class ClipboardUtils { - private ClipboardUtils() { - // Prevent instantiation - } - - public static void copyTextView(final View view) { - if (!(view instanceof TextView)) - return; - final CharSequence text = ((TextView) view).getText(); - if (text == null || text.length() == 0) - return; - final Object service = view.getContext().getSystemService(Context.CLIPBOARD_SERVICE); - if (!(service instanceof ClipboardManager)) - return; - final CharSequence description = view.getContentDescription(); - ((ClipboardManager) service).setPrimaryClip(ClipData.newPlainText(description, text)); - Snackbar.make(view, description + " copied to clipboard", Snackbar.LENGTH_LONG).show(); - } -} diff --git a/ui/src/main/java/com/wireguard/android/util/ClipboardUtils.kt b/ui/src/main/java/com/wireguard/android/util/ClipboardUtils.kt new file mode 100644 index 00000000..c1ddaa4c --- /dev/null +++ b/ui/src/main/java/com/wireguard/android/util/ClipboardUtils.kt @@ -0,0 +1,30 @@ +/* + * Copyright © 2017-2019 WireGuard LLC. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +package com.wireguard.android.util + +import android.content.ClipData +import android.content.ClipboardManager +import android.content.Context +import android.view.View +import android.widget.TextView +import com.google.android.material.snackbar.Snackbar + +/** + * Standalone utilities for interacting with the system clipboard. + */ +object ClipboardUtils { + @JvmStatic + fun copyTextView(view: View) { + if (view !is TextView) + return + val text = view.text + if (text == null || text.length == 0) return + val service = view.getContext().getSystemService(Context.CLIPBOARD_SERVICE) as? ClipboardManager + ?: return + val description = view.getContentDescription() + service.setPrimaryClip(ClipData.newPlainText(description, text)) + Snackbar.make(view, "$description copied to clipboard", Snackbar.LENGTH_LONG).show() + } +} diff --git a/ui/src/main/java/com/wireguard/android/util/DownloadsFileSaver.java b/ui/src/main/java/com/wireguard/android/util/DownloadsFileSaver.java deleted file mode 100644 index 14895b64..00000000 --- a/ui/src/main/java/com/wireguard/android/util/DownloadsFileSaver.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright © 2019 WireGuard LLC. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0 - */ - -package com.wireguard.android.util; - -import android.content.ContentResolver; -import android.content.ContentValues; -import android.content.Context; -import android.database.Cursor; -import android.net.Uri; -import android.os.Build; -import android.os.Environment; -import android.provider.MediaStore; -import android.provider.MediaStore.MediaColumns; - -import com.wireguard.android.R; -import com.wireguard.util.NonNullForAll; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -@NonNullForAll -public final class DownloadsFileSaver { - - private DownloadsFileSaver() { - // Prevent instantiation - } - - public static DownloadsFile save(final Context context, final String name, final String mimeType, final boolean overwriteExisting) throws Exception { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - final ContentResolver contentResolver = context.getContentResolver(); - if (overwriteExisting) - contentResolver.delete(MediaStore.Downloads.EXTERNAL_CONTENT_URI, String.format("%s = ?", MediaColumns.DISPLAY_NAME), new String[]{name}); - final ContentValues contentValues = new ContentValues(); - contentValues.put(MediaColumns.DISPLAY_NAME, name); - contentValues.put(MediaColumns.MIME_TYPE, mimeType); - final Uri contentUri = contentResolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, contentValues); - if (contentUri == null) - throw new IOException(context.getString(R.string.create_downloads_file_error)); - final OutputStream contentStream = contentResolver.openOutputStream(contentUri); - if (contentStream == null) - throw new IOException(context.getString(R.string.create_downloads_file_error)); - @SuppressWarnings("deprecation") - Cursor cursor = contentResolver.query(contentUri, new String[]{MediaColumns.DATA}, null, null, null); - String path = null; - if (cursor != null) { - try { - if (cursor.moveToFirst()) - path = cursor.getString(0); - } finally { - cursor.close(); - } - } - if (path == null) { - path = "Download/"; - cursor = contentResolver.query(contentUri, new String[]{MediaColumns.DISPLAY_NAME}, null, null, null); - if (cursor != null) { - try { - if (cursor.moveToFirst()) - path += cursor.getString(0); - } finally { - cursor.close(); - } - } - } - return new DownloadsFile(context, contentStream, path, contentUri); - } else { - @SuppressWarnings("deprecation") final File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS); - final File file = new File(path, name); - if (!path.isDirectory() && !path.mkdirs()) - throw new IOException(context.getString(R.string.create_output_dir_error)); - return new DownloadsFile(context, new FileOutputStream(file), file.getAbsolutePath(), null); - } - } - - public static final class DownloadsFile { - private final Context context; - private final String fileName; - private final OutputStream outputStream; - private final Uri uri; - - private DownloadsFile(final Context context, final OutputStream outputStream, final String fileName, final Uri uri) { - this.context = context; - this.outputStream = outputStream; - this.fileName = fileName; - this.uri = uri; - } - - public void delete() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) - context.getContentResolver().delete(uri, null, null); - else - new File(fileName).delete(); - } - - public String getFileName() { - return fileName; - } - - public OutputStream getOutputStream() { - return outputStream; - } - } -} diff --git a/ui/src/main/java/com/wireguard/android/util/DownloadsFileSaver.kt b/ui/src/main/java/com/wireguard/android/util/DownloadsFileSaver.kt new file mode 100644 index 00000000..a0f0e1fb --- /dev/null +++ b/ui/src/main/java/com/wireguard/android/util/DownloadsFileSaver.kt @@ -0,0 +1,72 @@ +/* + * Copyright © 2019 WireGuard LLC. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +package com.wireguard.android.util + +import android.content.ContentValues +import android.content.Context +import android.net.Uri +import android.os.Build +import android.os.Environment +import android.provider.MediaStore +import android.provider.MediaStore.MediaColumns +import com.wireguard.android.R +import java.io.File +import java.io.FileOutputStream +import java.io.IOException +import java.io.OutputStream + +object DownloadsFileSaver { + @Throws(Exception::class) + fun save(context: Context, name: String, mimeType: String?, overwriteExisting: Boolean) = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + val contentResolver = context.contentResolver + if (overwriteExisting) + contentResolver.delete(MediaStore.Downloads.EXTERNAL_CONTENT_URI, String.format("%s = ?", MediaColumns.DISPLAY_NAME), arrayOf(name)) + val contentValues = ContentValues() + contentValues.put(MediaColumns.DISPLAY_NAME, name) + contentValues.put(MediaColumns.MIME_TYPE, mimeType) + val contentUri = contentResolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, contentValues) + ?: throw IOException(context.getString(R.string.create_downloads_file_error)) + val contentStream = contentResolver.openOutputStream(contentUri) + ?: throw IOException(context.getString(R.string.create_downloads_file_error)) + @Suppress("DEPRECATION") var cursor = contentResolver.query(contentUri, arrayOf(MediaColumns.DATA), null, null, null) + var path: String? = null + if (cursor != null) { + try { + if (cursor.moveToFirst()) + path = cursor.getString(0) + } finally { + cursor.close() + } + } + if (path == null) { + path = "Download/" + cursor = contentResolver.query(contentUri, arrayOf(MediaColumns.DISPLAY_NAME), null, null, null) + if (cursor != null) { + try { + if (cursor.moveToFirst()) + path += cursor.getString(0) + } finally { + cursor.close() + } + } + } + DownloadsFile(context, contentStream, path, contentUri) + } else { + @Suppress("DEPRECATION") val path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + val file = File(path, name) + if (!path.isDirectory && !path.mkdirs()) + throw IOException(context.getString(R.string.create_output_dir_error)) + DownloadsFile(context, FileOutputStream(file), file.absolutePath, null) + } + + class DownloadsFile(private val context: Context, val outputStream: OutputStream, val fileName: String, private val uri: Uri?) { + fun delete() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) + context.contentResolver.delete(uri!!, null, null) + else + File(fileName).delete() + } + } +}