package com.quran.labs.androidquran.model.bookmark; import android.content.Context; import android.net.Uri; import android.support.annotation.NonNull; import android.support.v4.content.FileProvider; import com.quran.labs.androidquran.R; import com.quran.labs.androidquran.dao.BookmarkData; import com.quran.labs.androidquran.database.BookmarksDBAdapter; import java.io.File; import java.io.IOException; import javax.inject.Inject; import io.reactivex.Single; import io.reactivex.schedulers.Schedulers; import okio.BufferedSink; import okio.BufferedSource; import okio.Okio; public class BookmarkImportExportModel { private static final String FILE_NAME = "quran_android.backup"; private final Context appContext; private final BookmarkJsonModel jsonModel; private final BookmarkModel bookmarkModel; @Inject BookmarkImportExportModel(Context appContext, BookmarkJsonModel model, BookmarkModel bookmarkModel) { this.appContext = appContext; this.jsonModel = model; this.bookmarkModel = bookmarkModel; } public Single<BookmarkData> readBookmarks(@NonNull final BufferedSource source) { return Single.defer(() -> Single.just(jsonModel.fromJson(source))) .subscribeOn(Schedulers.io()); } public Single<Uri> exportBookmarksObservable() { return bookmarkModel.getBookmarkDataObservable(BookmarksDBAdapter.SORT_DATE_ADDED) .flatMap(bookmarkData -> Single.just(exportBookmarks(bookmarkData))) .subscribeOn(Schedulers.io()); } @NonNull private Uri exportBookmarks(BookmarkData data) throws IOException { // exporting often fails due to the thread being interrupted (when okio sees an interrupted // thread, it doesn't flush the buffer and instead just throws an exception and returns). // may revisit this after hearing back about https://github.com/ReactiveX/RxJava/issues/5024. Thread.interrupted(); File externalFilesDir = new File(appContext.getExternalFilesDir(null), "backups"); if (externalFilesDir.exists() || externalFilesDir.mkdir()) { File file = new File(externalFilesDir, FILE_NAME); BufferedSink sink = Okio.buffer(Okio.sink(file)); jsonModel.toJson(sink, data); sink.close(); return FileProvider.getUriForFile( appContext, appContext.getString(R.string.file_authority), file); } throw new IOException("Unable to write to external files directory."); } }