diff --git a/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java b/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java index a7f5b938f..49b9024cd 100644 --- a/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java +++ b/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java @@ -1,6 +1,7 @@ package org.schabi.newpipe.download; import android.app.Activity; +import android.content.ActivityNotFoundException; import android.content.ComponentName; import android.content.Context; import android.content.DialogInterface; @@ -53,6 +54,7 @@ import org.schabi.newpipe.extractor.stream.StreamInfo; import org.schabi.newpipe.extractor.stream.SubtitlesStream; import org.schabi.newpipe.extractor.stream.VideoStream; import org.schabi.newpipe.settings.NewPipeSettings; +import org.schabi.newpipe.streams.io.NoFileManagerHelper; import org.schabi.newpipe.streams.io.StoredDirectoryHelper; import org.schabi.newpipe.streams.io.StoredFileHelper; import org.schabi.newpipe.util.FilePickerActivityHelper; @@ -687,7 +689,12 @@ public class DownloadDialog extends DialogFragment } private void launchDirectoryPicker(final ActivityResultLauncher launcher) { - launcher.launch(StoredDirectoryHelper.getPicker(context)); + try { + launcher.launch(StoredDirectoryHelper.getPicker(context)); + } catch (final ActivityNotFoundException aex) { + Log.w(TAG, "Unable to launch directory-picker", aex); + NoFileManagerHelper.showActivityNotFoundAlert(getContext()); + } } private void prepareSelectedDownload() { @@ -766,8 +773,13 @@ public class DownloadDialog extends DialogFragment initialPath = Uri.parse(initialSavePath.getAbsolutePath()); } - requestDownloadSaveAsLauncher.launch(StoredFileHelper.getNewPicker(context, - filenameTmp, mimeTmp, initialPath)); + try { + requestDownloadSaveAsLauncher.launch(StoredFileHelper.getNewPicker(context, + filenameTmp, mimeTmp, initialPath)); + } catch (final ActivityNotFoundException aex) { + Log.w(TAG, "Unable to launch file-picker", aex); + NoFileManagerHelper.showActivityNotFoundAlert(getContext()); + } return; } diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt index 57e1effbe..8b170279d 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt @@ -1,6 +1,7 @@ package org.schabi.newpipe.local.subscription import android.app.Activity +import android.content.ActivityNotFoundException import android.content.BroadcastReceiver import android.content.Context import android.content.DialogInterface @@ -8,6 +9,7 @@ import android.content.Intent import android.content.IntentFilter import android.os.Bundle import android.os.Parcelable +import android.util.Log import android.view.LayoutInflater import android.view.Menu import android.view.MenuInflater @@ -55,6 +57,7 @@ import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.KEY_MODE import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.KEY_VALUE import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.PREVIOUS_EXPORT_MODE +import org.schabi.newpipe.streams.io.NoFileManagerHelper import org.schabi.newpipe.streams.io.StoredFileHelper import org.schabi.newpipe.util.NavigationHelper import org.schabi.newpipe.util.OnClickGesture @@ -179,16 +182,26 @@ class SubscriptionFragment : BaseStateFragment() { } private fun onImportPreviousSelected() { - requestImportLauncher.launch(StoredFileHelper.getPicker(activity, JSON_MIME_TYPE)) + try { + requestImportLauncher.launch(StoredFileHelper.getPicker(activity, JSON_MIME_TYPE)) + } catch (aex: ActivityNotFoundException) { + Log.w(TAG, "Unable to launch file-picker", aex) + NoFileManagerHelper.showActivityNotFoundAlert(context) + } } private fun onExportSelected() { val date = SimpleDateFormat("yyyyMMddHHmm", Locale.ENGLISH).format(Date()) val exportName = "newpipe_subscriptions_$date.json" - requestExportLauncher.launch( - StoredFileHelper.getNewPicker(activity, exportName, JSON_MIME_TYPE, null) - ) + try { + requestExportLauncher.launch( + StoredFileHelper.getNewPicker(activity, exportName, JSON_MIME_TYPE, null) + ) + } catch (aex: ActivityNotFoundException) { + Log.w(TAG, "Unable to launch file-picker", aex) + NoFileManagerHelper.showActivityNotFoundAlert(context) + } } private fun openReorderDialog() { diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionsImportFragment.java b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionsImportFragment.java index 675799586..10816922b 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionsImportFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionsImportFragment.java @@ -1,10 +1,12 @@ package org.schabi.newpipe.local.subscription; import android.app.Activity; +import android.content.ActivityNotFoundException; import android.content.Intent; import android.os.Bundle; import android.text.TextUtils; import android.text.util.Linkify; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -30,6 +32,7 @@ import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.subscription.SubscriptionExtractor; import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService; +import org.schabi.newpipe.streams.io.NoFileManagerHelper; import org.schabi.newpipe.streams.io.StoredFileHelper; import org.schabi.newpipe.util.Constants; import org.schabi.newpipe.util.ServiceHelper; @@ -175,8 +178,14 @@ public class SubscriptionsImportFragment extends BaseFragment { } public void onImportFile() { - // leave */* mime type to support all services with different mime types and file extensions - requestImportFileLauncher.launch(StoredFileHelper.getPicker(activity, "*/*")); + try { + // leave */* mime type to support all services + // with different mime types and file extensions + requestImportFileLauncher.launch(StoredFileHelper.getPicker(activity, "*/*")); + } catch (final ActivityNotFoundException aex) { + Log.w(TAG, "Unable to launch file-picker", aex); + NoFileManagerHelper.showActivityNotFoundAlert(getContext()); + } } private void requestImportFileResult(final ActivityResult result) { diff --git a/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java index 6e7e75932..3e72cf9a6 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java @@ -1,6 +1,7 @@ package org.schabi.newpipe.settings; import android.app.Activity; +import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; @@ -25,6 +26,7 @@ import org.schabi.newpipe.error.ReCaptchaActivity; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.localization.ContentCountry; import org.schabi.newpipe.extractor.localization.Localization; +import org.schabi.newpipe.streams.io.NoFileManagerHelper; import org.schabi.newpipe.streams.io.StoredFileHelper; import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.PicassoHelper; @@ -73,19 +75,29 @@ public class ContentSettingsFragment extends BasePreferenceFragment { final Preference importDataPreference = requirePreference(R.string.import_data); importDataPreference.setOnPreferenceClickListener((Preference p) -> { - requestImportPathLauncher.launch( - StoredFileHelper.getPicker(requireContext(), - ZIP_MIME_TYPE, getImportExportDataUri())); + try { + requestImportPathLauncher.launch( + StoredFileHelper.getPicker(requireContext(), + ZIP_MIME_TYPE, getImportExportDataUri())); + } catch (final ActivityNotFoundException aex) { + Log.w(TAG, "Unable to launch file-picker", aex); + NoFileManagerHelper.showActivityNotFoundAlert(getContext()); + } return true; }); final Preference exportDataPreference = requirePreference(R.string.export_data); exportDataPreference.setOnPreferenceClickListener((final Preference p) -> { - requestExportPathLauncher.launch( - StoredFileHelper.getNewPicker(requireContext(), - "NewPipeData-" + exportDateFormat.format(new Date()) + ".zip", - ZIP_MIME_TYPE, getImportExportDataUri())); + try { + requestExportPathLauncher.launch( + StoredFileHelper.getNewPicker(requireContext(), + "NewPipeData-" + exportDateFormat.format(new Date()) + ".zip", + ZIP_MIME_TYPE, getImportExportDataUri())); + } catch (final ActivityNotFoundException aex) { + Log.w(TAG, "Unable to launch file-picker", aex); + NoFileManagerHelper.showActivityNotFoundAlert(getContext()); + } return true; }); diff --git a/app/src/main/java/org/schabi/newpipe/settings/DownloadSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/DownloadSettingsFragment.java index dfd77f049..b083cc71d 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/DownloadSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/DownloadSettingsFragment.java @@ -1,6 +1,7 @@ package org.schabi.newpipe.settings; import android.app.Activity; +import android.content.ActivityNotFoundException; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; @@ -21,6 +22,7 @@ import androidx.preference.SwitchPreferenceCompat; import com.nononsenseapps.filepicker.Utils; import org.schabi.newpipe.R; +import org.schabi.newpipe.streams.io.NoFileManagerHelper; import org.schabi.newpipe.streams.io.StoredDirectoryHelper; import org.schabi.newpipe.util.FilePickerActivityHelper; @@ -214,7 +216,12 @@ public class DownloadSettingsFragment extends BasePreferenceFragment { } private void launchDirectoryPicker(final ActivityResultLauncher launcher) { - launcher.launch(StoredDirectoryHelper.getPicker(ctx)); + try { + launcher.launch(StoredDirectoryHelper.getPicker(ctx)); + } catch (final ActivityNotFoundException aex) { + Log.w(TAG, "Unable to launch directory-picker", aex); + NoFileManagerHelper.showActivityNotFoundAlert(getContext()); + } } private void requestDownloadVideoPathResult(final ActivityResult result) { diff --git a/app/src/main/java/org/schabi/newpipe/streams/io/NoFileManagerHelper.java b/app/src/main/java/org/schabi/newpipe/streams/io/NoFileManagerHelper.java new file mode 100644 index 000000000..cd9119c08 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/streams/io/NoFileManagerHelper.java @@ -0,0 +1,31 @@ +package org.schabi.newpipe.streams.io; + +import android.content.Context; + +import androidx.appcompat.app.AlertDialog; + +import org.schabi.newpipe.R; + +/** + * Helper for when no file-manager/activity was found. + */ +public final class NoFileManagerHelper { + private NoFileManagerHelper() { + // No impl + } + + /** + * Shows an alert dialog when no file-manager is found. + * @param context Context + */ + public static void showActivityNotFoundAlert(final Context context) { + new AlertDialog.Builder(context) + .setTitle(R.string.no_app_to_open_intent) + .setMessage( + context.getString( + R.string.no_appropriate_file_manager_message, + context.getString(R.string.downloads_storage_use_saf_title))) + .setPositiveButton(R.string.ok, null) + .show(); + } +} diff --git a/app/src/main/java/us/shandian/giga/ui/fragment/MissionsFragment.java b/app/src/main/java/us/shandian/giga/ui/fragment/MissionsFragment.java index 2cca3239b..5aa3d2a53 100644 --- a/app/src/main/java/us/shandian/giga/ui/fragment/MissionsFragment.java +++ b/app/src/main/java/us/shandian/giga/ui/fragment/MissionsFragment.java @@ -1,6 +1,7 @@ package us.shandian.giga.ui.fragment; import android.app.Activity; +import android.content.ActivityNotFoundException; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -10,6 +11,7 @@ import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.os.IBinder; +import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; @@ -32,6 +34,7 @@ import com.nononsenseapps.filepicker.Utils; import org.schabi.newpipe.R; import org.schabi.newpipe.settings.NewPipeSettings; +import org.schabi.newpipe.streams.io.NoFileManagerHelper; import org.schabi.newpipe.streams.io.StoredFileHelper; import org.schabi.newpipe.util.FilePickerActivityHelper; @@ -46,6 +49,7 @@ import us.shandian.giga.ui.adapter.MissionAdapter; public class MissionsFragment extends Fragment { + private static final String TAG = "MissionsFragment"; private static final int SPAN_SIZE = 2; private SharedPreferences mPrefs; @@ -257,9 +261,14 @@ public class MissionsFragment extends Fragment { initialPath = Uri.parse(initialSavePath.getAbsolutePath()); } - requestDownloadSaveAsLauncher.launch( - StoredFileHelper.getNewPicker(mContext, mission.storage.getName(), - mission.storage.getType(), initialPath)); + try { + requestDownloadSaveAsLauncher.launch( + StoredFileHelper.getNewPicker(mContext, mission.storage.getName(), + mission.storage.getType(), initialPath)); + } catch (final ActivityNotFoundException aex) { + Log.w(TAG, "Unable to launch file-picker", aex); + NoFileManagerHelper.showActivityNotFoundAlert(getContext()); + } } @Override diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7c8fd98ab..112f1a94c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -671,6 +671,7 @@ Recent Chapters No app on your device can open this + No appropriate file-manager was found for this action.\nPlease install a file-manager or try to enable/disable \'%s\' in the download-settings. This content is not available in your country. This is a SoundCloud Go+ track, at least in your country, so it cannot be streamed or downloaded by NewPipe. This content is private, so it cannot be streamed or downloaded by NewPipe.