diff options
author | Martin Fietz <Martin.Fietz@gmail.com> | 2016-02-01 18:29:39 +0100 |
---|---|---|
committer | Martin Fietz <Martin.Fietz@gmail.com> | 2016-02-03 19:35:57 +0100 |
commit | a2e6a0abe161325cc6b403a161d96b002a130ffa (patch) | |
tree | c6c833652cb114b978b22ce2bb90982e3a293bbe /app/src/main | |
parent | 832eb96d56f00aa6046d17d5fce388fabc2bcd06 (diff) | |
download | AntennaPod-a2e6a0abe161325cc6b403a161d96b002a130ffa.zip |
Let user change data folder when storage is not available
Diffstat (limited to 'app/src/main')
3 files changed, 205 insertions, 30 deletions
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/StorageErrorActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/StorageErrorActivity.java index b02e82f0b..870983b97 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/StorageErrorActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/StorageErrorActivity.java @@ -1,21 +1,36 @@ 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.os.Build; import android.os.Bundle; -import android.support.v7.app.ActionBarActivity; +import android.support.v4.app.ActivityCompat; +import android.support.v4.content.ContextCompat; +import android.support.v7.app.AlertDialog; +import android.support.v7.app.AppCompatActivity; +import android.text.Html; import android.text.TextUtils; import android.util.Log; +import android.widget.Button; + +import com.afollestad.materialdialogs.MaterialDialog; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; -import de.danoeh.antennapod.BuildConfig; import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.preferences.UserPreferences; +import de.danoeh.antennapod.core.util.Converter; import de.danoeh.antennapod.core.util.StorageUtils; /** Is show if there is now external storage available. */ -public class StorageErrorActivity extends ActionBarActivity { +public class StorageErrorActivity extends AppCompatActivity { + private static final String TAG = "StorageErrorActivity"; @Override @@ -24,7 +39,65 @@ public class StorageErrorActivity extends ActionBarActivity { super.onCreate(savedInstanceState); setContentView(R.layout.storage_error); - } + + Button btnChooseDataFolder = (Button) 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 MaterialDialog.Builder(this) + .content(R.string.choose_data_directory_permission_rationale) + .positiveText(android.R.string.ok) + .onPositive((dialog, which) -> requestPermission()) + .onNegative((dialog, which) -> finish()) + .show(); + } + } + + @Override + protected void onResume() { + super.onResume(); + if (StorageUtils.storageAvailable()) { + leaveErrorState(); + } else { + registerReceiver(mediaUpdate, new IntentFilter(Intent.ACTION_MEDIA_MOUNTED)); + } + } @Override protected void onPause() { @@ -32,18 +105,97 @@ public class StorageErrorActivity extends ActionBarActivity { try { unregisterReceiver(mediaUpdate); } catch (IllegalArgumentException e) { - + Log.e(TAG, Log.getStackTraceString(e)); } } - @Override - protected void onResume() { - super.onResume(); - if (StorageUtils.storageAvailable()) { - leaveErrorState(); - } else { - registerReceiver(mediaUpdate, new IntentFilter( - Intent.ACTION_MEDIA_MOUNTED)); + // see PreferenceController.showChooseDataFolderDialog() + private void showChooseDataFolderDialog() { + File dataFolder = UserPreferences.getDataFolder(null); + if(dataFolder == null) { + new MaterialDialog.Builder(this) + .title(R.string.error_label) + .content(R.string.external_storage_error_msg) + .neutralText(android.R.string.ok) + .show(); + return; + } + String dataFolderPath = dataFolder.getAbsolutePath(); + int selectedIndex = -1; + File[] mediaDirs = ContextCompat.getExternalFilesDirs(this, null); + List<String> folders = new ArrayList<>(mediaDirs.length); + List<CharSequence> choices = new ArrayList<>(mediaDirs.length); + for(int i=0; i < mediaDirs.length; i++) { + if(mediaDirs[i] == null) { + continue; + } + String path = mediaDirs[i].getAbsolutePath(); + folders.add(path); + if(dataFolderPath.equals(path)) { + selectedIndex = i; + } + int index = path.indexOf("Android"); + String choice; + if(index >= 0) { + choice = path.substring(0, index); + } else { + choice = path; + } + long bytes = StorageUtils.getFreeSpaceAvailable(path); + String freeSpace = String.format(getString(R.string.free_space_label), + Converter.byteToString(bytes)); + choices.add(Html.fromHtml("<html><small>" + choice + " [" + freeSpace + "]" + + "</small></html>")); + } + if(choices.size() == 0) { + new MaterialDialog.Builder(this) + .title(R.string.error_label) + .content(R.string.external_storage_error_msg) + .neutralText(android.R.string.ok) + .show(); + return; + } + MaterialDialog dialog = new MaterialDialog.Builder(this) + .title(R.string.choose_data_directory) + .content(R.string.choose_data_directory_message) + .items(choices.toArray(new CharSequence[choices.size()])) + .itemsCallbackSingleChoice(selectedIndex, (dialog1, itemView, which, text) -> { + String folder = folders.get(which); + UserPreferences.setDataFolder(folder); + leaveErrorState(); + return true; + }) + .negativeText(R.string.cancel_label) + .cancelable(true) + .build(); + dialog.show(); + } + + 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 = new File(dir); + 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(); + } } } @@ -58,13 +210,10 @@ public class StorageErrorActivity extends ActionBarActivity { public void onReceive(Context context, Intent intent) { if (TextUtils.equals(intent.getAction(), Intent.ACTION_MEDIA_MOUNTED)) { if (intent.getBooleanExtra("read-only", true)) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Media was mounted; Finishing activity"); + Log.d(TAG, "Media was mounted; Finishing activity"); leaveErrorState(); } else { - if (BuildConfig.DEBUG) - Log.d(TAG, - "Media seemed to have been mounted read only"); + Log.d(TAG, "Media seemed to have been mounted read only"); } } } 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 785944768..f297618db 100644 --- a/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java +++ b/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java @@ -161,7 +161,6 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc ui.findPreference(PreferenceController.PREF_OPML_EXPORT).setOnPreferenceClickListener( new Preference.OnPreferenceClickListener() { - @Override public boolean onPreferenceClick(Preference preference) { new OpmlExportWorker(activity) @@ -171,6 +170,26 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc } } ); + ui.findPreference(PreferenceController.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; + } + ); ui.findPreference(PreferenceController.PREF_CHOOSE_DATA_DIR) .setOnPreferenceClickListener( new Preference.OnPreferenceClickListener() { diff --git a/app/src/main/res/layout/storage_error.xml b/app/src/main/res/layout/storage_error.xml index c1ee77262..8ff28b3c1 100644 --- a/app/src/main/res/layout/storage_error.xml +++ b/app/src/main/res/layout/storage_error.xml @@ -1,25 +1,32 @@ <?xml version="1.0" encoding="utf-8"?> -<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" - android:layout_height="match_parent" > + android:layout_height="match_parent" + android:orientation="vertical" + android:gravity="center" + android:padding="16dp"> <ImageView android:id="@+id/imageView1" android:contentDescription="@string/external_storage_error_msg" - android:layout_width="30dp" - android:layout_height="30dp" - android:layout_centerHorizontal="true" - android:layout_centerVertical="true" - android:layout_margin="16dp" - android:src="@android:drawable/stat_notify_sdcard_usb" /> + android:layout_width="36dp" + android:layout_height="36dp" + android:layout_margin="8dp" + android:src="?attr/ic_sd_storage" /> <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_below="@+id/imageView1" - android:layout_centerHorizontal="true" android:layout_margin="8dp" android:text="@string/external_storage_error_msg" /> -</RelativeLayout>
\ No newline at end of file + <Button + android:id="@+id/btnChooseDataFolder" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_margin="8dp" + android:text="@string/choose_data_directory"/> + +</LinearLayout> |