Improved SAF missing reporting

pull/214/head
M66B 1 year ago
parent b8f57ea098
commit ac92c2a013

@ -1677,9 +1677,10 @@ This might be because your custom ROM does not include it or because it was acti
FairEmail does not request storage permissions, so this framework is required to select files and folders.
No app, except maybe file managers, targeting Android 4.4 KitKat or later should ask for storage permissions because it would allow access to *all* files.
Moreover, recent Android versions disallow access to all files for apps, except, under specific conditions, for file managers.
The storage access framework is provided by the package *com.android.documentsui*,
which is visible as *Files* app on some Android versions (notable OxygenOS).
which is visible as *Files* app on some Android versions (notably OxygenOS).
You can enable the storage access framework (again) with this adb command:

@ -394,7 +394,8 @@ public class ActivityEML extends ActivityBase {
create.putExtra(Intent.EXTRA_TITLE, apart.attachment.name);
Helper.openAdvanced(ActivityEML.this, create);
if (create.resolveActivity(getPackageManager()) == null) // system whitelisted
ToastEx.makeText(ActivityEML.this, R.string.title_no_saf, Toast.LENGTH_LONG).show();
Log.unexpectedError(getSupportFragmentManager(),
new IllegalArgumentException(getString(R.string.title_no_saf)), 25);
else
startActivityForResult(Helper.getChooser(ActivityEML.this, create), REQUEST_ATTACHMENT);
}

@ -755,7 +755,8 @@ public class ActivitySetup extends ActivityBase implements FragmentManager.OnBac
open.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
open.setType("*/*");
if (open.resolveActivity(getPackageManager()) == null) // system whitelisted
ToastEx.makeText(this, R.string.title_no_saf, Toast.LENGTH_LONG).show();
Log.unexpectedError(getSupportFragmentManager(),
new IllegalArgumentException(getString(R.string.title_no_saf)), 25);
else
startActivityForResult(Helper.getChooser(this, open), REQUEST_IMPORT_CERTIFICATE);
}

@ -1263,7 +1263,8 @@ public class AdapterFolder extends RecyclerView.Adapter<AdapterFolder.ViewHolder
Helper.openAdvanced(context, intent);
if (intent.resolveActivity(context.getPackageManager()) == null) { // // system/GET_CONTENT whitelisted
ToastEx.makeText(context, R.string.title_no_saf, Toast.LENGTH_LONG).show();
Log.unexpectedError(parentFragment.getParentFragmentManager(),
new IllegalArgumentException(context.getString(R.string.title_no_saf)), 25);
return;
}

@ -540,10 +540,10 @@ public class FragmentBase extends Fragment {
create.putExtra(Intent.EXTRA_TITLE, attachment.name);
Helper.openAdvanced(context, create);
PackageManager pm = context.getPackageManager();
if (create.resolveActivity(pm) == null) { // system whitelisted
Log.w("SAF missing");
ToastEx.makeText(context, R.string.title_no_saf, Toast.LENGTH_LONG).show();
} else
if (create.resolveActivity(pm) == null) // system whitelisted
Log.unexpectedError(getParentFragmentManager(),
new IllegalArgumentException(context.getString(R.string.title_no_saf)), 25);
else
startActivityForResult(Helper.getChooser(context, create), REQUEST_ATTACHMENT);
}
@ -556,10 +556,10 @@ public class FragmentBase extends Fragment {
Intent tree = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
Helper.openAdvanced(context, tree);
PackageManager pm = context.getPackageManager();
if (tree.resolveActivity(pm) == null) { // system whitelisted
Log.w("SAF missing");
ToastEx.makeText(context, R.string.title_no_saf, Toast.LENGTH_LONG).show();
} else
if (tree.resolveActivity(pm) == null) // system whitelisted
Log.unexpectedError(getParentFragmentManager(),
new IllegalArgumentException(context.getString(R.string.title_no_saf)), 25);
else
startActivityForResult(Helper.getChooser(context, tree), REQUEST_ATTACHMENTS);
}

@ -540,7 +540,8 @@ public class FragmentContacts extends FragmentBase {
open.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
open.setType("*/*");
if (open.resolveActivity(pm) == null) // system whitelisted
ToastEx.makeText(context, R.string.title_no_saf, Toast.LENGTH_LONG).show();
Log.unexpectedError(getParentFragmentManager(),
new IllegalArgumentException(context.getString(R.string.title_no_saf)), 25);
else
startActivityForResult(Helper.getChooser(context, open), REQUEST_IMPORT);
}

@ -1701,7 +1701,8 @@ public class FragmentOptionsBackup extends FragmentBase implements SharedPrefere
Intent intent = (export ? getIntentExport(context) : getIntentImport(context));
PackageManager pm = context.getPackageManager();
if (intent.resolveActivity(pm) == null) { // // system/GET_CONTENT whitelisted
ToastEx.makeText(context, R.string.title_no_saf, Toast.LENGTH_LONG).show();
Log.unexpectedError(getParentFragmentManager(),
new IllegalArgumentException(context.getString(R.string.title_no_saf)), 25);
return;
}

@ -409,7 +409,8 @@ public class FragmentOptionsEncryption extends FragmentBase
open.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
open.setType("*/*");
if (open.resolveActivity(pm) == null) // system whitelisted
ToastEx.makeText(context, R.string.title_no_saf, Toast.LENGTH_LONG).show();
Log.unexpectedError(getParentFragmentManager(),
new IllegalArgumentException(context.getString(R.string.title_no_saf)), 25);
else
startActivityForResult(Helper.getChooser(context, open), REQUEST_IMPORT_CERTIFICATE);
}

@ -87,6 +87,7 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
@ -1932,6 +1933,14 @@ public class Log {
}
static void unexpectedError(FragmentManager manager, Throwable ex, boolean report) {
unexpectedError(manager, ex, report, null);
}
static void unexpectedError(FragmentManager manager, Throwable ex, int faq) {
unexpectedError(manager, ex, false, faq);
}
static void unexpectedError(FragmentManager manager, Throwable ex, boolean report, Integer faq) {
Log.e(ex);
if (ex instanceof OutOfMemoryError)
@ -1940,6 +1949,7 @@ public class Log {
Bundle args = new Bundle();
args.putSerializable("ex", ex);
args.putBoolean("report", report);
args.putInt("faq", faq == null ? 0 : faq);
FragmentDialogUnexpected fragment = new FragmentDialogUnexpected();
fragment.setArguments(args);
@ -1950,17 +1960,28 @@ public class Log {
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
final Throwable ex = (Throwable) getArguments().getSerializable("ex");
boolean report = getArguments().getBoolean("report", true);
Bundle args = getArguments();
final Throwable ex = (Throwable) args.getSerializable("ex");
final boolean report = args.getBoolean("report", true);
final int faq = args.getInt("faq");
final Context context = getContext();
LayoutInflater inflater = LayoutInflater.from(context);
View dview = inflater.inflate(R.layout.dialog_unexpected, null);
TextView tvError = dview.findViewById(R.id.tvError);
Button btnHelp = dview.findViewById(R.id.btnHelp);
String message = Log.formatThrowable(ex, false);
tvError.setText(message);
btnHelp.setVisibility(faq > 0 ? View.VISIBLE : View.GONE);
btnHelp.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Helper.viewFAQ(v.getContext(), faq);
}
});
AlertDialog.Builder builder = new AlertDialog.Builder(context)
.setView(dview)
.setNegativeButton(android.R.string.cancel, null)

@ -17,10 +17,10 @@
android:layout_height="wrap_content"
android:drawableStart="@drawable/twotone_bug_report_24"
android:drawablePadding="6dp"
app:drawableTint="@color/red"
android:labelFor="@+id/etName"
android:text="@string/title_unexpected_error"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
app:drawableTint="@color/red"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
@ -29,10 +29,23 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:fontFamily="monospace"
android:text="Error"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:textIsSelectable="true"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvCaption" />
<Button
android:id="@+id/btnHelp"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:drawableEnd="@drawable/twotone_help_24"
android:drawablePadding="6dp"
android:text="@string/title_setup_help"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tvError" />
</androidx.constraintlayout.widget.ConstraintLayout>
</eu.faircode.email.ScrollViewEx>

@ -995,8 +995,8 @@ Visit https://aka.ms/smtp_auth_disabled for more information.</code></pre>
<p><a name="faq25"></a> <strong>(25) Why cant I select/open/save an image, attachment or a file?</strong></p>
<p>🌎 <a href="https://translate.google.com/translate?sl=en&amp;u=https%3A%2F%2Fm66b.github.io%2FFairEmail%2F%23faq25">Google Translate</a></p>
<p>When a menu item to select/open/save a file is disabled (dimmed) or when you get the message <em>Storage access framework not available</em>, the <a href="https://developer.android.com/guide/topics/providers/document-provider">storage access framework</a>, a standard Android component, is probably not present. This might be because your custom ROM does not include it or because it was actively removed (debloated).</p>
<p>FairEmail does not request storage permissions, so this framework is required to select files and folders. No app, except maybe file managers, targeting Android 4.4 KitKat or later should ask for storage permissions because it would allow access to <em>all</em> files.</p>
<p>The storage access framework is provided by the package <em>com.android.documentsui</em>, which is visible as <em>Files</em> app on some Android versions (notable OxygenOS).</p>
<p>FairEmail does not request storage permissions, so this framework is required to select files and folders. No app, except maybe file managers, targeting Android 4.4 KitKat or later should ask for storage permissions because it would allow access to <em>all</em> files. Moreover, recent Android versions disallow access to all files for apps, except, under specific conditions, for file managers.</p>
<p>The storage access framework is provided by the package <em>com.android.documentsui</em>, which is visible as <em>Files</em> app on some Android versions (notably OxygenOS).</p>
<p>You can enable the storage access framework (again) with this adb command:</p>
<pre><code>pm install -k --user 0 com.android.documentsui</code></pre>
<p>Alternatively, you might be able to enable the <em>Files</em> app again using the Android app settings.</p>

Loading…
Cancel
Save