Replace DirectoryChooser with simple dialog listing all external directories

This commit is contained in:
Martin Fietz 2015-09-17 17:19:05 +02:00
parent cc326c33df
commit 06cdd987e0
5 changed files with 137 additions and 73 deletions

View File

@ -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"

View File

@ -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();
}
}

View File

@ -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();

View File

@ -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();

View File

@ -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>