Skip to content

Commit

Permalink
Add error if file deletion fails
Browse files Browse the repository at this point in the history
  • Loading branch information
gzsombor committed Jan 20, 2021
1 parent 5d8937a commit 384cd49
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 51 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -487,23 +487,6 @@ public void setRetrievalTimestamp(Long retrievalTimestamp) {
this.retrievalTimestamp = retrievalTimestamp;
}

/**
* Remove local copy of this video, and delete it from the VideoDownloads DB.
*/
public void removeDownload() {
DownloadedVideosDb.getVideoDownloadsDb().removeDownload(getVideoId());
}

/**
* Get the Uri for the local copy of this Video.
*
* @return Uri
*/
public DownloadedVideosDb.Status getDownloadedFileStatus() {
return DownloadedVideosDb.getVideoDownloadsDb().getVideoFileUriAndValidate(getVideoId());
}


/**
* Returns whether or not this video has been downloaded.
*
Expand All @@ -513,7 +496,6 @@ public boolean isDownloaded() {
return DownloadedVideosDb.getVideoDownloadsDb().isVideoDownloaded(YouTubeVideo.this.getVideoId());
}


/**
* Downloads this video.
*
Expand Down Expand Up @@ -580,22 +562,20 @@ public void onGetDesiredStreamError(Throwable throwable) {
* Play the video using an external app
*/
public void playVideoExternally(Context context) {
DownloadedVideosDb.Status fileStatus = getDownloadedFileStatus();
if (fileStatus != null) {
DownloadedVideosDb.Status fileStatus = DownloadedVideosDb.getVideoDownloadsDb().getDownloadedFileStatus(context, getVideoId());
if (fileStatus.getLocalVideoFile() != null) {
Uri uri;
File file = fileStatus.getLocalVideoFile();
if (file != null) {
try {
uri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".provider", file);
} catch (Exception e) {
Logger.e(YouTubeVideo.this, "Error accessing path: " + file + ", message:" + e.getMessage(), e);
uri = fileStatus.getUri();
}
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
context.startActivity(intent);
return;
try {
uri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".provider", file);
} catch (Exception e) {
Logger.e(YouTubeVideo.this, "Error accessing path: " + file + ", message:" + e.getMessage(), e);
uri = fileStatus.getUri();
}
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
context.startActivity(intent);
return;
}
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(getVideoUrl()));
context.startActivity(browserIntent);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.util.Log;
import android.widget.Toast;

import androidx.annotation.NonNull;

Expand All @@ -21,6 +22,7 @@
import java.util.List;
import java.util.Set;

import free.rm.skytube.R;
import free.rm.skytube.app.Settings;
import free.rm.skytube.app.SkyTubeApp;
import free.rm.skytube.businessobjects.AsyncTaskParallel;
Expand Down Expand Up @@ -96,6 +98,18 @@ public String toString() {
}
}

public static class FileDeletionFailed extends Exception {
String path;
FileDeletionFailed(String path) {
super("File deletion failed for "+path);
this.path = path;
}

public String getPath() {
return path;
}
}

public interface DownloadedVideosListener {
void onDownloadedVideosUpdated();
}
Expand Down Expand Up @@ -232,17 +246,21 @@ public boolean remove(YouTubeVideo video) {
/**
* Remove local copy of this video, and delete it from the VideoDownloads DB.
*/
public void removeDownload(VideoId videoId) {
Status status = getVideoFileStatus(videoId);
Log.i(TAG, "removeDownload for " + videoId + " -> " + status);
if (status != null) {
deleteIfExists(status.getLocalAudioFile());
deleteIfExists(status.getLocalVideoFile());
remove(videoId.getId());
final Settings settings = SkyTubeApp.getSettings();
if (settings.isDownloadToSeparateFolders()) {
removeParentFolderIfEmpty(status, settings.getDownloadParentFolder());
public void removeDownload(Context ctx, VideoId videoId) {
try {
Status status = getVideoFileStatus(videoId);
Log.i(TAG, "removeDownload for " + videoId + " -> " + status);
if (status != null) {
deleteIfExists(status.getLocalAudioFile());
deleteIfExists(status.getLocalVideoFile());
remove(videoId.getId());
final Settings settings = SkyTubeApp.getSettings();
if (settings.isDownloadToSeparateFolders()) {
removeParentFolderIfEmpty(status, settings.getDownloadParentFolder());
}
}
} catch (FileDeletionFailed exc) {
displayError(ctx, exc);
}
}

Expand Down Expand Up @@ -315,7 +333,7 @@ private Uri getUri(Cursor cursor, int columnIndex) {
* @param videoId the id of the video
* @return the status, never null
*/
public Status getVideoFileUriAndValidate(VideoId videoId) {
public @NonNull Status getVideoFileUriAndValidate(@NonNull VideoId videoId) throws FileDeletionFailed {
Status downloadStatus = getVideoFileStatus(videoId);
if (downloadStatus != null) {
File localVideo = downloadStatus.getLocalVideoFile();
Expand All @@ -339,10 +357,32 @@ public Status getVideoFileUriAndValidate(VideoId videoId) {
return new Status(null,null, false);
}

private void deleteIfExists(File file) {
/**
* Get the Uri for the local copy of this Video, if the file is missing, or incorrect state, it tries to cleanup,
* and notifies the user about that error
*
* @return Status object - never null
*/
public @NonNull DownloadedVideosDb.Status getDownloadedFileStatus(Context context, @NonNull VideoId videoId) {
try {
return getVideoFileUriAndValidate(videoId);
} catch (DownloadedVideosDb.FileDeletionFailed exc) {
displayError(context, exc);
return new Status(null, null, true);
}
}

private void displayError(Context context, DownloadedVideosDb.FileDeletionFailed fileDeletionFailed) {
Logger.e(this, "Unable to delete file : %s", fileDeletionFailed.getPath());
Toast.makeText(context, context.getString(R.string.unable_to_delete_file, fileDeletionFailed.getPath()), Toast.LENGTH_LONG).show();
}

private void deleteIfExists(File file) throws FileDeletionFailed {
if (file != null && file.exists()) {
Log.i(TAG, "File exists " + file.getAbsolutePath());
file.delete();
if (!file.delete()) {
throw new FileDeletionFailed(file.getAbsolutePath());
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import free.rm.skytube.businessobjects.YouTube.POJOs.YouTubePlaylist;
import free.rm.skytube.businessobjects.YouTube.POJOs.YouTubeVideo;
import free.rm.skytube.businessobjects.db.DatabaseTasks;
import free.rm.skytube.businessobjects.db.DownloadedVideosDb;
import free.rm.skytube.businessobjects.db.PlaybackStatusDb;
import free.rm.skytube.businessobjects.db.SubscriptionsDb;
import free.rm.skytube.gui.activities.ThumbnailViewerActivity;
Expand Down Expand Up @@ -332,7 +333,7 @@ private void onOptionsButtonClick(final View view, YouTubeVideo youTubeVideo) {
context.startActivity(i);
return true;
case R.id.delete_download:
youTubeVideo.removeDownload();
DownloadedVideosDb.getVideoDownloadsDb().removeDownload(context, youTubeVideo.getVideoId());
return true;
case R.id.download_video:
final Policy decision = new MobileNetworkWarningDialog(view.getContext())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -788,12 +788,11 @@ private void loadVideo(boolean showMobileNetworkWarning) {
videoView.pause();
videoView.stopPlayback();
loadingVideoView.setVisibility(View.VISIBLE);
DownloadedVideosDb.Status status = youTubeVideo.getDownloadedFileStatus();
if (status != null && status.getLocalVideoFile() != null) {
DownloadedVideosDb.Status status = DownloadedVideosDb.getVideoDownloadsDb().getDownloadedFileStatus(getContext(), youTubeVideo.getVideoId());
if (status.getLocalVideoFile() != null) {
File file = status.getLocalVideoFile();
// If the file for this video has gone missing, remove it from the Database and then play remotely.
if (!file.exists()) {
DownloadedVideosDb.getVideoDownloadsDb().remove(youTubeVideo);
Toast.makeText(getContext(),
getContext().getString(R.string.playing_video_file_missing),
Toast.LENGTH_LONG).show();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,8 @@ public void onPlayerError(ExoPlaybackException error) {

boolean askForDelete = askForDelete(error);
String errorMessage = error.getCause().getMessage();
new SkyTubeMaterialDialog(YouTubePlayerV2Fragment.this.getContext())
Context ctx = YouTubePlayerV2Fragment.this.getContext();
new SkyTubeMaterialDialog(ctx)
.onNegativeOrCancel(dialog -> closeActivity())
.content(askForDelete ? R.string.error_downloaded_file_is_corrupted : R.string.error_video_parse_error, errorMessage)
.title(R.string.error_video_play)
Expand All @@ -328,7 +329,7 @@ public void onPlayerError(ExoPlaybackException error) {
.positiveText(askForDelete ? R.string.delete_download : 0)
.onPositive((dialog, which) -> {
if (askForDelete) {
YouTubePlayerV2Fragment.this.youTubeVideo.removeDownload();
DownloadedVideosDb.getVideoDownloadsDb().removeDownload(ctx, youTubeVideo.getVideoId());
}
closeActivity();
}).show();
Expand Down Expand Up @@ -423,7 +424,8 @@ private void preventDeviceSleeping(boolean flag) {
*/
private void loadVideo(boolean showMobileNetworkWarning) {
Policy decision = Policy.ALLOW;
DownloadedVideosDb.Status downloadStatus = DownloadedVideosDb.getVideoDownloadsDb().getVideoFileUriAndValidate(youTubeVideo.getVideoId());
Context ctx = getContext();
DownloadedVideosDb.Status downloadStatus = DownloadedVideosDb.getVideoDownloadsDb().getDownloadedFileStatus(ctx, youTubeVideo.getVideoId());

// if the user is using mobile network (i.e. 4g), then warn him
if (showMobileNetworkWarning && downloadStatus.getUri() == null) {
Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/values/strings_downloads.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<string name="downloads">Downloads</string>
<string name="warning_metered_network_download">Your device is connected to a metered network. To avoid potential extra data usage charges, it is recommended to connect to an unmetered network. Download video anyway?</string>
<string name="download_video">Download Video</string>
<string name="unable_to_delete_file">Unable to delete downloaded file: \'%s\'</string>
<string name="starting_video_download">Downloading \'%s\'…</string>
<string name="video_download_stream_error">Could not download \'%s\'.</string>
<string name="video_stream_not_found_with_request_resolution">No video stream found for the requested resolution, between %s - %s</string>
Expand Down

0 comments on commit 384cd49

Please sign in to comment.