Merge pull request #14583 from nextcloud/tryResources
Use of Try-With-Resources
This commit is contained in:
commit
fa83d67bfa
@ -963,20 +963,12 @@ public final class ThumbnailsCacheManager {
|
|||||||
thumbnail = addThumbnailToCache(imageKey, bitmap, file.getPath(), px, px);
|
thumbnail = addThumbnailToCache(imageKey, bitmap, file.getPath(), px, px);
|
||||||
}
|
}
|
||||||
} else if (Type.VIDEO == type) {
|
} else if (Type.VIDEO == type) {
|
||||||
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
|
try (MediaMetadataRetriever retriever = new MediaMetadataRetriever()) {
|
||||||
try {
|
|
||||||
retriever.setDataSource(file.getAbsolutePath());
|
retriever.setDataSource(file.getAbsolutePath());
|
||||||
thumbnail = retriever.getFrameAtTime(-1);
|
thumbnail = retriever.getFrameAtTime(-1);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
// can't create a bitmap
|
// can't create a bitmap
|
||||||
Log_OC.w(TAG, "Failed to create bitmap from video " + file.getAbsolutePath());
|
Log_OC.w(TAG, "Failed to create bitmap from video " + file.getAbsolutePath());
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
retriever.release();
|
|
||||||
} catch (RuntimeException | IOException ex) {
|
|
||||||
// Ignore failure at this point.
|
|
||||||
Log_OC.w(TAG, "Failed release MediaMetadataRetriever for " + file.getAbsolutePath());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (thumbnail != null) {
|
if (thumbnail != null) {
|
||||||
|
@ -953,15 +953,11 @@ public class UploadFileOperation extends SyncOperation {
|
|||||||
File temporalFile = null;
|
File temporalFile = null;
|
||||||
File originalFile = new File(mOriginalStoragePath);
|
File originalFile = new File(mOriginalStoragePath);
|
||||||
File expectedFile = null;
|
File expectedFile = null;
|
||||||
FileLock fileLock = null;
|
|
||||||
FileChannel channel = null;
|
|
||||||
|
|
||||||
long size;
|
long size;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// check conditions
|
// check conditions
|
||||||
result = checkConditions(originalFile);
|
result = checkConditions(originalFile);
|
||||||
|
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -983,107 +979,121 @@ public class UploadFileOperation extends SyncOperation {
|
|||||||
|
|
||||||
// Get the last modification date of the file from the file system
|
// Get the last modification date of the file from the file system
|
||||||
long lastModifiedTimestamp = originalFile.lastModified() / 1000;
|
long lastModifiedTimestamp = originalFile.lastModified() / 1000;
|
||||||
|
|
||||||
final Long creationTimestamp = FileUtil.getCreationTimestamp(originalFile);
|
final Long creationTimestamp = FileUtil.getCreationTimestamp(originalFile);
|
||||||
|
|
||||||
try {
|
// Initialize channel and fileLock in try-with-resources
|
||||||
channel = new RandomAccessFile(mFile.getStoragePath(), "rw").getChannel();
|
try (
|
||||||
fileLock = channel.tryLock();
|
FileChannel channel = new RandomAccessFile(mFile.getStoragePath(), "rw").getChannel();
|
||||||
} catch (FileNotFoundException e) {
|
FileLock fileLock = channel.tryLock()
|
||||||
// this basically means that the file is on SD card
|
) {
|
||||||
// try to copy file to temporary dir if it doesn't exist
|
if (fileLock == null) {
|
||||||
String temporalPath = FileStorageUtils.getInternalTemporalPath(user.getAccountName(), mContext) +
|
// Handle the case when the file lock cannot be acquired
|
||||||
mFile.getRemotePath();
|
String temporalPath = FileStorageUtils.getInternalTemporalPath(user.getAccountName(), mContext) + mFile.getRemotePath();
|
||||||
mFile.setStoragePath(temporalPath);
|
mFile.setStoragePath(temporalPath);
|
||||||
temporalFile = new File(temporalPath);
|
temporalFile = new File(temporalPath);
|
||||||
|
|
||||||
Files.deleteIfExists(Paths.get(temporalPath));
|
Files.deleteIfExists(Paths.get(temporalPath));
|
||||||
result = copy(originalFile, temporalFile);
|
result = copy(originalFile, temporalFile);
|
||||||
|
|
||||||
if (result.isSuccess()) {
|
if (result.isSuccess()) {
|
||||||
if (temporalFile.length() == originalFile.length()) {
|
if (temporalFile.length() == originalFile.length()) {
|
||||||
channel = new RandomAccessFile(temporalFile.getAbsolutePath(), "rw").getChannel();
|
// Acquire lock on temporary file
|
||||||
fileLock = channel.tryLock();
|
try (FileChannel tempChannel = new RandomAccessFile(temporalFile.getAbsolutePath(), "rw").getChannel();
|
||||||
|
FileLock tempFileLock = tempChannel.tryLock()) {
|
||||||
|
if (tempFileLock != null) {
|
||||||
|
// Use the temporary channel for the upload
|
||||||
|
size = tempChannel.size();
|
||||||
|
updateSize(size);
|
||||||
|
|
||||||
|
// Perform the upload operation
|
||||||
|
if (size > ChunkedFileUploadRemoteOperation.CHUNK_SIZE_MOBILE) {
|
||||||
|
boolean onWifiConnection = connectivityService.getConnectivity().isWifi();
|
||||||
|
mUploadOperation = new ChunkedFileUploadRemoteOperation(
|
||||||
|
mFile.getStoragePath(),
|
||||||
|
mFile.getRemotePath(),
|
||||||
|
mFile.getMimeType(),
|
||||||
|
mFile.getEtagInConflict(),
|
||||||
|
lastModifiedTimestamp,
|
||||||
|
creationTimestamp,
|
||||||
|
onWifiConnection,
|
||||||
|
mDisableRetries
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
mUploadOperation = new UploadFileRemoteOperation(
|
||||||
|
mFile.getStoragePath(),
|
||||||
|
mFile.getRemotePath(),
|
||||||
|
mFile.getMimeType(),
|
||||||
|
mFile.getEtagInConflict(),
|
||||||
|
lastModifiedTimestamp,
|
||||||
|
creationTimestamp,
|
||||||
|
mDisableRetries
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (result.isSuccess() && mUploadOperation != null) {
|
||||||
|
result = mUploadOperation.execute(client);
|
||||||
|
if (!result.isSuccess() && result.getHttpCode() == HttpStatus.SC_PRECONDITION_FAILED) {
|
||||||
|
result = new RemoteOperationResult(ResultCode.SYNC_CONFLICT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result = new RemoteOperationResult(ResultCode.LOCK_FAILED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result = new RemoteOperationResult(ResultCode.LOCK_FAILED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
size = channel.size();
|
||||||
|
updateSize(size);
|
||||||
|
|
||||||
|
// Perform the upload operation
|
||||||
|
if (size > ChunkedFileUploadRemoteOperation.CHUNK_SIZE_MOBILE) {
|
||||||
|
boolean onWifiConnection = connectivityService.getConnectivity().isWifi();
|
||||||
|
mUploadOperation = new ChunkedFileUploadRemoteOperation(
|
||||||
|
mFile.getStoragePath(),
|
||||||
|
mFile.getRemotePath(),
|
||||||
|
mFile.getMimeType(),
|
||||||
|
mFile.getEtagInConflict(),
|
||||||
|
lastModifiedTimestamp,
|
||||||
|
creationTimestamp,
|
||||||
|
onWifiConnection,
|
||||||
|
mDisableRetries
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
result = new RemoteOperationResult(ResultCode.LOCK_FAILED);
|
mUploadOperation = new UploadFileRemoteOperation(
|
||||||
|
mFile.getStoragePath(),
|
||||||
|
mFile.getRemotePath(),
|
||||||
|
mFile.getMimeType(),
|
||||||
|
mFile.getEtagInConflict(),
|
||||||
|
lastModifiedTimestamp,
|
||||||
|
creationTimestamp,
|
||||||
|
mDisableRetries
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.isSuccess() && mUploadOperation != null) {
|
||||||
|
result = mUploadOperation.execute(client);
|
||||||
|
if (!result.isSuccess() && result.getHttpCode() == HttpStatus.SC_PRECONDITION_FAILED) {
|
||||||
|
result = new RemoteOperationResult(ResultCode.SYNC_CONFLICT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
Log_OC.d(TAG, mOriginalStoragePath + " not exists anymore");
|
||||||
|
result = new RemoteOperationResult(ResultCode.LOCAL_FILE_NOT_FOUND);
|
||||||
|
} catch (OverlappingFileLockException e) {
|
||||||
|
Log_OC.d(TAG, "Overlapping file lock exception");
|
||||||
|
result = new RemoteOperationResult(ResultCode.LOCK_FAILED);
|
||||||
|
} catch (Exception e) {
|
||||||
|
result = new RemoteOperationResult(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
// Finalize cleanup
|
||||||
size = channel.size();
|
|
||||||
} catch (Exception e1) {
|
|
||||||
size = new File(mFile.getStoragePath()).length();
|
|
||||||
}
|
|
||||||
|
|
||||||
updateSize(size);
|
|
||||||
|
|
||||||
// perform the upload
|
|
||||||
if (size > ChunkedFileUploadRemoteOperation.CHUNK_SIZE_MOBILE) {
|
|
||||||
boolean onWifiConnection = connectivityService.getConnectivity().isWifi();
|
|
||||||
|
|
||||||
mUploadOperation = new ChunkedFileUploadRemoteOperation(mFile.getStoragePath(),
|
|
||||||
mFile.getRemotePath(),
|
|
||||||
mFile.getMimeType(),
|
|
||||||
mFile.getEtagInConflict(),
|
|
||||||
lastModifiedTimestamp,
|
|
||||||
creationTimestamp,
|
|
||||||
onWifiConnection,
|
|
||||||
mDisableRetries);
|
|
||||||
} else {
|
|
||||||
mUploadOperation = new UploadFileRemoteOperation(mFile.getStoragePath(),
|
|
||||||
mFile.getRemotePath(),
|
|
||||||
mFile.getMimeType(),
|
|
||||||
mFile.getEtagInConflict(),
|
|
||||||
lastModifiedTimestamp,
|
|
||||||
creationTimestamp,
|
|
||||||
mDisableRetries);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (OnDatatransferProgressListener mDataTransferListener : mDataTransferListeners) {
|
|
||||||
mUploadOperation.addDataTransferProgressListener(mDataTransferListener);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mCancellationRequested.get()) {
|
|
||||||
throw new OperationCancelledException();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result.isSuccess() && mUploadOperation != null) {
|
|
||||||
result = mUploadOperation.execute(client);
|
|
||||||
|
|
||||||
/// move local temporal file or original file to its corresponding
|
|
||||||
// location in the Nextcloud local folder
|
|
||||||
if (!result.isSuccess() && result.getHttpCode() == HttpStatus.SC_PRECONDITION_FAILED) {
|
|
||||||
result = new RemoteOperationResult(ResultCode.SYNC_CONFLICT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
Log_OC.d(TAG, mOriginalStoragePath + " not exists anymore");
|
|
||||||
result = new RemoteOperationResult(ResultCode.LOCAL_FILE_NOT_FOUND);
|
|
||||||
} catch (OverlappingFileLockException e) {
|
|
||||||
Log_OC.d(TAG, "Overlapping file lock exception");
|
|
||||||
result = new RemoteOperationResult(ResultCode.LOCK_FAILED);
|
|
||||||
} catch (Exception e) {
|
|
||||||
result = new RemoteOperationResult(e);
|
|
||||||
} finally {
|
|
||||||
mUploadStarted.set(false);
|
mUploadStarted.set(false);
|
||||||
|
|
||||||
if (fileLock != null) {
|
|
||||||
try {
|
|
||||||
fileLock.release();
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log_OC.e(TAG, "Failed to unlock file with path " + mOriginalStoragePath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (channel != null) {
|
|
||||||
try {
|
|
||||||
channel.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log_OC.w(TAG, "Failed to close file channel");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (temporalFile != null && !originalFile.equals(temporalFile)) {
|
if (temporalFile != null && !originalFile.equals(temporalFile)) {
|
||||||
temporalFile.delete();
|
temporalFile.delete();
|
||||||
}
|
}
|
||||||
@ -1093,6 +1103,8 @@ public class UploadFileOperation extends SyncOperation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logResult(result, mOriginalStoragePath, mRemotePath);
|
logResult(result, mOriginalStoragePath, mRemotePath);
|
||||||
|
} catch (Exception e) {
|
||||||
|
result = new RemoteOperationResult(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result.isSuccess()) {
|
if (result.isSuccess()) {
|
||||||
@ -1101,7 +1113,7 @@ public class UploadFileOperation extends SyncOperation {
|
|||||||
getStorageManager().saveConflict(mFile, mFile.getEtagInConflict());
|
getStorageManager().saveConflict(mFile, mFile.getEtagInConflict());
|
||||||
}
|
}
|
||||||
|
|
||||||
// delete temporal file
|
// Delete temporal file
|
||||||
if (temporalFile != null && temporalFile.exists() && !temporalFile.delete()) {
|
if (temporalFile != null && temporalFile.exists() && !temporalFile.delete()) {
|
||||||
Log_OC.e(TAG, "Could not delete temporal file " + temporalFile.getAbsolutePath());
|
Log_OC.e(TAG, "Could not delete temporal file " + temporalFile.getAbsolutePath());
|
||||||
}
|
}
|
||||||
@ -1109,6 +1121,7 @@ public class UploadFileOperation extends SyncOperation {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void updateSize(long size) {
|
private void updateSize(long size) {
|
||||||
OCUpload ocUpload = uploadsStorageManager.getUploadById(getOCUploadId());
|
OCUpload ocUpload = uploadsStorageManager.getUploadById(getOCUploadId());
|
||||||
if (ocUpload != null) {
|
if (ocUpload != null) {
|
||||||
@ -1532,22 +1545,16 @@ public class UploadFileOperation extends SyncOperation {
|
|||||||
if (!sourceFile.renameTo(targetFile)) {
|
if (!sourceFile.renameTo(targetFile)) {
|
||||||
// try to copy and then delete
|
// try to copy and then delete
|
||||||
targetFile.createNewFile();
|
targetFile.createNewFile();
|
||||||
FileChannel inChannel = new FileInputStream(sourceFile).getChannel();
|
try (
|
||||||
FileChannel outChannel = new FileOutputStream(targetFile).getChannel();
|
FileChannel inChannel = new FileInputStream(sourceFile).getChannel();
|
||||||
try {
|
FileChannel outChannel = new FileOutputStream(targetFile).getChannel()
|
||||||
|
) {
|
||||||
inChannel.transferTo(0, inChannel.size(), outChannel);
|
inChannel.transferTo(0, inChannel.size(), outChannel);
|
||||||
sourceFile.delete();
|
sourceFile.delete();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
mFile.setStoragePath(""); // forget the local file
|
mFile.setStoragePath(""); // forget the local file
|
||||||
// by now, treat this as a success; the file was uploaded
|
// by now, treat this as a success; the file was uploaded
|
||||||
// the best option could be show a warning message
|
// the best option could be show a warning message
|
||||||
} finally {
|
|
||||||
if (inChannel != null) {
|
|
||||||
inChannel.close();
|
|
||||||
}
|
|
||||||
if (outChannel != null) {
|
|
||||||
outChannel.close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,9 +117,6 @@ public class CopyAndUploadContentUrisTask extends AsyncTask<Object, Void, Result
|
|||||||
protected ResultCode doInBackground(Object[] params) {
|
protected ResultCode doInBackground(Object[] params) {
|
||||||
|
|
||||||
ResultCode result = ResultCode.UNKNOWN_ERROR;
|
ResultCode result = ResultCode.UNKNOWN_ERROR;
|
||||||
|
|
||||||
InputStream inputStream = null;
|
|
||||||
FileOutputStream outputStream = null;
|
|
||||||
String fullTempPath = null;
|
String fullTempPath = null;
|
||||||
Uri currentUri = null;
|
Uri currentUri = null;
|
||||||
|
|
||||||
@ -137,11 +134,7 @@ public class CopyAndUploadContentUrisTask extends AsyncTask<Object, Void, Result
|
|||||||
currentRemotePath = remotePaths[i];
|
currentRemotePath = remotePaths[i];
|
||||||
|
|
||||||
long lastModified = 0;
|
long lastModified = 0;
|
||||||
try (Cursor cursor = leakedContentResolver.query(currentUri,
|
try (Cursor cursor = leakedContentResolver.query(currentUri, null, null, null, null)) {
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null)) {
|
|
||||||
if (cursor != null && cursor.moveToFirst()) {
|
if (cursor != null && cursor.moveToFirst()) {
|
||||||
// this check prevents a crash when last modification time is not available on certain phones
|
// this check prevents a crash when last modification time is not available on certain phones
|
||||||
int columnIndex = cursor.getColumnIndex(DocumentsContract.Document.COLUMN_LAST_MODIFIED);
|
int columnIndex = cursor.getColumnIndex(DocumentsContract.Document.COLUMN_LAST_MODIFIED);
|
||||||
@ -152,42 +145,37 @@ public class CopyAndUploadContentUrisTask extends AsyncTask<Object, Void, Result
|
|||||||
}
|
}
|
||||||
|
|
||||||
fullTempPath = FileStorageUtils.getTemporalPath(user.getAccountName()) + currentRemotePath;
|
fullTempPath = FileStorageUtils.getTemporalPath(user.getAccountName()) + currentRemotePath;
|
||||||
inputStream = leakedContentResolver.openInputStream(currentUri);
|
|
||||||
File cacheFile = new File(fullTempPath);
|
File cacheFile = new File(fullTempPath);
|
||||||
File tempDir = cacheFile.getParentFile();
|
File tempDir = cacheFile.getParentFile();
|
||||||
if (!tempDir.exists()) {
|
if (!tempDir.exists()) {
|
||||||
tempDir.mkdirs();
|
tempDir.mkdirs();
|
||||||
}
|
}
|
||||||
cacheFile.createNewFile();
|
cacheFile.createNewFile();
|
||||||
outputStream = new FileOutputStream(fullTempPath);
|
try (InputStream inputStream = leakedContentResolver.openInputStream(currentUri);
|
||||||
byte[] buffer = new byte[4096];
|
FileOutputStream outputStream = new FileOutputStream(fullTempPath)) {
|
||||||
|
byte[] buffer = new byte[4096];
|
||||||
int count;
|
int count;
|
||||||
while ((count = inputStream.read(buffer)) > 0) {
|
while ((count = inputStream.read(buffer)) > 0) {
|
||||||
outputStream.write(buffer, 0, count);
|
outputStream.write(buffer, 0, count);
|
||||||
}
|
|
||||||
|
|
||||||
if (lastModified != 0) {
|
|
||||||
try {
|
|
||||||
if (!cacheFile.setLastModified(lastModified)) {
|
|
||||||
Log_OC.w(TAG, "Could not change mtime of cacheFile");
|
|
||||||
}
|
|
||||||
} catch (SecurityException e) {
|
|
||||||
Log_OC.e(TAG, "Not enough permissions to change mtime of cacheFile", e);
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
Log_OC.e(TAG, "Could not change mtime of cacheFile, mtime is negativ: "+lastModified, e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lastModified != 0) {
|
||||||
|
try {
|
||||||
|
if (!cacheFile.setLastModified(lastModified)) {
|
||||||
|
Log_OC.w(TAG, "Could not change mtime of cacheFile");
|
||||||
|
}
|
||||||
|
} catch (SecurityException e) {
|
||||||
|
Log_OC.e(TAG, "Not enough permissions to change mtime of cacheFile", e);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
Log_OC.e(TAG, "Could not change mtime of cacheFile, mtime is negativ: " + lastModified, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
requestUpload(user, fullTempPath, currentRemotePath, behaviour);
|
||||||
|
fullTempPath = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
requestUpload(
|
|
||||||
user,
|
|
||||||
fullTempPath,
|
|
||||||
currentRemotePath,
|
|
||||||
behaviour
|
|
||||||
);
|
|
||||||
fullTempPath = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result = ResultCode.OK;
|
result = ResultCode.OK;
|
||||||
|
|
||||||
} catch (ArrayIndexOutOfBoundsException e) {
|
} catch (ArrayIndexOutOfBoundsException e) {
|
||||||
@ -206,7 +194,7 @@ public class CopyAndUploadContentUrisTask extends AsyncTask<Object, Void, Result
|
|||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log_OC.e(TAG, "Exception while copying " + currentUri + " to temporary file", e);
|
Log_OC.e(TAG, "Exception while copying " + currentUri + " to temporary file", e);
|
||||||
result = ResultCode.LOCAL_STORAGE_NOT_COPIED;
|
result = ResultCode.LOCAL_STORAGE_NOT_COPIED;
|
||||||
|
|
||||||
// clean
|
// clean
|
||||||
if (fullTempPath != null) {
|
if (fullTempPath != null) {
|
||||||
@ -216,22 +204,6 @@ public class CopyAndUploadContentUrisTask extends AsyncTask<Object, Void, Result
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} finally {
|
|
||||||
if (inputStream != null) {
|
|
||||||
try {
|
|
||||||
inputStream.close();
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log_OC.w(TAG, "Ignoring exception of inputStream closure");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (outputStream != null) {
|
|
||||||
try {
|
|
||||||
outputStream.close();
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log_OC.w(TAG, "Ignoring exception of outStream closure");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -1,68 +0,0 @@
|
|||||||
/*
|
|
||||||
* Nextcloud - Android Client
|
|
||||||
*
|
|
||||||
* SPDX-FileCopyrightText: 2018 Andy Scherzinger <info@andy-scherzinger.de>
|
|
||||||
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
|
|
||||||
*/
|
|
||||||
package com.owncloud.android.ui.decoration;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.res.TypedArray;
|
|
||||||
import android.graphics.Canvas;
|
|
||||||
import android.graphics.Rect;
|
|
||||||
import android.graphics.drawable.Drawable;
|
|
||||||
import android.util.DisplayMetrics;
|
|
||||||
import android.view.View;
|
|
||||||
|
|
||||||
import androidx.recyclerview.widget.DividerItemDecoration;
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DividerItemDecoration based on {@link DividerItemDecoration} adding a 72dp left padding.
|
|
||||||
*/
|
|
||||||
public class SimpleListItemDividerDecoration extends DividerItemDecoration {
|
|
||||||
private static final int[] ATTRS = new int[]{android.R.attr.listDivider};
|
|
||||||
|
|
||||||
private final Rect bounds = new Rect();
|
|
||||||
private Drawable divider;
|
|
||||||
private int leftPadding;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default divider will be used
|
|
||||||
*/
|
|
||||||
public SimpleListItemDividerDecoration(Context context) {
|
|
||||||
super(context, DividerItemDecoration.VERTICAL);
|
|
||||||
final TypedArray styledAttributes = context.obtainStyledAttributes(ATTRS);
|
|
||||||
divider = styledAttributes.getDrawable(0);
|
|
||||||
leftPadding = Math.round(72 * (context.getResources().getDisplayMetrics().xdpi / DisplayMetrics.DENSITY_DEFAULT));
|
|
||||||
styledAttributes.recycle();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDraw(Canvas canvas, RecyclerView parent, RecyclerView.State state) {
|
|
||||||
canvas.save();
|
|
||||||
final int right;
|
|
||||||
//noinspection AndroidLintNewApi - NewApi lint fails to handle overrides.
|
|
||||||
if (parent.getClipToPadding()) {
|
|
||||||
right = parent.getWidth() - parent.getPaddingRight();
|
|
||||||
canvas.clipRect(leftPadding, parent.getPaddingTop(), right,
|
|
||||||
parent.getHeight() - parent.getPaddingBottom());
|
|
||||||
} else {
|
|
||||||
right = parent.getWidth();
|
|
||||||
}
|
|
||||||
|
|
||||||
final int childCount = parent.getChildCount();
|
|
||||||
for (int i = 0; i < childCount; i++) {
|
|
||||||
final View child = parent.getChildAt(i);
|
|
||||||
parent.getDecoratedBoundsWithMargins(child, bounds);
|
|
||||||
final int bottom = bounds.bottom + Math.round(child.getTranslationY());
|
|
||||||
final int top = bottom - 1;
|
|
||||||
|
|
||||||
if (divider != null) {
|
|
||||||
divider.setBounds(leftPadding, top, right, bottom);
|
|
||||||
divider.draw(canvas);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
canvas.restore();
|
|
||||||
}
|
|
||||||
}
|
|
@ -113,11 +113,9 @@ public class AndroidCalendar {
|
|||||||
|
|
||||||
private static boolean missing(ContentResolver resolver, Uri uri) {
|
private static boolean missing(ContentResolver resolver, Uri uri) {
|
||||||
// Determine if a provider is missing
|
// Determine if a provider is missing
|
||||||
ContentProviderClient provider = resolver.acquireContentProviderClient(uri);
|
try (ContentProviderClient provider = resolver.acquireContentProviderClient(uri)) {
|
||||||
if (provider != null) {
|
return provider == null;
|
||||||
provider.release();
|
|
||||||
}
|
}
|
||||||
return provider == null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
Loading…
x
Reference in New Issue
Block a user