Merge branch 'master' into develop

This commit is contained in:
ByteHamster 2020-07-16 16:59:45 +02:00
commit 663c715e3f
15 changed files with 75 additions and 756 deletions

View File

@ -14,8 +14,8 @@ android {
// "1.2.3-SNAPSHOT" -> 1020300
// "1.2.3-RC4" -> 1020304
// "1.2.3" -> 1020395
versionCode 2000005
versionName "2.0.0-RC5"
versionCode 2000006
versionName "2.0.0-RC6"
multiDexEnabled false
vectorDrawables.useSupportLibrary true

View File

@ -192,13 +192,6 @@
<data android:mimeType="video/*"/>
</intent-filter>
</activity>
<activity
android:name=".activity.DirectoryChooserActivity"
android:label="@string/choose_data_directory">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="de.danoeh.antennapod.activity.PreferenceActivity"/>
</activity>
<activity
android:name=".activity.OnlineFeedViewActivity"

View File

@ -1,333 +0,0 @@
package de.danoeh.antennapod.activity;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Environment;
import android.os.FileObserver;
import androidx.core.app.NavUtils;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
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 AppCompatActivity {
private static final String TAG = "DirectoryChooserActivit";
private static final String CREATE_DIRECTORY_NAME = "AntennaPod";
public static final String RESULT_SELECTED_DIR = "selected_dir";
public static final int RESULT_CODE_DIR_SELECTED = 1;
private Button butConfirm;
private Button butCancel;
private ImageButton butNavUp;
private TextView txtvSelectedFolder;
private ListView listDirectories;
private ArrayAdapter<String> listDirectoriesAdapter;
private ArrayList<String> filenames;
/** The directory that is currently being shown. */
private File selectedDir;
private File[] filesInDir;
private FileObserver fileObserver;
@Override
protected void onCreate(Bundle savedInstanceState) {
setTheme(UserPreferences.getTheme());
super.onCreate(savedInstanceState);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
setContentView(R.layout.directory_chooser);
butConfirm = findViewById(R.id.butConfirm);
butCancel = findViewById(R.id.butCancel);
butNavUp = findViewById(R.id.butNavUp);
txtvSelectedFolder = findViewById(R.id.txtvSelectedFolder);
listDirectories = findViewById(R.id.directory_list);
butConfirm.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (isValidFile(selectedDir)) {
if (selectedDir.list().length == 0) {
returnSelectedFolder();
} else {
showNonEmptyDirectoryWarning();
}
}
}
private void showNonEmptyDirectoryWarning() {
AlertDialog.Builder adb = new AlertDialog.Builder(
DirectoryChooserActivity.this);
adb.setTitle(R.string.folder_not_empty_dialog_title);
adb.setMessage(R.string.folder_not_empty_dialog_msg);
adb.setNegativeButton(R.string.cancel_label,
(dialog, which) -> dialog.dismiss());
adb.setPositiveButton(R.string.confirm_label,
(dialog, which) -> {
dialog.dismiss();
returnSelectedFolder();
});
adb.create().show();
}
});
butCancel.setOnClickListener(v -> {
setResult(Activity.RESULT_CANCELED);
finish();
});
listDirectories.setOnItemClickListener((adapter, view, position, id) -> {
Log.d(TAG, "Selected index: " + position);
if (filesInDir != null && position >= 0
&& position < filesInDir.length) {
changeDirectory(filesInDir[position]);
}
});
butNavUp.setOnClickListener(v -> {
File parent;
if (selectedDir != null
&& (parent = selectedDir.getParentFile()) != null) {
changeDirectory(parent);
}
});
filenames = new ArrayList<>();
listDirectoriesAdapter = new ArrayAdapter<>(this,
android.R.layout.simple_list_item_1, filenames);
listDirectories.setAdapter(listDirectoriesAdapter);
changeDirectory(Environment.getExternalStorageDirectory());
}
/**
* Finishes the activity and returns the selected folder as a result. The
* selected folder can also be null.
*/
private void returnSelectedFolder() {
if (selectedDir != null && BuildConfig.DEBUG)
Log.d(TAG, "Returning " + selectedDir.getAbsolutePath()
+ " as result");
Intent resultData = new Intent();
if (selectedDir != null) {
resultData.putExtra(RESULT_SELECTED_DIR,
selectedDir.getAbsolutePath());
}
setResult(Activity.RESULT_OK, resultData);
finish();
}
@Override
protected void onPause() {
super.onPause();
if (fileObserver != null) {
fileObserver.stopWatching();
}
}
@Override
protected void onResume() {
super.onResume();
if (fileObserver != null) {
fileObserver.startWatching();
}
}
@Override
public void onStop() {
super.onStop();
listDirectoriesAdapter = null;
fileObserver = null;
}
/**
* Change the directory that is currently being displayed.
*
* @param dir
* The file the activity should switch to. This File must be
* non-null and a directory, otherwise the displayed directory
* will not be changed
*/
private void changeDirectory(File dir) {
if (dir != null && dir.isDirectory()) {
File[] contents = dir.listFiles();
if (contents != null) {
int numDirectories = 0;
for (File f : contents) {
if (f.isDirectory()) {
numDirectories++;
}
}
filesInDir = new File[numDirectories];
filenames.clear();
for (int i = 0, counter = 0; i < numDirectories; counter++) {
if (contents[counter].isDirectory()) {
filesInDir[i] = contents[counter];
filenames.add(contents[counter].getName());
i++;
}
}
Arrays.sort(filesInDir);
Collections.sort(filenames);
selectedDir = dir;
txtvSelectedFolder.setText(dir.getAbsolutePath());
listDirectoriesAdapter.notifyDataSetChanged();
fileObserver = createFileObserver(dir.getAbsolutePath());
fileObserver.startWatching();
Log.d(TAG, "Changed directory to " + dir.getAbsolutePath());
} else {
Log.d(TAG, "Could not change folder: contents of dir were null");
}
} else {
if (dir == null) {
Log.d(TAG, "Could not change folder: dir was null");
} else {
Log.d(TAG, "Could not change folder: dir is no directory");
}
}
refreshButtonState();
}
/**
* Changes the state of the buttons depending on the currently selected file
* or folder.
*/
private void refreshButtonState() {
if (selectedDir != null) {
butConfirm.setEnabled(isValidFile(selectedDir));
supportInvalidateOptionsMenu();
}
}
/** Refresh the contents of the directory that is currently shown. */
private void refreshDirectory() {
if (selectedDir != null) {
changeDirectory(selectedDir);
}
}
/** Sets up a FileObserver to watch the current directory. */
private FileObserver createFileObserver(String path) {
return new FileObserver(path, FileObserver.CREATE | FileObserver.DELETE
| FileObserver.MOVED_FROM | FileObserver.MOVED_TO) {
@Override
public void onEvent(int event, String path) {
Log.d(TAG, "FileObserver received event " + event);
runOnUiThread(DirectoryChooserActivity.this::refreshDirectory);
}
};
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
menu.findItem(R.id.new_folder_item).setVisible(isValidFile(selectedDir));
return true;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.directory_chooser, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
NavUtils.navigateUpFromSameTask(this);
return true;
case R.id.new_folder_item:
openNewFolderDialog();
return true;
case R.id.set_to_default_folder_item:
selectedDir = null;
returnSelectedFolder();
return true;
default:
return false;
}
}
/**
* Shows a confirmation dialog that asks the user if he wants to create a
* new folder.
*/
private void openNewFolderDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.create_folder_label);
builder.setMessage(String.format(getString(R.string.create_folder_msg),
CREATE_DIRECTORY_NAME));
builder.setNegativeButton(R.string.cancel_label,
(dialog, which) -> dialog.dismiss());
builder.setPositiveButton(R.string.confirm_label,
(dialog, which) -> {
dialog.dismiss();
int msg = createFolder();
Toast t = Toast.makeText(DirectoryChooserActivity.this,
msg, Toast.LENGTH_SHORT);
t.show();
});
builder.create().show();
}
/**
* Creates a new folder in the current directory with the name
* CREATE_DIRECTORY_NAME.
*/
private int createFolder() {
if (selectedDir == null) {
return R.string.create_folder_error;
} else if (selectedDir.canWrite()) {
File newDir = new File(selectedDir, CREATE_DIRECTORY_NAME);
if (!newDir.exists()) {
boolean result = newDir.mkdir();
if (result) {
return R.string.create_folder_success;
} else {
return R.string.create_folder_error;
}
} else {
return R.string.create_folder_error_already_exists;
}
} else {
return R.string.create_folder_error_no_write_access;
}
}
/** 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();
}
}

View File

@ -1,38 +1,25 @@
package de.danoeh.antennapod.activity;
import android.Manifest;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import androidx.core.app.ActivityCompat;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Button;
import java.io.File;
import androidx.appcompat.app.AppCompatActivity;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.util.StorageUtils;
import de.danoeh.antennapod.dialog.ChooseDataFolderDialog;
/** Is show if there is now external storage available. */
/**
* Is show if there is now external storage available.
*/
public class StorageErrorActivity extends AppCompatActivity {
private static final String TAG = "StorageErrorActivity";
private static final String[] EXTERNAL_STORAGE_PERMISSIONS = {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE };
private static final int PERMISSION_REQUEST_EXTERNAL_STORAGE = 42;
@Override
protected void onCreate(Bundle savedInstanceState) {
setTheme(UserPreferences.getTheme());
@ -41,51 +28,11 @@ public class StorageErrorActivity extends AppCompatActivity {
setContentView(R.layout.storage_error);
Button btnChooseDataFolder = findViewById(R.id.btnChooseDataFolder);
btnChooseDataFolder.setOnClickListener(v -> {
if (Build.VERSION_CODES.KITKAT <= Build.VERSION.SDK_INT &&
Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP_MR1) {
showChooseDataFolderDialog();
} else {
openDirectoryChooser();
}
});
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
int readPermission = ActivityCompat.checkSelfPermission(this,
Manifest.permission.READ_EXTERNAL_STORAGE);
int writePermission = ActivityCompat.checkSelfPermission(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (readPermission != PackageManager.PERMISSION_GRANTED ||
writePermission != PackageManager.PERMISSION_GRANTED) {
requestPermission();
}
}
}
private void requestPermission() {
ActivityCompat.requestPermissions(this, EXTERNAL_STORAGE_PERMISSIONS,
PERMISSION_REQUEST_EXTERNAL_STORAGE);
}
private void openDirectoryChooser() {
Intent intent = new Intent(this, DirectoryChooserActivity.class);
startActivityForResult(intent, DirectoryChooserActivity.RESULT_CODE_DIR_SELECTED);
}
@Override
public void onRequestPermissionsResult(int requestCode,
String[] permissions,
int[] grantResults) {
if (requestCode != PERMISSION_REQUEST_EXTERNAL_STORAGE || grantResults.length != 2) {
return;
}
if (grantResults[0] != PackageManager.PERMISSION_GRANTED ||
grantResults[1] != PackageManager.PERMISSION_GRANTED) {
new AlertDialog.Builder(this)
.setMessage(R.string.choose_data_directory_permission_rationale)
.setPositiveButton(android.R.string.ok, (dialog, which) -> requestPermission())
.setNegativeButton(android.R.string.cancel, (dialog, which) -> finish())
.show();
}
btnChooseDataFolder.setOnClickListener(v ->
ChooseDataFolderDialog.showDialog(this, path -> {
UserPreferences.setDataFolder(path);
leaveErrorState();
}));
}
@Override
@ -108,55 +55,6 @@ public class StorageErrorActivity extends AppCompatActivity {
}
}
// see PreferenceController.showChooseDataFolderDialog()
private void showChooseDataFolderDialog() {
ChooseDataFolderDialog.showDialog(
this, new ChooseDataFolderDialog.RunnableWithString() {
@Override
public void run(final String folder) {
UserPreferences.setDataFolder(folder);
leaveErrorState();
}
});
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK
&& requestCode == DirectoryChooserActivity.RESULT_CODE_DIR_SELECTED) {
String dir = data.getStringExtra(DirectoryChooserActivity.RESULT_SELECTED_DIR);
File path;
if (dir != null) {
path = new File(dir);
} else {
path = getExternalFilesDir(null);
}
if (path == null) {
return;
}
String message = null;
if (!path.exists()) {
message = String.format(getString(R.string.folder_does_not_exist_error), dir);
} else if (!path.canRead()) {
message = String.format(getString(R.string.folder_not_readable_error), dir);
} else if (!path.canWrite()) {
message = String.format(getString(R.string.folder_not_writable_error), dir);
}
if (message == null) {
Log.d(TAG, "Setting data folder: " + dir);
UserPreferences.setDataFolder(dir);
leaveErrorState();
} else {
AlertDialog.Builder ab = new AlertDialog.Builder(this);
ab.setMessage(message);
ab.setPositiveButton(android.R.string.ok, null);
ab.show();
}
}
}
private void leaveErrorState() {
finish();
startActivity(new Intent(this, MainActivity.class));

View File

@ -1,6 +1,5 @@
package de.danoeh.antennapod.adapter;
import android.app.Dialog;
import android.content.Context;
import android.text.format.Formatter;
import android.view.LayoutInflater;
@ -9,29 +8,25 @@ import android.view.ViewGroup;
import android.widget.ProgressBar;
import android.widget.RadioButton;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.core.util.Consumer;
import androidx.recyclerview.widget.RecyclerView;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.util.StorageUtils;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.util.StorageUtils;
import de.danoeh.antennapod.dialog.ChooseDataFolderDialog;
public class DataFolderAdapter extends RecyclerView.Adapter<DataFolderAdapter.ViewHolder> {
private final ChooseDataFolderDialog.RunnableWithString selectionHandler;
private final Consumer<String> selectionHandler;
private final String currentPath;
private final List<StoragePath> entries;
private final String freeSpaceString;
private Dialog dialog;
public DataFolderAdapter(Context context, ChooseDataFolderDialog.RunnableWithString selectionHandler) {
public DataFolderAdapter(Context context, @NonNull Consumer<String> selectionHandler) {
this.entries = getStorageEntries(context);
this.currentPath = getCurrentPath();
this.selectionHandler = selectionHandler;
@ -56,8 +51,10 @@ public class DataFolderAdapter extends RecyclerView.Adapter<DataFolderAdapter.Vi
holder.path.setText(storagePath.getShortPath());
holder.size.setText(String.format(freeSpaceString, freeSpace, totalSpace));
holder.progressBar.setProgress(storagePath.getUsagePercentage());
holder.root.setOnClickListener((View v) -> selectAndDismiss(storagePath));
holder.radioButton.setOnClickListener((View v) -> selectAndDismiss(storagePath));
View.OnClickListener selectListener = v -> selectionHandler.accept(storagePath.getFullPath());
holder.root.setOnClickListener(selectListener);
holder.radioButton.setOnClickListener(selectListener);
if (storagePath.getFullPath().equals(currentPath)) {
holder.radioButton.toggle();
}
@ -65,20 +62,14 @@ public class DataFolderAdapter extends RecyclerView.Adapter<DataFolderAdapter.Vi
@Override
public int getItemCount() {
if (currentPath == null) {
return 0;
} else {
return entries.size();
}
}
public void setDialog(Dialog dialog) {
this.dialog = dialog;
return entries.size();
}
private String getCurrentPath() {
File dataFolder = UserPreferences.getDataFolder(null);
if (dataFolder != null) return dataFolder.getAbsolutePath();
if (dataFolder != null) {
return dataFolder.getAbsolutePath();
}
return null;
}
@ -86,28 +77,27 @@ public class DataFolderAdapter extends RecyclerView.Adapter<DataFolderAdapter.Vi
File[] mediaDirs = ContextCompat.getExternalFilesDirs(context, null);
final List<StoragePath> entries = new ArrayList<>(mediaDirs.length);
for (File dir : mediaDirs) {
if (isNotWritable(dir)) continue;
if (!isWritable(dir)) {
continue;
}
entries.add(new StoragePath(dir.getAbsolutePath()));
}
if (entries.isEmpty() && isWritable(context.getFilesDir())) {
entries.add(new StoragePath(context.getFilesDir().getAbsolutePath()));
}
return entries;
}
private boolean isNotWritable(File dir) {
return dir == null || !dir.exists() || !dir.canRead() || !dir.canWrite();
}
private void selectAndDismiss(StoragePath storagePath) {
selectionHandler.run(storagePath.getFullPath());
dialog.dismiss();
private boolean isWritable(File dir) {
return dir != null && dir.exists() && dir.canRead() && dir.canWrite();
}
static class ViewHolder extends RecyclerView.ViewHolder {
private View root;
private TextView path;
private TextView size;
private RadioButton radioButton;
private ProgressBar progressBar;
private final View root;
private final TextView path;
private final TextView size;
private final RadioButton radioButton;
private final ProgressBar progressBar;
ViewHolder(View itemView) {
super(itemView);

View File

@ -4,6 +4,7 @@ import android.content.Context;
import android.view.View;
import androidx.appcompat.app.AlertDialog;
import androidx.core.util.Consumer;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import de.danoeh.antennapod.R;
@ -11,29 +12,7 @@ import de.danoeh.antennapod.adapter.DataFolderAdapter;
public class ChooseDataFolderDialog {
public abstract static class RunnableWithString implements Runnable {
public RunnableWithString() {
super();
}
public abstract void run(final String arg);
@Override public void run() {
throw new IllegalArgumentException("Expect one String parameter.");
}
}
private ChooseDataFolderDialog() {}
public static void showDialog(final Context context, RunnableWithString handlerFunc) {
DataFolderAdapter adapter = new DataFolderAdapter(context, handlerFunc);
if (adapter.getItemCount() == 0) {
new AlertDialog.Builder(context)
.setTitle(R.string.error_label)
.setMessage(R.string.external_storage_error_msg)
.setPositiveButton(android.R.string.ok, null)
.show();
return;
}
public static void showDialog(final Context context, Consumer<String> handlerFunc) {
View content = View.inflate(context, R.layout.choose_data_folder_dialog, null);
AlertDialog dialog = new AlertDialog.Builder(context)
@ -43,9 +22,22 @@ public class ChooseDataFolderDialog {
.setNegativeButton(R.string.cancel_label, null)
.create();
((RecyclerView) content.findViewById(R.id.recyclerView)).setLayoutManager(new LinearLayoutManager(context));
DataFolderAdapter adapter = new DataFolderAdapter(context, path -> {
dialog.dismiss();
handlerFunc.accept(path);
});
((RecyclerView) content.findViewById(R.id.recyclerView)).setAdapter(adapter);
adapter.setDialog(dialog);
dialog.show();
if (adapter.getItemCount() > 0) {
dialog.show();
} else {
new AlertDialog.Builder(context)
.setTitle(R.string.error_label)
.setMessage(R.string.external_storage_error_msg)
.setPositiveButton(android.R.string.ok, null)
.show();
}
}
}

View File

@ -1,18 +1,9 @@
package de.danoeh.antennapod.fragment.preferences;
import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import androidx.appcompat.app.AlertDialog;
import androidx.core.app.ActivityCompat;
import androidx.preference.PreferenceFragmentCompat;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.DirectoryChooserActivity;
import de.danoeh.antennapod.activity.PreferenceActivity;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.dialog.ChooseDataFolderDialog;
@ -23,10 +14,6 @@ public class StoragePreferencesFragment extends PreferenceFragmentCompat {
private static final String TAG = "StoragePrefFragment";
private static final String PREF_CHOOSE_DATA_DIR = "prefChooseDataDir";
private static final String PREF_IMPORT_EXPORT = "prefImportExport";
private static final String[] EXTERNAL_STORAGE_PERMISSIONS = {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE };
private static final int PERMISSION_REQUEST_EXTERNAL_STORAGE = 41;
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
@ -47,36 +34,12 @@ public class StoragePreferencesFragment extends PreferenceFragmentCompat {
}
private void setupStorageScreen() {
final Activity activity = getActivity();
findPreference(PREF_CHOOSE_DATA_DIR).setOnPreferenceClickListener(
preference -> {
if (Build.VERSION_CODES.KITKAT <= Build.VERSION.SDK_INT
&& Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP_MR1) {
showChooseDataFolderDialog();
} else {
int readPermission = ActivityCompat.checkSelfPermission(
activity, Manifest.permission.READ_EXTERNAL_STORAGE);
int writePermission = ActivityCompat.checkSelfPermission(
activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (readPermission == PackageManager.PERMISSION_GRANTED
&& writePermission == PackageManager.PERMISSION_GRANTED) {
openDirectoryChooser();
} else {
requestPermission();
}
}
return true;
}
);
findPreference(PREF_CHOOSE_DATA_DIR).setOnPreferenceClickListener(
preference -> {
if (Build.VERSION.SDK_INT >= 19) {
showChooseDataFolderDialog();
} else {
Intent intent = new Intent(activity, DirectoryChooserActivity.class);
activity.startActivityForResult(intent,
DirectoryChooserActivity.RESULT_CODE_DIR_SELECTED);
}
ChooseDataFolderDialog.showDialog(getContext(), path -> {
UserPreferences.setDataFolder(path);
setDataFolderText();
});
return true;
}
);
@ -104,65 +67,10 @@ public class StoragePreferencesFragment extends PreferenceFragmentCompat {
);
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == Activity.RESULT_OK && requestCode == DirectoryChooserActivity.RESULT_CODE_DIR_SELECTED) {
String dir = data.getStringExtra(DirectoryChooserActivity.RESULT_SELECTED_DIR);
File path;
if (dir != null) {
path = new File(dir);
} else {
path = getActivity().getExternalFilesDir(null);
}
String message = null;
final Context context = 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(getActivity());
ab.setMessage(message);
ab.setPositiveButton(android.R.string.ok, null);
ab.show();
}
}
}
private void setDataFolderText() {
File f = UserPreferences.getDataFolder(null);
if (f != null) {
findPreference(PREF_CHOOSE_DATA_DIR).setSummary(f.getAbsolutePath());
}
}
private void requestPermission() {
ActivityCompat.requestPermissions(getActivity(), EXTERNAL_STORAGE_PERMISSIONS,
PERMISSION_REQUEST_EXTERNAL_STORAGE);
}
private void openDirectoryChooser() {
Activity activity = getActivity();
Intent intent = new Intent(activity, DirectoryChooserActivity.class);
activity.startActivityForResult(intent, DirectoryChooserActivity.RESULT_CODE_DIR_SELECTED);
}
private void showChooseDataFolderDialog() {
ChooseDataFolderDialog.showDialog(
getActivity(), new ChooseDataFolderDialog.RunnableWithString() {
@Override
public void run(final String folder) {
UserPreferences.setDataFolder(folder);
setDataFolderText();
}
});
}
}

View File

@ -68,7 +68,7 @@ public class ShownotesWebView extends WebView implements View.OnLongClickListene
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (Timeline.isTimecodeLink(url) && timecodeSelectedListener != null) {
timecodeSelectedListener.accept(Timeline.getTimecodeLinkTime(selectedUrl));
timecodeSelectedListener.accept(Timeline.getTimecodeLinkTime(url));
} else {
IntentUtils.openInBrowser(getContext(), url);
}

View File

@ -1,122 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:background="@android:color/darker_gray">
<RelativeLayout
android:id="@+id/footer"
android:layout_width="fill_parent"
android:layout_height="48dp"
android:layout_alignParentBottom="true" >
<View
android:layout_width="match_parent"
android:layout_height="1dip"
android:layout_alignParentTop="true"
android:background="?android:attr/dividerVertical" />
<View
android:id="@+id/horizontal_divider"
android:layout_width="1dip"
android:layout_height="fill_parent"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="4dp"
android:layout_marginTop="4dp"
android:background="?android:attr/dividerVertical" />
<Button
android:id="@+id/butCancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_toLeftOf="@id/horizontal_divider"
android:layout_toStartOf="@id/horizontal_divider"
android:background="?android:attr/selectableItemBackground"
android:text="@string/cancel_label" />
<Button
android:id="@+id/butConfirm"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_alignParentTop="true"
android:layout_toRightOf="@id/horizontal_divider"
android:layout_toEndOf="@id/horizontal_divider"
android:background="?android:attr/selectableItemBackground"
android:text="@string/confirm_label" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/directory_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true" >
<ImageButton
android:id="@+id/butNavUp"
android:contentDescription="@string/navigate_upwards_label"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:background="?attr/selectableItemBackground"
android:src="?attr/navigation_up"
tools:src="@drawable/navigation_up"
tools:background="@android:color/holo_green_dark" />
<TextView
android:id="@+id/txtvSelectedFolderLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginTop="8dp"
android:layout_toRightOf="@id/butNavUp"
android:layout_toEndOf="@id/butNavUp"
android:text="@string/selected_folder_label"
android:textStyle="bold"
tools:background="@android:color/holo_green_dark">
</TextView>
<TextView
android:id="@+id/txtvSelectedFolder"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_below="@id/txtvSelectedFolderLabel"
android:layout_margin="8dp"
android:layout_toRightOf="@id/butNavUp"
android:layout_toEndOf="@id/butNavUp"
android:ellipsize="start"
android:scrollHorizontally="true"
android:singleLine="true"
tools:text="/path/to/selected/folder"
tools:background="@android:color/holo_green_dark"/>
<View
android:id="@+id/divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_below="@id/butNavUp"
android:background="?android:attr/dividerHorizontal" />
</RelativeLayout>
<ListView
android:id="@+id/directory_list"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_above="@id/footer"
android:layout_below="@id/directory_info" />
</RelativeLayout>

View File

@ -1,16 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<menu
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/new_folder_item"
android:title="@string/create_folder_label"
app:icon="?attr/content_new"
app:showAsAction="ifRoom|withText" />
<item
android:id="@+id/set_to_default_folder_item"
android:title="@string/set_to_default_folder"
app:showAsAction="collapseActionView" />
</menu>

View File

@ -65,7 +65,7 @@ project.ext {
rxAndroidVersion = "2.1.1"
rxJavaVersion = "2.2.2"
iconifyVersion = "2.2.2"
audioPlayerVersion = "v1.0.17"
audioPlayerVersion = "v2.0.0"
// Google Play build
wearableSupportVersion = "2.6.0"

View File

@ -65,11 +65,12 @@ public class HttpDownloader extends Downloader {
final URI uri = URIUtil.getURIFromRequestUrl(request.getSource());
Request.Builder httpReq = new Request.Builder().url(uri.toURL());
httpReq.tag(request);
httpReq.cacheControl(new CacheControl.Builder().noStore().build());
if (request.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA) {
// set header explicitly so that okhttp doesn't do transparent gzip
Log.d(TAG, "addHeader(\"Accept-Encoding\", \"identity\")");
httpReq.addHeader("Accept-Encoding", "identity");
httpReq.cacheControl(new CacheControl.Builder().noStore().build());
}
if (!TextUtils.isEmpty(request.getLastModified())) {

View File

@ -274,7 +274,7 @@ public class DownloadRequester implements DownloadStateProvider {
}
File dest;
if (feedmedia.getFile_url() != null) {
if (feedmedia.getFile_url() != null && new File(feedmedia.getFile_url()).exists()) {
dest = new File(feedmedia.getFile_url());
} else {
dest = new File(getMediafilePath(feedmedia), getMediafilename(feedmedia));

View File

@ -4,7 +4,10 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.util.Log;
import java.net.URLConnection;
import java.util.zip.CheckedOutputStream;
import de.danoeh.antennapod.core.ClientConfig;
import org.apache.commons.io.IOUtils;
import java.io.BufferedInputStream;
@ -80,7 +83,9 @@ public class ChapterUtils {
CountingInputStream in = null;
try {
URL url = new URL(p.getStreamUrl());
in = new CountingInputStream(url.openStream());
URLConnection urlConnection = url.openConnection();
urlConnection.setRequestProperty("User-Agent", ClientConfig.USER_AGENT);
in = new CountingInputStream(urlConnection.getInputStream());
List<Chapter> chapters = readChaptersFrom(in);
if (!chapters.isEmpty()) {
p.setChapters(chapters);
@ -149,7 +154,9 @@ public class ChapterUtils {
InputStream input = null;
try {
URL url = new URL(media.getStreamUrl());
input = url.openStream();
URLConnection urlConnection = url.openConnection();
urlConnection.setRequestProperty("User-Agent", ClientConfig.USER_AGENT);
input = urlConnection.getInputStream();
if (input != null) {
readOggChaptersFromInputStream(media, input);
}

View File

@ -6,6 +6,7 @@ import android.preference.PreferenceManager;
import android.util.Log;
import android.view.SurfaceHolder;
import de.danoeh.antennapod.core.ClientConfig;
import org.antennapod.audio.MediaPlayer;
import de.danoeh.antennapod.core.preferences.UserPreferences;
@ -17,7 +18,7 @@ public class AudioPlayer extends MediaPlayer implements IPlayer {
private static final String TAG = "AudioPlayer";
public AudioPlayer(Context context) {
super(context);
super(context, true, ClientConfig.USER_AGENT);
PreferenceManager.getDefaultSharedPreferences(context)
.registerOnSharedPreferenceChangeListener((sharedPreferences, key) -> {
if (key.equals(UserPreferences.PREF_MEDIA_PLAYER)) {