From e1b68f66f2c3f9c9482c4c885b14f91728c27da0 Mon Sep 17 00:00:00 2001 From: inorichi Date: Tue, 8 Dec 2015 19:39:57 +0100 Subject: [PATCH] Changes: - Declare RxJava as dependency - Add a folder chooser for downloads - Fix a force close when updating library - Enable ACRA and add a setting to send crash reports - Manga class now uses the default get resolver - Other minor changes --- app/build.gradle | 5 +- app/src/main/AndroidManifest.xml | 6 ++ .../main/java/eu/kanade/mangafeed/App.java | 24 ++--- .../data/database/DatabaseHelper.java | 4 +- .../resolvers/MangaWithUnreadGetResolver.java | 6 +- .../data/preference/PreferencesHelper.java | 19 +++- .../data/sync/LibraryUpdateService.java | 10 +-- .../ui/setting/SettingsAccountsFragment.java | 11 ++- .../ui/setting/SettingsActivity.java | 2 +- .../ui/setting/SettingsCacheFragment.java | 12 ++- .../ui/setting/SettingsDownloadsFragment.java | 89 +++++++++++++++---- .../ui/setting/SettingsNestedFragment.java | 14 ++- .../eu/kanade/mangafeed/util/DiskUtils.java | 75 ---------------- app/src/main/res/layout/listitem_dir.xml | 37 ++++++++ app/src/main/res/values/strings.xml | 4 + app/src/main/res/values/styles.xml | 15 ++++ app/src/main/res/xml/pref_downloads.xml | 11 ++- app/src/main/res/xml/pref_main.xml | 6 ++ 18 files changed, 217 insertions(+), 133 deletions(-) create mode 100644 app/src/main/res/layout/listitem_dir.xml diff --git a/app/build.gradle b/app/build.gradle index 38f3de2a30..6d236fe910 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -70,6 +70,7 @@ dependencies { compile 'com.jakewharton:disklrucache:2.0.2' compile 'org.jsoup:jsoup:1.8.3' compile 'io.reactivex:rxandroid:1.0.1' + compile 'io.reactivex:rxjava:1.1.0' compile 'com.f2prateek.rx.preferences:rx-preferences:1.0.1' compile "com.pushtorefresh.storio:sqlite:$STORIO_VERSION" compile "com.pushtorefresh.storio:sqlite-annotations:$STORIO_VERSION" @@ -86,6 +87,7 @@ dependencies { provided "frankiesardo:icepick-processor:$ICEPICK_VERSION" compile 'com.github.dmytrodanylyk.android-process-button:library:1.0.4' compile 'eu.davidea:flexible-adapter:4.1.0@aar' + compile 'com.nononsenseapps:filepicker:2.5.0' compile "com.google.dagger:dagger:$DAGGER_VERSION" apt "com.google.dagger:dagger-compiler:$DAGGER_VERSION" @@ -98,9 +100,6 @@ dependencies { compile('com.github.afollestad.material-dialogs:core:0.8.5.2@aar') { transitive = true } - compile('com.github.afollestad.material-dialogs:commons:0.8.5.2@aar') { - transitive = true - } testCompile 'junit:junit:4.12' testCompile "org.hamcrest:hamcrest-core:$HAMCREST_VERSION" diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 11309792c2..50f2b86084 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -40,6 +40,12 @@ android:parentActivityName=".ui.main.MainActivity" > + + + diff --git a/app/src/main/java/eu/kanade/mangafeed/App.java b/app/src/main/java/eu/kanade/mangafeed/App.java index 071f6dad5e..4c76c466b6 100644 --- a/app/src/main/java/eu/kanade/mangafeed/App.java +++ b/app/src/main/java/eu/kanade/mangafeed/App.java @@ -3,6 +3,7 @@ package eu.kanade.mangafeed; import android.app.Application; import android.content.Context; +import org.acra.ACRA; import org.acra.annotation.ReportsCrashes; import eu.kanade.mangafeed.injection.ComponentReflectionInjector; @@ -12,30 +13,29 @@ import eu.kanade.mangafeed.injection.module.AppModule; import timber.log.Timber; @ReportsCrashes( - formUri = "http://couch.kanade.eu/acra-manga/_design/acra-storage/_update/report", + formUri = "http://mangafeed.kanade.eu/crash_report", reportType = org.acra.sender.HttpSender.Type.JSON, httpMethod = org.acra.sender.HttpSender.Method.PUT, - formUriBasicAuthLogin="test", - formUriBasicAuthPassword="test" + excludeMatchingSharedPreferencesKeys={".*username.*",".*password.*"} ) public class App extends Application { - AppComponent mApplicationComponent; - ComponentReflectionInjector mComponentInjector; + AppComponent applicationComponent; + ComponentReflectionInjector componentInjector; @Override public void onCreate() { super.onCreate(); if (BuildConfig.DEBUG) Timber.plant(new Timber.DebugTree()); - mApplicationComponent = DaggerAppComponent.builder() + applicationComponent = DaggerAppComponent.builder() .appModule(new AppModule(this)) .build(); - mComponentInjector = - new ComponentReflectionInjector<>(AppComponent.class, mApplicationComponent); + componentInjector = + new ComponentReflectionInjector<>(AppComponent.class, applicationComponent); - //ACRA.init(this); + ACRA.init(this); } public static App get(Context context) { @@ -43,15 +43,15 @@ public class App extends Application { } public AppComponent getComponent() { - return mApplicationComponent; + return applicationComponent; } public ComponentReflectionInjector getComponentReflection() { - return mComponentInjector; + return componentInjector; } // Needed to replace the component with a test specific one public void setComponent(AppComponent applicationComponent) { - mApplicationComponent = applicationComponent; + this.applicationComponent = applicationComponent; } } diff --git a/app/src/main/java/eu/kanade/mangafeed/data/database/DatabaseHelper.java b/app/src/main/java/eu/kanade/mangafeed/data/database/DatabaseHelper.java index 814c1e3bcd..779f692d0c 100644 --- a/app/src/main/java/eu/kanade/mangafeed/data/database/DatabaseHelper.java +++ b/app/src/main/java/eu/kanade/mangafeed/data/database/DatabaseHelper.java @@ -27,6 +27,7 @@ import eu.kanade.mangafeed.data.database.models.ChapterSyncStorIOSQLiteGetResolv import eu.kanade.mangafeed.data.database.models.ChapterSyncStorIOSQLitePutResolver; import eu.kanade.mangafeed.data.database.models.Manga; import eu.kanade.mangafeed.data.database.models.MangaStorIOSQLiteDeleteResolver; +import eu.kanade.mangafeed.data.database.models.MangaStorIOSQLiteGetResolver; import eu.kanade.mangafeed.data.database.models.MangaStorIOSQLitePutResolver; import eu.kanade.mangafeed.data.database.resolvers.MangaWithUnreadGetResolver; import eu.kanade.mangafeed.data.database.tables.ChapterSyncTable; @@ -46,7 +47,7 @@ public class DatabaseHelper { .sqliteOpenHelper(new DbOpenHelper(context)) .addTypeMapping(Manga.class, SQLiteTypeMapping.builder() .putResolver(new MangaStorIOSQLitePutResolver()) - .getResolver(new MangaWithUnreadGetResolver()) + .getResolver(new MangaStorIOSQLiteGetResolver()) .deleteResolver(new MangaStorIOSQLiteDeleteResolver()) .build()) .addTypeMapping(Chapter.class, SQLiteTypeMapping.builder() @@ -94,6 +95,7 @@ public class DatabaseHelper { .query(favoriteMangasWithUnreadQuery) .observesTables(MangaTable.TABLE, ChapterTable.TABLE) .build()) + .withGetResolver(MangaWithUnreadGetResolver.instance) .prepare(); } diff --git a/app/src/main/java/eu/kanade/mangafeed/data/database/resolvers/MangaWithUnreadGetResolver.java b/app/src/main/java/eu/kanade/mangafeed/data/database/resolvers/MangaWithUnreadGetResolver.java index e438513e73..546bf34208 100644 --- a/app/src/main/java/eu/kanade/mangafeed/data/database/resolvers/MangaWithUnreadGetResolver.java +++ b/app/src/main/java/eu/kanade/mangafeed/data/database/resolvers/MangaWithUnreadGetResolver.java @@ -9,12 +9,14 @@ import eu.kanade.mangafeed.data.database.tables.MangaTable; public class MangaWithUnreadGetResolver extends MangaStorIOSQLiteGetResolver { + public static final MangaWithUnreadGetResolver instance = new MangaWithUnreadGetResolver(); + @Override + @NonNull public Manga mapFromCursor(@NonNull Cursor cursor) { Manga manga = super.mapFromCursor(cursor); int unreadColumn = cursor.getColumnIndex(MangaTable.COLUMN_UNREAD); - if (unreadColumn != -1) - manga.unread = cursor.getInt(unreadColumn); + manga.unread = cursor.getInt(unreadColumn); return manga; } diff --git a/app/src/main/java/eu/kanade/mangafeed/data/preference/PreferencesHelper.java b/app/src/main/java/eu/kanade/mangafeed/data/preference/PreferencesHelper.java index 1ca74cef85..6a57da63a2 100644 --- a/app/src/main/java/eu/kanade/mangafeed/data/preference/PreferencesHelper.java +++ b/app/src/main/java/eu/kanade/mangafeed/data/preference/PreferencesHelper.java @@ -2,15 +2,17 @@ package eu.kanade.mangafeed.data.preference; import android.content.Context; import android.content.SharedPreferences; +import android.os.Environment; import android.preference.PreferenceManager; import com.f2prateek.rx.preferences.Preference; import com.f2prateek.rx.preferences.RxSharedPreferences; +import java.io.File; + import eu.kanade.mangafeed.R; import eu.kanade.mangafeed.data.chaptersync.BaseChapterSync; import eu.kanade.mangafeed.data.source.base.Source; -import eu.kanade.mangafeed.util.DiskUtils; import rx.Observable; public class PreferencesHelper { @@ -24,12 +26,21 @@ public class PreferencesHelper { private static final String CHAPTERSYNC_ACCOUNT_USERNAME = "pref_chaptersync_username_"; private static final String CHAPTERSYNC_ACCOUNT_PASSWORD = "pref_chaptersync_password_"; + private File defaultDownloadsDir; + public PreferencesHelper(Context context) { this.context = context; PreferenceManager.setDefaultValues(context, R.xml.pref_reader, false); prefs = PreferenceManager.getDefaultSharedPreferences(context); rxPrefs = RxSharedPreferences.create(prefs); + + defaultDownloadsDir = new File(Environment.getExternalStorageDirectory() + + File.separator + context.getString(R.string.app_name), "downloads"); + + // Create default directory + if (getDownloadsDirectory().equals(defaultDownloadsDir.getAbsolutePath())) + defaultDownloadsDir.mkdirs(); } private String getKey(int keyResource) { @@ -108,7 +119,11 @@ public class PreferencesHelper { public String getDownloadsDirectory() { return prefs.getString(getKey(R.string.pref_download_directory_key), - DiskUtils.getStorageDirectories(context)[0]); + defaultDownloadsDir.getAbsolutePath()); + } + + public void setDownloadsDirectory(String path) { + prefs.edit().putString(getKey(R.string.pref_download_directory_key), path).apply(); } public int getDownloadThreads() { diff --git a/app/src/main/java/eu/kanade/mangafeed/data/sync/LibraryUpdateService.java b/app/src/main/java/eu/kanade/mangafeed/data/sync/LibraryUpdateService.java index c6d96071c4..b705467c87 100644 --- a/app/src/main/java/eu/kanade/mangafeed/data/sync/LibraryUpdateService.java +++ b/app/src/main/java/eu/kanade/mangafeed/data/sync/LibraryUpdateService.java @@ -32,7 +32,6 @@ public class LibraryUpdateService extends Service { @Inject SourceManager sourceManager; private Subscription updateSubscription; - private Subscription favoriteMangasSubscription; public static final int UPDATE_NOTIFICATION_ID = 1; @@ -68,14 +67,9 @@ public class LibraryUpdateService extends Service { return START_NOT_STICKY; } - if (favoriteMangasSubscription != null && !favoriteMangasSubscription.isUnsubscribed()) - favoriteMangasSubscription.unsubscribe(); - - favoriteMangasSubscription = db.getFavoriteMangas().createObservable() + Observable.fromCallable(() -> db.getFavoriteMangas().executeAsBlocking()) .subscribe(mangas -> { - // Don't receive further db updates - favoriteMangasSubscription.unsubscribe(); - this.startUpdating(mangas, startId); + startUpdating(mangas, startId); }); return START_STICKY; diff --git a/app/src/main/java/eu/kanade/mangafeed/ui/setting/SettingsAccountsFragment.java b/app/src/main/java/eu/kanade/mangafeed/ui/setting/SettingsAccountsFragment.java index fe04f989b5..eb021022b4 100644 --- a/app/src/main/java/eu/kanade/mangafeed/ui/setting/SettingsAccountsFragment.java +++ b/app/src/main/java/eu/kanade/mangafeed/ui/setting/SettingsAccountsFragment.java @@ -3,6 +3,9 @@ package eu.kanade.mangafeed.ui.setting; import android.os.Bundle; import android.preference.PreferenceCategory; import android.preference.PreferenceScreen; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; import java.util.List; @@ -24,13 +27,18 @@ public class SettingsAccountsFragment extends SettingsNestedFragment { public static SettingsNestedFragment newInstance(int resourcePreference, int resourceTitle) { SettingsNestedFragment fragment = new SettingsAccountsFragment(); - fragment.setBundle(resourcePreference, resourceTitle); + fragment.setArgs(resourcePreference, resourceTitle); return fragment; } public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); App.get(getActivity()).getComponent().inject(this); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedSate) { + View view = super.onCreateView(inflater, container, savedSate); PreferenceScreen screen = getPreferenceScreen(); @@ -60,6 +68,7 @@ public class SettingsAccountsFragment extends SettingsNestedFragment { chapterSyncCategory.addPreference(dialog); } + return view; } private List getSourcesWithLogin() { diff --git a/app/src/main/java/eu/kanade/mangafeed/ui/setting/SettingsActivity.java b/app/src/main/java/eu/kanade/mangafeed/ui/setting/SettingsActivity.java index 4b94f8d302..e97381c816 100644 --- a/app/src/main/java/eu/kanade/mangafeed/ui/setting/SettingsActivity.java +++ b/app/src/main/java/eu/kanade/mangafeed/ui/setting/SettingsActivity.java @@ -24,7 +24,7 @@ public class SettingsActivity extends BaseActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - App.get(getActivity()).getComponent().inject(this); + App.get(this).getComponent().inject(this); setContentView(R.layout.activity_preferences); ButterKnife.bind(this); diff --git a/app/src/main/java/eu/kanade/mangafeed/ui/setting/SettingsCacheFragment.java b/app/src/main/java/eu/kanade/mangafeed/ui/setting/SettingsCacheFragment.java index 81a04fe86a..e5f868f887 100644 --- a/app/src/main/java/eu/kanade/mangafeed/ui/setting/SettingsCacheFragment.java +++ b/app/src/main/java/eu/kanade/mangafeed/ui/setting/SettingsCacheFragment.java @@ -2,6 +2,9 @@ package eu.kanade.mangafeed.ui.setting; import android.os.Bundle; import android.preference.Preference; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; import com.afollestad.materialdialogs.MaterialDialog; @@ -25,13 +28,14 @@ public class SettingsCacheFragment extends SettingsNestedFragment implements Pre public static SettingsNestedFragment newInstance(int resourcePreference, int resourceTitle) { SettingsNestedFragment fragment = new SettingsCacheFragment(); - fragment.setBundle(resourcePreference, resourceTitle); + fragment.setArgs(resourcePreference, resourceTitle); return fragment; } @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) { + View view = super.onCreateView(inflater, container, savedState); + cacheManager = getSettingsActivity().cacheManager; IntListPreference cacheSize = (IntListPreference)findPreference(getString(R.string.pref_chapter_cache_size_key)); @@ -44,6 +48,8 @@ public class SettingsCacheFragment extends SettingsNestedFragment implements Pre clearCache = findPreference(getString(R.string.pref_clear_chapter_cache_key)); clearCache.setOnPreferenceClickListener(this); clearCache.setSummary(getString(R.string.used_cache, cacheManager.getReadableSize())); + + return view; } @Override diff --git a/app/src/main/java/eu/kanade/mangafeed/ui/setting/SettingsDownloadsFragment.java b/app/src/main/java/eu/kanade/mangafeed/ui/setting/SettingsDownloadsFragment.java index 9f7e0cdeca..b0efd7a8d2 100644 --- a/app/src/main/java/eu/kanade/mangafeed/ui/setting/SettingsDownloadsFragment.java +++ b/app/src/main/java/eu/kanade/mangafeed/ui/setting/SettingsDownloadsFragment.java @@ -1,40 +1,93 @@ package eu.kanade.mangafeed.ui.setting; +import android.app.Activity; +import android.content.Intent; +import android.net.Uri; import android.os.Bundle; -import android.preference.ListPreference; -import android.preference.PreferenceScreen; +import android.preference.Preference; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.nononsenseapps.filepicker.AbstractFilePickerFragment; +import com.nononsenseapps.filepicker.FilePickerActivity; +import com.nononsenseapps.filepicker.FilePickerFragment; +import com.nononsenseapps.filepicker.LogicHandler; + +import java.io.File; import eu.kanade.mangafeed.R; -import eu.kanade.mangafeed.util.DiskUtils; public class SettingsDownloadsFragment extends SettingsNestedFragment { + Preference downloadDirPref; + + public static final int DOWNLOAD_DIR_CODE = 1; + public static SettingsNestedFragment newInstance(int resourcePreference, int resourceTitle) { SettingsNestedFragment fragment = new SettingsDownloadsFragment(); - fragment.setBundle(resourcePreference, resourceTitle); + fragment.setArgs(resourcePreference, resourceTitle); return fragment; } - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View view = super.onCreateView(inflater, container, savedInstanceState); - PreferenceScreen screen = getPreferenceScreen(); + downloadDirPref = findPreference(getString(R.string.pref_download_directory_key)); - ListPreference directoriesPref = new ListPreference(getActivity(), null); + downloadDirPref.setOnPreferenceClickListener(preference -> { + Intent i = new Intent(getActivity(), CustomLayoutPickerActivity.class); + i.putExtra(FilePickerActivity.EXTRA_ALLOW_MULTIPLE, false); + i.putExtra(FilePickerActivity.EXTRA_ALLOW_CREATE_DIR, true); + i.putExtra(FilePickerActivity.EXTRA_MODE, FilePickerActivity.MODE_DIR); + i.putExtra(FilePickerActivity.EXTRA_START_PATH, preferences.getDownloadsDirectory()); - String[] externalDirs = DiskUtils.getStorageDirectories(getActivity()); - directoriesPref.setKey(getString(R.string.pref_download_directory_key)); - directoriesPref.setTitle(R.string.pref_download_directory); - directoriesPref.setEntryValues(externalDirs); - directoriesPref.setEntries(externalDirs); - directoriesPref.setSummary(preferences.getDownloadsDirectory()); - - directoriesPref.setOnPreferenceChangeListener((preference, newValue) -> { - preference.setSummary(newValue.toString()); + startActivityForResult(i, DOWNLOAD_DIR_CODE); return true; }); + return view; + } - screen.addPreference(directoriesPref); + @Override + public void onResume() { + super.onResume(); + downloadDirPref.setSummary(preferences.getDownloadsDirectory()); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + if (requestCode == DOWNLOAD_DIR_CODE && resultCode == Activity.RESULT_OK) { + Uri uri = data.getData(); + preferences.setDownloadsDirectory(uri.getPath()); + } + } + + public static class CustomLayoutPickerActivity extends FilePickerActivity { + + @Override + protected AbstractFilePickerFragment getFragment( + String startPath, int mode, boolean allowMultiple, boolean allowCreateDir) { + AbstractFilePickerFragment fragment = new CustomLayoutFilePickerFragment(); + fragment.setArgs(startPath, mode, allowMultiple, allowCreateDir); + return fragment; + } + } + + public static class CustomLayoutFilePickerFragment extends FilePickerFragment { + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View v; + switch (viewType) { + case LogicHandler.VIEWTYPE_DIR: + v = LayoutInflater.from(getActivity()).inflate(R.layout.listitem_dir, + parent, false); + return new DirViewHolder(v); + default: + return super.onCreateViewHolder(parent, viewType); + } + } } } diff --git a/app/src/main/java/eu/kanade/mangafeed/ui/setting/SettingsNestedFragment.java b/app/src/main/java/eu/kanade/mangafeed/ui/setting/SettingsNestedFragment.java index c1e74c7832..84a49c2652 100644 --- a/app/src/main/java/eu/kanade/mangafeed/ui/setting/SettingsNestedFragment.java +++ b/app/src/main/java/eu/kanade/mangafeed/ui/setting/SettingsNestedFragment.java @@ -2,6 +2,9 @@ package eu.kanade.mangafeed.ui.setting; import android.os.Bundle; import android.preference.PreferenceFragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; import eu.kanade.mangafeed.data.preference.PreferencesHelper; import eu.kanade.mangafeed.ui.base.activity.BaseActivity; @@ -15,17 +18,22 @@ public class SettingsNestedFragment extends PreferenceFragment { public static SettingsNestedFragment newInstance(int resourcePreference, int resourceTitle) { SettingsNestedFragment fragment = new SettingsNestedFragment(); - fragment.setBundle(resourcePreference, resourceTitle); + fragment.setArgs(resourcePreference, resourceTitle); return fragment; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - preferences = getSettingsActivity().preferences; addPreferencesFromResource(getArguments().getInt(RESOURCE_FILE)); } + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + preferences = getSettingsActivity().preferences; + return super.onCreateView(inflater, container, savedInstanceState); + } + @Override public void onResume() { super.onResume(); @@ -33,7 +41,7 @@ public class SettingsNestedFragment extends PreferenceFragment { .setToolbarTitle(getString(getArguments().getInt(TOOLBAR_TITLE))); } - public void setBundle(int resourcePreference, int resourceTitle) { + public void setArgs(int resourcePreference, int resourceTitle) { Bundle args = new Bundle(); args.putInt(RESOURCE_FILE, resourcePreference); args.putInt(TOOLBAR_TITLE, resourceTitle); diff --git a/app/src/main/java/eu/kanade/mangafeed/util/DiskUtils.java b/app/src/main/java/eu/kanade/mangafeed/util/DiskUtils.java index 6c805b3d6f..94fd6027c3 100644 --- a/app/src/main/java/eu/kanade/mangafeed/util/DiskUtils.java +++ b/app/src/main/java/eu/kanade/mangafeed/util/DiskUtils.java @@ -1,95 +1,20 @@ package eu.kanade.mangafeed.util; -import android.content.Context; -import android.os.Build; -import android.os.Environment; -import android.text.TextUtils; - import java.io.File; import java.io.IOException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; -import java.util.HashSet; -import java.util.Set; -import java.util.regex.Pattern; import okio.BufferedSink; import okio.BufferedSource; import okio.Okio; public final class DiskUtils { - private static final Pattern DIR_SEPARATOR = Pattern.compile("/"); private DiskUtils() { throw new AssertionError(); } - // http://stackoverflow.com/questions/13976982/removable-storage-external-sdcard-path-by-manufacturers - // http://stackoverflow.com/questions/11281010/how-can-i-get-external-sd-card-path-for-android-4-0 - public static String[] getStorageDirectories(Context context) { - final Set storageDirectories = new HashSet(); - - storageDirectories.add(context.getFilesDir().getAbsolutePath()); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - File[] directories = context.getExternalFilesDirs(null); - if (directories != null) { - for (File storage : directories) { - if (storage != null) { - storageDirectories.add(storage.getAbsolutePath()); - } - } - } - } else { - final String rawExternalStorage = System.getenv("EXTERNAL_STORAGE"); - final String rawSecondaryStoragesStr = System.getenv("SECONDARY_STORAGE"); - final String rawEmulatedStorageTarget = System.getenv("EMULATED_STORAGE_TARGET"); - - if (TextUtils.isEmpty(rawEmulatedStorageTarget)) { - if (TextUtils.isEmpty(rawExternalStorage)) { - storageDirectories.add("/storage/sdcard0" + File.separator + context.getPackageName()); - } else { - storageDirectories.add(rawExternalStorage + File.separator + context.getPackageName()); - } - } else { - final String rawUserId; - - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) { - rawUserId = ""; - } else { - final String path = Environment.getExternalStorageDirectory().getAbsolutePath(); - final String[] folders = DIR_SEPARATOR.split(path); - final String lastFolder = folders[folders.length - 1]; - boolean isDigit = false; - - try { - Integer.valueOf(lastFolder); - isDigit = true; - } catch (NumberFormatException e) { - // Do Nothing. - } - - rawUserId = isDigit ? lastFolder : ""; - } - - if (TextUtils.isEmpty(rawUserId)) { - storageDirectories.add(rawEmulatedStorageTarget + File.separator + context.getPackageName()); - } else { - storageDirectories.add(rawEmulatedStorageTarget + File.separator + rawUserId + File.separator + context.getPackageName()); - } - } - - if (!TextUtils.isEmpty(rawSecondaryStoragesStr)) { - String[] rawSecondaryStorages = rawSecondaryStoragesStr.split(File.pathSeparator); - for (int index = 0; index < rawSecondaryStorages.length; index++) { - storageDirectories.add(rawSecondaryStorages[index] + File.separator + context.getPackageName()); - } - } - } - - return storageDirectories.toArray(new String[storageDirectories.size()]); - } - public static String hashKeyForDisk(String key) { String cacheKey; try { diff --git a/app/src/main/res/layout/listitem_dir.xml b/app/src/main/res/layout/listitem_dir.xml new file mode 100644 index 0000000000..abe52a2d3d --- /dev/null +++ b/app/src/main/res/layout/listitem_dir.xml @@ -0,0 +1,37 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 576024c764..a923b15480 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -64,6 +64,10 @@ Cache cleared. %1$d files have been deleted An error occurred clearing cache + + Send crash reports + Help fixing bugs. Sensitive data is not sent + Login for %1$s diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index a63e25d9c0..258b513d42 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -50,6 +50,21 @@ #e5e5e5 + + + +