package pct.droid.base.subs; import android.content.Context; import android.os.AsyncTask; import android.support.annotation.NonNull; import com.squareup.okhttp.Callback; import com.squareup.okhttp.Request; import com.squareup.okhttp.Response; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.lang.ref.WeakReference; import pct.droid.base.providers.media.models.Media; import pct.droid.base.providers.subs.SubsProvider; import pct.droid.base.torrent.StreamInfo; import pct.droid.base.utils.FileUtils; public class SubtitleDownloader { private final Media media; private final WeakReference<Context> contextReference; private String subtitleLanguage; private WeakReference<ISubtitleDownloaderListener> listenerReference; public SubtitleDownloader(@NonNull Context context, @NonNull StreamInfo streamInfo, @NonNull String language) { if (language.equals(SubsProvider.SUBTITLE_LANGUAGE_NONE)) throw new IllegalArgumentException("language must be specified"); contextReference = new WeakReference<>(context); subtitleLanguage = language; media = streamInfo.getMedia(); if (media == null) throw new IllegalArgumentException("media from StreamInfo must not null"); } public void downloadSubtitle() { if (listenerReference == null) throw new IllegalArgumentException("listener must not null. Call setSubtitleDownloaderListener() to sets one"); if (contextReference.get() == null) return; Context context = contextReference.get(); SubsProvider.download(context, media, subtitleLanguage, new Callback() { @Override public void onFailure(Request request, IOException exception) { onSubtitleDownloadFailed(); } @Override public void onResponse(Response response) throws IOException { onSubtitleDownloadSuccess(); } }); } public void parseSubtitle(@NonNull File subtitleFile) { if (listenerReference == null) throw new IllegalArgumentException("listener must not null. Call setSubtitleDownloaderListener() to sets one"); if (listenerReference.get() == null) return; ISubtitleDownloaderListener listener = listenerReference.get(); SubtitleParseTask task = new SubtitleParseTask(subtitleLanguage, listener); task.execute(subtitleFile); } public void setSubtitleDownloaderListener(ISubtitleDownloaderListener listener) { if (listener == null) throw new IllegalArgumentException("listener must not null"); listenerReference = new WeakReference<>(listener); } public static File getDownloadedSubtitleFile( @NonNull Context context, @NonNull Media media, @NonNull String language) throws FileNotFoundException { if (language.equals(SubsProvider.SUBTITLE_LANGUAGE_NONE)) throw new IllegalArgumentException("language must be specified"); File subtitleFile = new File( SubsProvider.getStorageLocation(context), media.videoId + "-" + language + ".srt"); if (subtitleFile.exists()) return subtitleFile; throw new FileNotFoundException("Subtitle file does not exists"); } /** * Invoked when subtitle download finished successfully. */ private void onSubtitleDownloadSuccess() { if (contextReference.get() == null) return; if (listenerReference.get() == null) return; Context context = contextReference.get(); ISubtitleDownloaderListener listener = listenerReference.get(); try { File subtitleFile = getDownloadedSubtitleFile(context, media, subtitleLanguage); SubtitleParseTask task = new SubtitleParseTask(subtitleLanguage, listener); task.execute(subtitleFile); } catch (FileNotFoundException e) { e.printStackTrace(); listener.onSubtitleDownloadCompleted(false, null); } } /** * Invoked when subtitle download failed. */ private void onSubtitleDownloadFailed() { subtitleLanguage = SubsProvider.SUBTITLE_LANGUAGE_NONE; if (listenerReference.get() == null) return; ISubtitleDownloaderListener listener = listenerReference.get(); listener.onSubtitleDownloadCompleted(false, null); } private class SubtitleParseTask extends AsyncTask<File, TimedTextObject, TimedTextObject> { String subtitleLanguage; WeakReference<ISubtitleDownloaderListener> listenerReference; public SubtitleParseTask(String language, ISubtitleDownloaderListener listener) { subtitleLanguage = language; listenerReference = new WeakReference<>(listener); } @Override protected TimedTextObject doInBackground(File... files) { for (File file : files) { try { TimedTextObject text = parseAsTimedTextObject(file); publishProgress(text); } catch (FileNotFoundException e) { if (e.getMessage().contains("EBUSY")) { try { TimedTextObject text = parseAsTimedTextObject(file); publishProgress(text); } catch (IOException e1) { e1.printStackTrace(); return null; } } e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); return null; } } return null; } @Override protected void onProgressUpdate(TimedTextObject... values) { super.onProgressUpdate(values); for (TimedTextObject timedTextObject : values ) { if (listenerReference.get() == null) break; listenerReference.get().onSubtitleDownloadCompleted(true, timedTextObject); } } private TimedTextObject parseAsTimedTextObject(File file) throws IOException { FileInputStream fileInputStream = new FileInputStream(file); FormatSRT formatSRT = new FormatSRT(); TimedTextObject result = formatSRT.parseFile( file.toString(), FileUtils.inputstreamToCharsetString( fileInputStream, subtitleLanguage).split("\n")); return result; } } public interface ISubtitleDownloaderListener { void onSubtitleDownloadCompleted(boolean isSuccessful, TimedTextObject subtitleFile); } }