diff options
5 files changed, 137 insertions, 73 deletions
diff --git a/app/build.gradle b/app/build.gradle index 3368af0d6..5a391b45e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -19,6 +19,7 @@ dependencies { compile("org.shredzone.flattr4j:flattr4j-core:$flattr4jVersion") { exclude group: "org.json", module: "json" } + compile "commons-io:commons-io:$commonsioVersion" compile "org.jsoup:jsoup:$jsoupVersion" compile "com.github.bumptech.glide:glide:$glideVersion" diff --git a/app/src/main/java/de/danoeh/antennapod/activity/DirectoryChooserActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/DirectoryChooserActivity.java index 86ca90eb5..c68e7f862 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/DirectoryChooserActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/DirectoryChooserActivity.java @@ -1,7 +1,6 @@ package de.danoeh.antennapod.activity; import android.app.Activity; -import android.content.DialogInterface; import android.content.Intent; import android.os.Bundle; import android.os.Environment; @@ -15,23 +14,28 @@ import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; -import android.widget.*; -import android.widget.AdapterView.OnItemClickListener; -import de.danoeh.antennapod.BuildConfig; -import de.danoeh.antennapod.R; -import de.danoeh.antennapod.core.preferences.UserPreferences; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.ImageButton; +import android.widget.ListView; +import android.widget.TextView; +import android.widget.Toast; import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import de.danoeh.antennapod.BuildConfig; +import de.danoeh.antennapod.R; +import de.danoeh.antennapod.core.preferences.UserPreferences; + /** * Let's the user choose a directory on the storage device. The selected folder * will be sent back to the starting activity as an activity result. */ public class DirectoryChooserActivity extends ActionBarActivity { - private static final String TAG = "DirectoryChooserActivity"; + private static final String TAG = "DirectoryChooserActivit"; private static final String CREATE_DIRECTORY_NAME = "AntennaPod"; @@ -103,7 +107,7 @@ public class DirectoryChooserActivity extends ActionBarActivity { listDirectories.setOnItemClickListener((adapter, view, position, id) -> { Log.d(TAG, "Selected index: " + position); - if (filesInDir != null && position >= 0 + if (filesInDir != null && position >= 0 && position < filesInDir.length) { changeDirectory(filesInDir[position]); } @@ -137,7 +141,7 @@ public class DirectoryChooserActivity extends ActionBarActivity { resultData.putExtra(RESULT_SELECTED_DIR, selectedDir.getAbsolutePath()); } - setResult(RESULT_CODE_DIR_SELECTED, resultData); + setResult(Activity.RESULT_OK, resultData); finish(); } @@ -157,6 +161,13 @@ public class DirectoryChooserActivity extends ActionBarActivity { } } + @Override + public void onStop() { + super.onStop(); + listDirectoriesAdapter = null; + fileObserver = null; + } + /** * Change the directory that is currently being displayed. * @@ -191,20 +202,15 @@ public class DirectoryChooserActivity extends ActionBarActivity { listDirectoriesAdapter.notifyDataSetChanged(); fileObserver = createFileObserver(dir.getAbsolutePath()); fileObserver.startWatching(); - if (BuildConfig.DEBUG) - Log.d(TAG, "Changed directory to " + dir.getAbsolutePath()); + Log.d(TAG, "Changed directory to " + dir.getAbsolutePath()); } else { - if (BuildConfig.DEBUG) - Log.d(TAG, - "Could not change folder: contents of dir were null"); + Log.d(TAG, "Could not change folder: contents of dir were null"); } } else { if (dir == null) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Could not change folder: dir was null"); + Log.d(TAG, "Could not change folder: dir was null"); } else { - if (BuildConfig.DEBUG) - Log.d(TAG, "Could not change folder: dir is no directory"); + Log.d(TAG, "Could not change folder: dir is no directory"); } } refreshButtonState(); @@ -235,15 +241,8 @@ public class DirectoryChooserActivity extends ActionBarActivity { @Override public void onEvent(int event, String path) { - if (BuildConfig.DEBUG) - Log.d(TAG, "FileObserver received event " + event); - runOnUiThread(new Runnable() { - - @Override - public void run() { - refreshDirectory(); - } - }); + Log.d(TAG, "FileObserver received event " + event); + runOnUiThread(() -> refreshDirectory()); } }; } @@ -292,25 +291,17 @@ public class DirectoryChooserActivity extends ActionBarActivity { builder.setMessage(String.format(getString(R.string.create_folder_msg), CREATE_DIRECTORY_NAME)); builder.setNegativeButton(R.string.cancel_label, - new DialogInterface.OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, int which) { - dialog.dismiss(); - } - }); + (dialog, which) -> { + dialog.dismiss(); + }); builder.setPositiveButton(R.string.confirm_label, - new DialogInterface.OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, int which) { - dialog.dismiss(); - int msg = createFolder(); - Toast t = Toast.makeText(DirectoryChooserActivity.this, - msg, Toast.LENGTH_SHORT); - t.show(); - } - }); + (dialog, which) -> { + dialog.dismiss(); + int msg = createFolder(); + Toast t = Toast.makeText(DirectoryChooserActivity.this, + msg, Toast.LENGTH_SHORT); + t.show(); + }); builder.create().show(); } @@ -340,7 +331,6 @@ public class DirectoryChooserActivity extends ActionBarActivity { /** Returns true if the selected file or directory would be valid selection. */ private boolean isValidFile(File file) { - return (file != null && file.isDirectory() && file.canRead() && file - .canWrite()); + return file != null && file.isDirectory() && file.canRead() && file.canWrite(); } } diff --git a/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java b/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java index f729ef807..73d7da0f2 100644 --- a/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java +++ b/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java @@ -1,5 +1,6 @@ package de.danoeh.antennapod.preferences; +import android.annotation.SuppressLint; import android.app.Activity; import android.app.TimePickerDialog; import android.content.Context; @@ -16,8 +17,10 @@ import android.preference.ListPreference; import android.preference.Preference; import android.preference.PreferenceManager; import android.preference.PreferenceScreen; +import android.support.v4.content.ContextCompat; import android.support.v7.app.AlertDialog; import android.text.Editable; +import android.text.Html; import android.text.TextWatcher; import android.text.format.DateFormat; import android.util.Log; @@ -31,7 +34,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import de.danoeh.antennapod.BuildConfig; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.AboutActivity; import de.danoeh.antennapod.activity.DirectoryChooserActivity; @@ -41,6 +43,8 @@ import de.danoeh.antennapod.activity.PreferenceActivityGingerbread; import de.danoeh.antennapod.asynctask.OpmlExportWorker; import de.danoeh.antennapod.core.preferences.GpodnetPreferences; import de.danoeh.antennapod.core.preferences.UserPreferences; +import de.danoeh.antennapod.core.util.Converter; +import de.danoeh.antennapod.core.util.StorageUtils; import de.danoeh.antennapod.core.util.flattr.FlattrUtils; import de.danoeh.antennapod.dialog.AuthenticationDialog; import de.danoeh.antennapod.dialog.AutoFlattrPreferenceDialog; @@ -50,9 +54,11 @@ import de.danoeh.antennapod.dialog.VariableSpeedDialog; /** * Sets up a preference UI that lets the user change user preferences. */ + public class PreferenceController implements SharedPreferences.OnSharedPreferenceChangeListener { private static final String TAG = "PreferenceController"; + public static final String PREF_FLATTR_SETTINGS = "prefFlattrSettings"; public static final String PREF_FLATTR_AUTH = "pref_flattr_authenticate"; public static final String PREF_FLATTR_REVOKE = "prefRevokeAccess"; @@ -158,21 +164,22 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc } } ); - - ui.findPreference(PreferenceController.PREF_CHOOSE_DATA_DIR).setOnPreferenceClickListener( - new Preference.OnPreferenceClickListener() { - - @Override - public boolean onPreferenceClick(Preference preference) { - activity.startActivityForResult( - new Intent(activity, - DirectoryChooserActivity.class), - DirectoryChooserActivity.RESULT_CODE_DIR_SELECTED - ); - return true; - } - } - ); + ui.findPreference(PreferenceController.PREF_CHOOSE_DATA_DIR) + .setOnPreferenceClickListener( + new Preference.OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(Preference preference) { + if(Build.VERSION.SDK_INT >= 19) { + showChooseDataFolderDialog(); + } else { + Intent intent = new Intent(activity, DirectoryChooserActivity.class); + activity.startActivityForResult(intent, + DirectoryChooserActivity.RESULT_CODE_DIR_SELECTED); + } + return true; + } + } + ); ui.findPreference(UserPreferences.PREF_THEME) .setOnPreferenceChangeListener( new Preference.OnPreferenceChangeListener() { @@ -394,16 +401,37 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc updateGpodnetPreferenceScreen(); } + @SuppressLint("NewApi") public void onActivityResult(int requestCode, int resultCode, Intent data) { - if (resultCode == DirectoryChooserActivity.RESULT_CODE_DIR_SELECTED) { - String dir = data - .getStringExtra(DirectoryChooserActivity.RESULT_SELECTED_DIR); - if (BuildConfig.DEBUG) - Log.d(TAG, "Setting data folder"); - UserPreferences.setDataFolder(dir); + if (resultCode == Activity.RESULT_OK && + requestCode == DirectoryChooserActivity.RESULT_CODE_DIR_SELECTED) { + String dir = data.getStringExtra(DirectoryChooserActivity.RESULT_SELECTED_DIR); + + File path = new File(dir); + String message = null; + final Context context= ui.getActivity().getApplicationContext(); + if(!path.exists()) { + message = String.format(context.getString(R.string.folder_does_not_exist_error), dir); + } else if(!path.canRead()) { + message = String.format(context.getString(R.string.folder_not_readable_error), dir); + } else if(!path.canWrite()) { + message = String.format(context.getString(R.string.folder_not_writable_error), dir); + } + + if(message == null) { + Log.d(TAG, "Setting data folder: " + dir); + UserPreferences.setDataFolder(dir); + setDataFolderText(); + } else { + AlertDialog.Builder ab = new AlertDialog.Builder(ui.getActivity()); + ab.setMessage(message); + ab.setPositiveButton(android.R.string.ok, null); + ab.show(); + } } } + private void updateGpodnetPreferenceScreen() { final boolean loggedIn = GpodnetPreferences.loggedIn(); ui.findPreference(PreferenceController.PREF_GPODNET_LOGIN).setEnabled(!loggedIn); @@ -564,9 +592,7 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc ); boolean newValue = ((CheckBoxPreference) preference) .isChecked(); - if (BuildConfig.DEBUG) - Log.d(TAG, "Selected network " + key - + ". New state: " + newValue); + Log.d(TAG, "Selected network " + key + ". New state: " + newValue); int index = prefValuesList.indexOf(key); if (index >= 0 && newValue == false) { @@ -649,6 +675,47 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc builder.create().show(); } + private void showChooseDataFolderDialog() { + Context context = ui.getActivity(); + String dataFolder = UserPreferences.getDataFolder(context, null).getAbsolutePath(); + int selectedIndex = -1; + File[] mediaDirs = ContextCompat.getExternalFilesDirs(context, null); + String[] folders = new String[mediaDirs.length]; + CharSequence[] choices = new CharSequence[mediaDirs.length]; + for(int i=0; i < mediaDirs.length; i++) { + String path = folders[i] = mediaDirs[i].getAbsolutePath(); + if(dataFolder.equals(path)) { + selectedIndex = i; + } + int index = path.indexOf("Android"); + if(index >= 0) { + choices[i] = path.substring(0, index); + } else { + choices[i] = path; + } + long bytes = StorageUtils.getFreeSpaceAvailable(); + String freeSpace = String.format(context.getString(R.string.free_space_label), + Converter.byteToString(bytes)); + choices[i] = Html.fromHtml("<html><small>" + choices[i] + + " [" + freeSpace + "]" + "</small></html>"); + } + MaterialDialog dialog = new MaterialDialog.Builder(ui.getActivity()) + .title(R.string.choose_data_directory) + .content(R.string.choose_data_directory_message) + .items(choices) + .itemsCallbackSingleChoice(selectedIndex, (dialog1, itemView, which, text) -> { + String folder = folders[which]; + Log.d(TAG, "data folder: " + folder); + UserPreferences.setDataFolder(folder); + setDataFolderText(); + return true; + }) + .negativeText(R.string.cancel_label) + .cancelable(true) + .build(); + dialog.show(); + } + private void showUpdateIntervalTimePreferencesDialog() { final Context context = ui.getActivity(); diff --git a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java index d3c4d3ffd..6de546d3b 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java +++ b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java @@ -565,7 +565,7 @@ public class UserPreferences { } public static void setDataFolder(String dir) { - Log.d(TAG, "Result from DirectoryChooser: " + dir); + Log.d(TAG, "setDataFolder(dir: " + dir + ")"); prefs.edit() .putString(PREF_DATA_FOLDER, dir) .apply(); diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 0c56e1d3e..6cbc5579d 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -25,6 +25,7 @@ <string name="playback_history_label">Playback History</string> <string name="gpodnet_main_label">gpodder.net</string> <string name="gpodnet_auth_label">gpodder.net Login</string> + <string name="free_space_label">"%1$s free</string> <!-- New episodes fragment --> <string name="recently_published_episodes_label">Recently published</string> @@ -464,11 +465,15 @@ <string name="selected_folder_label">Selected folder:</string> <string name="create_folder_label">Create folder</string> <string name="choose_data_directory">Choose Data Folder</string> + <string name="choose_data_directory_message">Please choose the base of your data folder. AntennaPod will create the appropriate sub-directories.</string> <string name="create_folder_msg">Create new folder with name "%1$s"?</string> <string name="create_folder_success">Created new folder</string> <string name="create_folder_error_no_write_access">Cannot write to this folder</string> <string name="create_folder_error_already_exists">Folder already exists</string> <string name="create_folder_error">Could not create folder</string> + <string name="folder_does_not_exist_error">"%1$s" does not exist</string> + <string name="folder_not_readable_error">"%1$s" is not readable</string> + <string name="folder_not_writable_error">"%1$s" is not writable</string> <string name="folder_not_empty_dialog_title">Folder is not empty</string> <string name="folder_not_empty_dialog_msg">The folder you have selected is not empty. Media downloads and other files will be placed directly in this folder. Continue anyway?</string> <string name="set_to_default_folder">Choose default folder</string> @@ -478,6 +483,7 @@ <string name="pref_resumeAfterCall_title">Resume after Call</string> <string name="pref_restart_required">AntennaPod has to be restarted for this change to take effect.</string> + <!-- Online feed view --> <string name="subscribe_label">Subscribe</string> <string name="subscribed_label">Subscribed</string> |