Convert FileHelper to Kotlin

pull/1127/head
Alex Baker 5 years ago
parent 81904e5888
commit e6926f5943

@ -93,7 +93,7 @@ class ShareLinkActivity : InjectingAppCompatActivity() {
?: uri.lastPathSegment
}
val basename = Files.getNameWithoutExtension(filename!!)
return Lists.newArrayList(FileHelper.copyToUri(context, preferences.attachmentsDirectory, uri, basename))
return Lists.newArrayList(FileHelper.copyToUri(context, preferences.attachmentsDirectory!!, uri, basename))
}
private fun copyMultipleAttachments(intent: Intent): ArrayList<Uri> {
@ -101,7 +101,7 @@ class ShareLinkActivity : InjectingAppCompatActivity() {
val uris = intent.getParcelableArrayListExtra<Uri>(Intent.EXTRA_STREAM)
if (uris != null) {
for (uri in uris) {
result.add(FileHelper.copyToUri(context, preferences.attachmentsDirectory, uri))
result.add(FileHelper.copyToUri(context, preferences.attachmentsDirectory!!, uri))
}
}
return result

@ -337,7 +337,7 @@ class TaskEditFragment : Fragment(), Toolbar.OnMenuItemClickListener {
val model = editViewModel.task!!
val userActivity = UserActivity()
if (picture != null) {
val output = FileHelper.copyToUri(context, preferences.attachmentsDirectory, picture)
val output = FileHelper.copyToUri(context, preferences.attachmentsDirectory!!, picture)
userActivity.setPicture(output)
}
userActivity.message = message

@ -132,14 +132,14 @@ class FilesControlSet : TaskEditControlFragment() {
}
private fun copyToAttachmentDirectory(input: Uri?) {
newAttachment(FileHelper.copyToUri(context, preferences.attachmentsDirectory, input))
newAttachment(FileHelper.copyToUri(requireContext(), preferences.attachmentsDirectory!!, input!!))
}
private fun newAttachment(output: Uri) {
val attachment = TaskAttachment(
viewModel.task!!.uuid,
output,
FileHelper.getFilename(context, output)!!)
FileHelper.getFilename(requireContext(), output)!!)
lifecycleScope.launch {
taskAttachmentDao.createNew(attachment)
addAttachment(attachment)

@ -83,12 +83,12 @@ class TasksJsonExporter @Inject constructor(
doTasksExport(os, tasks)
os!!.close()
val externalStorageBackup = FileHelper.newFile(
context,
preferences.backupDirectory,
context!!,
preferences.backupDirectory!!,
MIME,
Files.getNameWithoutExtension(filename),
EXTENSION)
FileHelper.copyStream(context, internalStorageBackup, externalStorageBackup)
FileHelper.copyStream(context!!, internalStorageBackup, externalStorageBackup)
workManager.scheduleDriveUpload(externalStorageBackup, exportType == ExportType.EXPORT_TYPE_SERVICE)
BackupManager(context).dataChanged()
}

@ -74,7 +74,7 @@ class DriveInvoker @Inject constructor(
@Throws(IOException::class)
suspend fun createFile(folderId: String, uri: Uri?) {
val mime = FileHelper.getMimeType(context, uri)
val mime = FileHelper.getMimeType(context, uri!!)
val metadata = File()
.setParents(listOf(folderId))
.setMimeType(mime)

@ -1,288 +0,0 @@
package org.tasks.files;
import static android.content.ContentResolver.SCHEME_CONTENT;
import static android.provider.DocumentsContract.EXTRA_INITIAL_URI;
import static androidx.core.content.FileProvider.getUriForFile;
import static com.google.common.collect.Iterables.any;
import static com.todoroo.astrid.utility.Constants.FILE_PROVIDER_AUTHORITY;
import static org.tasks.Strings.isNullOrEmpty;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.provider.OpenableColumns;
import android.webkit.MimeTypeMap;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.documentfile.provider.DocumentFile;
import androidx.fragment.app.Fragment;
import com.google.common.io.ByteStreams;
import com.google.common.io.Files;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.List;
import org.tasks.R;
import timber.log.Timber;
public class FileHelper {
public static final int MAX_FILENAME_LENGTH = 40;
public static Intent newFilePickerIntent(Activity activity, Uri initial, String... mimeTypes) {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.putExtra("android.content.extra.SHOW_ADVANCED", true);
intent.putExtra("android.content.extra.FANCY", true);
intent.putExtra("android.content.extra.SHOW_FILESIZE", true);
intent.addCategory(Intent.CATEGORY_OPENABLE);
setInitialUri(activity, intent, initial);
if (mimeTypes.length == 1) {
intent.setType(mimeTypes[0]);
} else {
intent.setType("*/*");
if (mimeTypes.length > 1) {
intent.putExtra(Intent.EXTRA_MIME_TYPES, mimeTypes);
}
}
return intent;
}
public static void newDirectoryPicker(Fragment fragment, int rc, @Nullable Uri initial) {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
intent.addFlags(
Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION
| Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);
intent.putExtra("android.content.extra.SHOW_ADVANCED", true);
intent.putExtra("android.content.extra.FANCY", true);
intent.putExtra("android.content.extra.SHOW_FILESIZE", true);
setInitialUri(fragment.getContext(), intent, initial);
fragment.startActivityForResult(intent, rc);
}
@TargetApi(Build.VERSION_CODES.O)
private static void setInitialUri(Context context, Intent intent, Uri uri) {
if (uri == null || !uri.getScheme().equals(SCHEME_CONTENT)) {
return;
}
try {
intent.putExtra(EXTRA_INITIAL_URI, DocumentFile.fromTreeUri(context, uri).getUri());
} catch (Exception e) {
Timber.e(e);
}
}
public static void delete(Context context, Uri uri) {
if (uri == null) {
return;
}
switch (uri.getScheme()) {
case "content":
DocumentFile documentFile = DocumentFile.fromSingleUri(context, uri);
documentFile.delete();
break;
case "file":
delete(new File(uri.getPath()));
break;
}
}
private static void delete(File... files) {
if (files == null) {
return;
}
for (File file : files) {
if (file.isDirectory()) {
delete(file.listFiles());
} else {
file.delete();
}
}
}
public @Nullable static String getFilename(Context context, Uri uri) {
switch (uri.getScheme()) {
case ContentResolver.SCHEME_FILE:
return uri.getLastPathSegment();
case SCHEME_CONTENT:
Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
try {
return cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
} finally {
cursor.close();
}
}
break;
}
return null;
}
public static String getExtension(Context context, Uri uri) {
if (uri.getScheme().equals(ContentResolver.SCHEME_CONTENT)) {
String mimeType = context.getContentResolver().getType(uri);
String extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(mimeType);
if (!isNullOrEmpty(extension)) {
return extension;
}
}
String extension = MimeTypeMap.getFileExtensionFromUrl(uri.getPath());
if (!isNullOrEmpty(extension)) {
return extension;
}
return Files.getFileExtension(getFilename(context, uri));
}
public static String getMimeType(Context context, Uri uri) {
String mimeType = context.getContentResolver().getType(uri);
if (!isNullOrEmpty(mimeType)) {
return mimeType;
}
String extension = getExtension(context, uri);
return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
}
public static void startActionView(Activity context, Uri uri) {
if (uri == null) {
return;
}
String mimeType = getMimeType(context, uri);
Intent intent = new Intent(Intent.ACTION_VIEW);
if (uri.getScheme().equals(SCHEME_CONTENT)) {
uri = copyToUri(context, Uri.fromFile(context.getExternalCacheDir()), uri);
}
Uri share = getUriForFile(context, FILE_PROVIDER_AUTHORITY, new File(uri.getPath()));
intent.setDataAndType(share, mimeType);
grantReadPermissions(intent);
PackageManager packageManager = context.getPackageManager();
if (intent.resolveActivity(packageManager) != null) {
context.startActivity(intent);
} else {
Toast.makeText(context, R.string.no_application_found, Toast.LENGTH_SHORT).show();
}
}
private static void grantReadPermissions(Intent intent) {
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
public static Uri newFile(
Context context, Uri destination, String mimeType, String baseName, String extension)
throws IOException {
String filename = getNonCollidingFileName(context, destination, baseName, extension);
switch (destination.getScheme()) {
case "content":
DocumentFile tree = DocumentFile.fromTreeUri(context, destination);
DocumentFile f1 = tree.createFile(mimeType, filename);
if (f1 == null) {
throw new FileNotFoundException("Failed to create " + filename);
}
return f1.getUri();
case "file":
File dir = new File(destination.getPath());
if (!dir.exists() && !dir.mkdirs()) {
throw new IOException("Failed to create %s" + dir.getAbsolutePath());
}
File f2 = new File(dir.getAbsolutePath() + File.separator + filename);
if (f2.createNewFile()) {
return Uri.fromFile(f2);
}
throw new FileNotFoundException("Failed to create " + filename);
default:
throw new IllegalArgumentException("Unknown URI scheme: " + destination.getScheme());
}
}
public static Uri copyToUri(Context context, Uri destination, Uri input) {
String filename = getFilename(context, input);
return copyToUri(context, destination, input, Files.getNameWithoutExtension(filename));
}
public static Uri copyToUri(Context context, Uri destination, Uri input, String basename) {
try {
Uri output =
newFile(
context,
destination,
getMimeType(context, input),
basename,
getExtension(context, input));
copyStream(context, input, output);
return output;
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
public static void copyStream(Context context, Uri input, Uri output) {
ContentResolver contentResolver = context.getContentResolver();
try {
InputStream inputStream = contentResolver.openInputStream(input);
OutputStream outputStream = contentResolver.openOutputStream(output);
ByteStreams.copy(inputStream, outputStream);
inputStream.close();
outputStream.close();
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
private static String getNonCollidingFileName(
Context context, Uri uri, String baseName, String extension) {
int tries = 1;
if (!extension.startsWith(".")) {
extension = "." + extension;
}
String tempName = baseName;
switch (uri.getScheme()) {
case SCHEME_CONTENT:
DocumentFile dir = DocumentFile.fromTreeUri(context, uri);
List<DocumentFile> documentFiles = Arrays.asList(dir.listFiles());
while (true) {
String result = tempName + extension;
if (any(documentFiles, f -> f.getName().equals(result))) {
tempName = baseName + "-" + tries;
tries++;
} else {
break;
}
}
break;
case ContentResolver.SCHEME_FILE:
File f = new File(uri.getPath(), baseName + extension);
while (f.exists()) {
tempName = baseName + "-" + tries; // $NON-NLS-1$
f = new File(uri.getPath(), tempName + extension);
tries++;
}
break;
}
return tempName + extension;
}
public static String uri2String(@Nullable Uri uri) {
if (uri == null) {
return "";
}
if (uri.getScheme().equals(ContentResolver.SCHEME_FILE)) {
return new File(uri.getPath()).getAbsolutePath();
}
return uri.toString();
}
}

@ -0,0 +1,265 @@
package org.tasks.files
import android.annotation.TargetApi
import android.app.Activity
import android.content.ContentResolver
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.provider.DocumentsContract
import android.provider.OpenableColumns
import android.webkit.MimeTypeMap
import android.widget.Toast
import androidx.core.content.FileProvider
import androidx.documentfile.provider.DocumentFile
import androidx.fragment.app.Fragment
import com.google.common.collect.Iterables
import com.google.common.io.ByteStreams
import com.google.common.io.Files
import com.todoroo.astrid.utility.Constants
import org.tasks.R
import org.tasks.Strings.isNullOrEmpty
import timber.log.Timber
import java.io.File
import java.io.FileNotFoundException
import java.io.IOException
import java.util.*
object FileHelper {
const val MAX_FILENAME_LENGTH = 40
fun newFilePickerIntent(activity: Activity?, initial: Uri?, vararg mimeTypes: String?): Intent {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
intent.putExtra("android.content.extra.SHOW_ADVANCED", true)
intent.putExtra("android.content.extra.FANCY", true)
intent.putExtra("android.content.extra.SHOW_FILESIZE", true)
intent.addCategory(Intent.CATEGORY_OPENABLE)
setInitialUri(activity, intent, initial)
if (mimeTypes.size == 1) {
intent.type = mimeTypes[0]
} else {
intent.type = "*/*"
if (mimeTypes.size > 1) {
intent.putExtra(Intent.EXTRA_MIME_TYPES, mimeTypes)
}
}
return intent
}
fun newDirectoryPicker(fragment: Fragment, rc: Int, initial: Uri?) {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
intent.addFlags(
Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
or Intent.FLAG_GRANT_READ_URI_PERMISSION
or Intent.FLAG_GRANT_PREFIX_URI_PERMISSION)
intent.putExtra("android.content.extra.SHOW_ADVANCED", true)
intent.putExtra("android.content.extra.FANCY", true)
intent.putExtra("android.content.extra.SHOW_FILESIZE", true)
setInitialUri(fragment.context, intent, initial)
fragment.startActivityForResult(intent, rc)
}
@TargetApi(Build.VERSION_CODES.O)
private fun setInitialUri(context: Context?, intent: Intent, uri: Uri?) {
if (uri == null || uri.scheme != ContentResolver.SCHEME_CONTENT) {
return
}
try {
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, DocumentFile.fromTreeUri(context!!, uri)!!.uri)
} catch (e: Exception) {
Timber.e(e)
}
}
fun delete(context: Context?, uri: Uri?) {
if (uri == null) {
return
}
when (uri.scheme) {
"content" -> {
val documentFile = DocumentFile.fromSingleUri(context!!, uri)
documentFile!!.delete()
}
"file" -> delete(File(uri.path))
}
}
private fun delete(vararg files: File) {
if (files == null) {
return
}
for (file in files) {
if (file.isDirectory) {
delete(*file.listFiles())
} else {
file.delete()
}
}
}
fun getFilename(context: Context, uri: Uri): String? {
when (uri.scheme) {
ContentResolver.SCHEME_FILE -> return uri.lastPathSegment
ContentResolver.SCHEME_CONTENT -> {
val cursor = context.contentResolver.query(uri, null, null, null, null)
if (cursor != null && cursor.moveToFirst()) {
return try {
cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME))
} finally {
cursor.close()
}
}
}
}
return null
}
fun getExtension(context: Context, uri: Uri): String? {
if (uri.scheme == ContentResolver.SCHEME_CONTENT) {
val mimeType = context.contentResolver.getType(uri)
val extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(mimeType)
if (!isNullOrEmpty(extension)) {
return extension
}
}
val extension = MimeTypeMap.getFileExtensionFromUrl(uri.path)
return if (!isNullOrEmpty(extension)) {
extension
} else Files.getFileExtension(getFilename(context, uri)!!)
}
fun getMimeType(context: Context, uri: Uri): String? {
val mimeType = context.contentResolver.getType(uri)
if (!isNullOrEmpty(mimeType)) {
return mimeType
}
val extension = getExtension(context, uri)
return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension)
}
fun startActionView(context: Activity, uri: Uri?) {
var uri = uri ?: return
val mimeType = getMimeType(context, uri)
val intent = Intent(Intent.ACTION_VIEW)
if (uri.scheme == ContentResolver.SCHEME_CONTENT) {
uri = copyToUri(context, Uri.fromFile(context.externalCacheDir), uri)
}
val share = FileProvider.getUriForFile(context, Constants.FILE_PROVIDER_AUTHORITY, File(uri.path))
intent.setDataAndType(share, mimeType)
grantReadPermissions(intent)
val packageManager = context.packageManager
if (intent.resolveActivity(packageManager) != null) {
context.startActivity(intent)
} else {
Toast.makeText(context, R.string.no_application_found, Toast.LENGTH_SHORT).show()
}
}
private fun grantReadPermissions(intent: Intent) {
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
@JvmStatic
@Throws(IOException::class)
fun newFile(
context: Context, destination: Uri, mimeType: String?, baseName: String, extension: String?): Uri {
val filename = getNonCollidingFileName(context, destination, baseName, extension)
return when (destination.scheme) {
"content" -> {
val tree = DocumentFile.fromTreeUri(context, destination)
val f1 = tree!!.createFile(mimeType!!, filename)
?: throw FileNotFoundException("Failed to create $filename")
f1.uri
}
"file" -> {
val dir = File(destination.path)
if (!dir.exists() && !dir.mkdirs()) {
throw IOException("Failed to create %s" + dir.absolutePath)
}
val f2 = File(dir.absolutePath + File.separator + filename)
if (f2.createNewFile()) {
return Uri.fromFile(f2)
}
throw FileNotFoundException("Failed to create $filename")
}
else -> throw IllegalArgumentException("Unknown URI scheme: " + destination.scheme)
}
}
fun copyToUri(context: Context, destination: Uri, input: Uri): Uri {
val filename = getFilename(context, input)
return copyToUri(context, destination, input, Files.getNameWithoutExtension(filename!!))
}
fun copyToUri(context: Context, destination: Uri, input: Uri, basename: String): Uri {
return try {
val output = newFile(
context,
destination,
getMimeType(context, input),
basename,
getExtension(context, input))
copyStream(context, input, output)
output
} catch (e: IOException) {
throw IllegalStateException(e)
}
}
fun copyStream(context: Context, input: Uri?, output: Uri?) {
val contentResolver = context.contentResolver
try {
val inputStream = contentResolver.openInputStream(input!!)
val outputStream = contentResolver.openOutputStream(output!!)
ByteStreams.copy(inputStream!!, outputStream!!)
inputStream.close()
outputStream.close()
} catch (e: IOException) {
throw IllegalStateException(e)
}
}
private fun getNonCollidingFileName(
context: Context, uri: Uri, baseName: String, extension: String?): String {
var extension = extension
var tries = 1
if (!extension!!.startsWith(".")) {
extension = ".$extension"
}
var tempName = baseName
when (uri.scheme) {
ContentResolver.SCHEME_CONTENT -> {
val dir = DocumentFile.fromTreeUri(context, uri)
val documentFiles = Arrays.asList(*dir!!.listFiles())
while (true) {
val result = tempName + extension
if (Iterables.any(documentFiles) { f: DocumentFile? -> f!!.name == result }) {
tempName = "$baseName-$tries"
tries++
} else {
break
}
}
}
ContentResolver.SCHEME_FILE -> {
var f = File(uri.path, baseName + extension)
while (f.exists()) {
tempName = "$baseName-$tries" // $NON-NLS-1$
f = File(uri.path, tempName + extension)
tries++
}
}
}
return tempName + extension
}
fun uri2String(uri: Uri?): String {
if (uri == null) {
return ""
}
return if (uri.scheme == ContentResolver.SCHEME_FILE) {
File(uri.path).absolutePath
} else uri.toString()
}
}

@ -162,7 +162,7 @@ class Backups : InjectingPreferenceFragment() {
} else if (requestCode == REQUEST_PICKER) {
if (resultCode == RESULT_OK) {
val uri = data!!.data
val extension = FileHelper.getExtension(activity, uri)
val extension = FileHelper.getExtension(requireContext(), uri!!)
if (!("json".equals(extension, ignoreCase = true) || "xml".equals(
extension,
ignoreCase = true

Loading…
Cancel
Save