Kore/app/src/main/java/org/xbmc/kore/utils/FileDownloadHelper.java

426 lines
16 KiB
Java
Raw Normal View History

2015-01-14 12:12:47 +01:00
/*
* Copyright 2015 Synced Synapse. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.xbmc.kore.utils;
2015-01-14 12:12:47 +01:00
import android.app.DownloadManager;
import android.content.Context;
import android.net.Uri;
import android.os.Environment;
import android.os.Handler;
import android.text.TextUtils;
import android.util.Base64;
import android.widget.Toast;
import org.xbmc.kore.R;
import org.xbmc.kore.Settings;
import org.xbmc.kore.host.HostInfo;
import org.xbmc.kore.jsonrpc.ApiCallback;
import org.xbmc.kore.jsonrpc.HostConnection;
import org.xbmc.kore.jsonrpc.method.Files;
import org.xbmc.kore.jsonrpc.method.JSONRPC;
import org.xbmc.kore.jsonrpc.type.FilesType;
2015-01-14 12:12:47 +01:00
import java.io.File;
import java.util.List;
/**
* Various methods to help with file downloading
*/
public class FileDownloadHelper {
private static final String TAG = LogUtils.makeLogTag(FileDownloadHelper.class);
// These chars cause problems with DownloadManager
private static final String RESERVED_CHARS_REGEX = "[?]";
2015-01-14 12:12:47 +01:00
public static final int OVERWRITE_FILES = 0,
DOWNLOAD_WITH_NEW_NAME = 1;
public static final String NO_ARTIST_DIR = "No artist",
NO_MOVIE_TITLE_DIR = "No title",
NO_TVSHOW_TITLE_DIR = "No title";
2015-01-14 12:12:47 +01:00
public static abstract class MediaInfo {
public String fileName;
2015-01-14 12:12:47 +01:00
public MediaInfo(final String fileName) {
this.fileName = fileName;
}
/**
* Check whether the directory on which to load the file exists
* @return Whether the directory exists
*/
public boolean downloadDirectoryExists() {
File file = new File(getAbsoluteDirectoryPath());
// LogUtils.LOGD(TAG, "Checking directory: " + file.getPath());
// LogUtils.LOGD(TAG, "Exists: " + file.exists());
return file.exists();
}
/**
* Check whether the file to download already exists
* @return Whether the file exists
*/
public boolean downloadFileExists() {
if (!downloadDirectoryExists())
return false;
File file = new File(getAbsoluteFilePath());
return file.exists();
}
public String getAbsoluteDirectoryPath() {
File externalFilesDir = Environment.getExternalStoragePublicDirectory(getExternalPublicDirType());
String filePath = externalFilesDir.getPath() + "/" + getRelativeDirectoryPath();
return filePath.replaceAll(RESERVED_CHARS_REGEX, "_");
2015-01-14 12:12:47 +01:00
}
public String getAbsoluteFilePath() {
String filePath = getAbsoluteDirectoryPath() + "/" + getDownloadFileName();
return filePath.replaceAll(RESERVED_CHARS_REGEX, "_");
2015-01-14 12:12:47 +01:00
}
public String getRelativeFilePath() {
String filePath = getRelativeDirectoryPath() + "/" + getDownloadFileName();
return filePath.replaceAll(RESERVED_CHARS_REGEX, "_");
2015-01-14 12:12:47 +01:00
}
public abstract String getExternalPublicDirType();
public abstract String getRelativeDirectoryPath();
public abstract String getDownloadFileName();
public abstract String getDownloadTitle(Context context);
public String getDownloadDescrition(Context context) {
return context.getString(R.string.download_file_description);
}
public String getMediaUrl(HostInfo hostInfo) {
2020-06-07 10:33:26 +02:00
String pathforUrl = Uri.encode(fileName);
String credentials = (hostInfo.getPassword() == null || hostInfo.getPassword().isEmpty()) ? "" :
String.format("%s:%s@", hostInfo.getUsername(), hostInfo.getPassword());
String videoUrl = String.format("http://%s%s:%d/vfs/%s", credentials, hostInfo.getAddress(),
hostInfo.getHttpPort(), pathforUrl);
return videoUrl;
}
2015-01-14 12:12:47 +01:00
}
/**
* Info for downloading songs
*/
public static class SongInfo extends MediaInfo {
public String artist;
public String album;
public int songId;
public int track;
public String title;
public SongInfo() {
super(null);
artist = null;
album = null;
songId = -1;
track = -1;
title = null;
}
2015-01-14 12:12:47 +01:00
public SongInfo(final String artist, final String album,
final int songId, final int track, final String title,
final String fileName) {
super(fileName);
this.artist = artist;
this.album = album;
this.songId = songId;
this.track = track;
this.title = title;
}
public String getRelativeDirectoryPath() {
return (TextUtils.isEmpty(artist) ? NO_ARTIST_DIR :
TextUtils.isEmpty(album) ? artist : artist + "/" + album);
2015-01-14 12:12:47 +01:00
}
public String getDownloadFileName() {
String ext = getFilenameExtension(fileName);
return (ext != null) ?
String.valueOf(track) + " - " + title + ext :
null;
}
public String getExternalPublicDirType() {
return Environment.DIRECTORY_MUSIC;
}
public String getDownloadTitle(Context context) {
return title;
}
}
/**
* Info for downloading movies
*/
public static class MovieInfo extends MediaInfo {
public final String title;
public MovieInfo(final String title, final String fileName) {
super(fileName);
this.title = title;
}
public String getRelativeDirectoryPath() {
return (TextUtils.isEmpty(title)) ?
NO_MOVIE_TITLE_DIR : title;
2015-01-14 12:12:47 +01:00
}
public String getDownloadFileName() {
String ext = getFilenameExtension(fileName);
return (ext != null) ?
title + ext : null;
}
public String getExternalPublicDirType() {
return Environment.DIRECTORY_MOVIES;
}
public String getDownloadTitle(Context context) {
return title;
}
}
/**
* Info for downloading TVShows
*/
public static class TVShowInfo extends MediaInfo {
public final String tvshowTitle;
public final int season;
public final int episodeNumber;
public final String title;
public TVShowInfo(final String tvshowTitle, final int season,
final int episodeNumber, final String title,
final String fileName) {
super(fileName);
this.tvshowTitle = tvshowTitle;
this.season = season;
this.episodeNumber = episodeNumber;
this.title = title;
}
public String getRelativeDirectoryPath() {
if (season > 0) {
return (TextUtils.isEmpty(tvshowTitle)) ?
NO_TVSHOW_TITLE_DIR : tvshowTitle + "/Season" + String.valueOf(season);
2015-01-14 12:12:47 +01:00
} else {
return (TextUtils.isEmpty(tvshowTitle)) ?
NO_TVSHOW_TITLE_DIR : tvshowTitle;
2015-01-14 12:12:47 +01:00
}
}
public String getDownloadFileName() {
String ext = getFilenameExtension(fileName);
return (ext != null) ?
String.valueOf(episodeNumber) + " - " + title + ext : null;
}
public String getExternalPublicDirType() {
return Environment.DIRECTORY_MOVIES;
}
public String getDownloadTitle(Context context) {
return title;
}
}
/**
* Info for downloading music videos
*/
public static class MusicVideoInfo extends MediaInfo {
public final String title;
private static final String SUBDIRECTORY = "Music Videos";
public MusicVideoInfo(final String title, final String fileName) {
super(fileName);
this.title = title;
}
public String getRelativeDirectoryPath() {
return (TextUtils.isEmpty(title)) ?
null : SUBDIRECTORY + "/" + title;
}
public String getDownloadFileName() {
String ext = getFilenameExtension(fileName);
return (ext != null) ?
title + ext : null;
}
public String getExternalPublicDirType() {
return Environment.DIRECTORY_MUSIC;
}
public String getDownloadTitle(Context context) {
return title;
}
}
/**
* Auxiliary method to get a filename extension, assuming the filename ends with .ext
* @param filename File name
* @return Extension if present, or null
*/
public static String getFilenameExtension(String filename) {
int idx = filename.lastIndexOf(".");
return (idx > 0) ? filename.substring(idx) : null;
}
public static void downloadFiles(final Context context, final HostInfo hostInfo,
final MediaInfo mediaInfo,
final int fileHandlingMode,
final Handler callbackHandler) {
if (mediaInfo == null)
return;
if (!checkDownloadDir(context, mediaInfo.getAbsoluteDirectoryPath()))
return;
// Check if we are connected to the host
final HostConnection httpHostConnection = new HostConnection(hostInfo);
httpHostConnection.setProtocol(HostConnection.PROTOCOL_HTTP);
JSONRPC.Ping action = new JSONRPC.Ping();
action.execute(httpHostConnection, new ApiCallback<String>() {
@Override
2015-03-16 19:33:40 +01:00
public void onSuccess(String result) {
2015-01-14 12:12:47 +01:00
// Ok, continue, iterate through the song list and launch a download for each
final DownloadManager downloadManager = (DownloadManager)context.getSystemService(Context.DOWNLOAD_SERVICE);
downloadSingleFile(context, httpHostConnection, hostInfo,
mediaInfo, fileHandlingMode, downloadManager, callbackHandler);
}
@Override
public void onError(int errorCode, String description) {
Toast.makeText(context, R.string.unable_to_connect_to_xbmc, Toast.LENGTH_SHORT)
.show();
}
}, callbackHandler);
}
public static void downloadFiles(final Context context, final HostInfo hostInfo,
final List<? extends MediaInfo> mediaInfoList,
final int fileHandlingMode,
final Handler callbackHandler) {
if ((mediaInfoList == null) || (mediaInfoList.isEmpty()))
2015-01-14 12:12:47 +01:00
return;
if (!checkDownloadDir(context, mediaInfoList.get(0).getAbsoluteDirectoryPath()))
return;
// Check if we are connected to the host
final HostConnection httpHostConnection = new HostConnection(hostInfo);
httpHostConnection.setProtocol(HostConnection.PROTOCOL_HTTP);
JSONRPC.Ping action = new JSONRPC.Ping();
action.execute(httpHostConnection, new ApiCallback<String>() {
@Override
2015-03-16 19:33:40 +01:00
public void onSuccess(String result) {
2015-01-14 12:12:47 +01:00
// Ok, continue, iterate through the song list and launch a download for each
final DownloadManager downloadManager = (DownloadManager)context.getSystemService(Context.DOWNLOAD_SERVICE);
for (final MediaInfo mediaInfo : mediaInfoList) {
downloadSingleFile(context, httpHostConnection, hostInfo,
mediaInfo, fileHandlingMode, downloadManager, callbackHandler);
}
}
@Override
public void onError(int errorCode, String description) {
Toast.makeText(context, R.string.unable_to_connect_to_xbmc, Toast.LENGTH_SHORT)
.show();
}
}, callbackHandler);
}
private static boolean checkDownloadDir(Context context, String downloadDirPath) {
File downloadDir = new File(downloadDirPath);
if ((downloadDir.exists() && !downloadDir.isDirectory())) {
Toast.makeText(context,
"Download directory already exists and is not a directory.",
Toast.LENGTH_SHORT)
.show();
return false;
}
if (!downloadDir.isDirectory() && !downloadDir.mkdirs()) {
Toast.makeText(context,
"Couldn't create download directory: " + downloadDir.getPath(),
Toast.LENGTH_SHORT)
.show();
return false;
}
return true;
}
private static void downloadSingleFile(final Context context,
final HostConnection httpHostConnection,
final HostInfo hostInfo,
final MediaInfo mediaInfo,
final int fileHandlingMode,
final DownloadManager downloadManager,
final Handler callbackHandler) {
Files.PrepareDownload action = new Files.PrepareDownload(mediaInfo.fileName);
action.execute(httpHostConnection, new ApiCallback<FilesType.PrepareDownloadReturnType>() {
@Override
2015-03-16 19:33:40 +01:00
public void onSuccess(FilesType.PrepareDownloadReturnType result) {
2015-01-14 12:12:47 +01:00
// If the file exists and it's to be overwritten, delete it,
// as the DownloadManager always creates a new name
if (fileHandlingMode == OVERWRITE_FILES) {
File file = new File(mediaInfo.getAbsoluteFilePath());
if (file.exists()) {
file.delete();
}
}
// Ok, we got the path, invoke downloader
Uri uri = Uri.parse(hostInfo.getHttpURL() + "/" + result.path);
DownloadManager.Request request = new DownloadManager.Request(uri);
// http basic authorization
if ((hostInfo.getUsername() != null) && !hostInfo.getUsername().isEmpty() &&
(hostInfo.getPassword() != null) && !hostInfo.getPassword().isEmpty()) {
final String token = Base64.encodeToString((hostInfo.getUsername() + ":" +
hostInfo.getPassword()).getBytes(), Base64.DEFAULT);
request.addRequestHeader("Authorization", "Basic " + token);
}
request.allowScanningByMediaScanner();
request.setAllowedNetworkTypes(Settings.allowedDownloadNetworkTypes(context));
2015-01-14 12:12:47 +01:00
request.setTitle(mediaInfo.getDownloadTitle(context));
request.setDescription(mediaInfo.getDownloadDescrition(context));
request.setDestinationInExternalPublicDir(mediaInfo.getExternalPublicDirType(),
mediaInfo.getRelativeFilePath());
downloadManager.enqueue(request);
}
@Override
public void onError(int errorCode, String description) {
Toast.makeText(context,
String.format(context.getString(R.string.error_getting_file_information),
mediaInfo.getDownloadTitle(context)),
Toast.LENGTH_SHORT)
.show();
}
}, callbackHandler);
}
}