diff options
author | Stefan Niedermann <info@niedermann.it> | 2020-07-02 10:17:18 +0300 |
---|---|---|
committer | Stefan Niedermann <info@niedermann.it> | 2020-07-02 10:17:18 +0300 |
commit | cd1998d41f454c232f849c729570f0990f7fb754 (patch) | |
tree | 552fb2857ac40c81847d83b463f91aa2b8efcd54 /app/src/main | |
parent | 425457b1cb482deb43f4ad79ca78c99d1e7a2e78 (diff) |
Provide exception hints also on total crash in ExceptionActivity
Diffstat (limited to 'app/src/main')
5 files changed, 136 insertions, 100 deletions
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/SyncManager.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/SyncManager.java index fcb42f0ba..4e5941002 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/SyncManager.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/SyncManager.java @@ -12,6 +12,7 @@ import androidx.lifecycle.LiveData; import androidx.lifecycle.MediatorLiveData; import androidx.lifecycle.MutableLiveData; +import com.nextcloud.android.sso.exceptions.NextcloudApiNotRespondingException; import com.nextcloud.android.sso.exceptions.NextcloudHttpRequestFailedException; import java.io.File; @@ -169,6 +170,7 @@ public class SyncManager { responseCallback.getAccount().getId() == null) { throw new IllegalArgumentException("please provide an account ID."); } + responseCallback.onError(new NextcloudApiNotRespondingException()); doAsync(() -> refreshCapabilities(new IResponseCallback<Capabilities>(responseCallback.getAccount()) { @Override public void onResponse(Capabilities response) { diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/exception/ExceptionActivity.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/exception/ExceptionActivity.java index 3ba3eb59f..9eef878c3 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/exception/ExceptionActivity.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/exception/ExceptionActivity.java @@ -11,6 +11,7 @@ import androidx.appcompat.app.AppCompatActivity; import it.niedermann.nextcloud.deck.DeckLog; import it.niedermann.nextcloud.deck.R; import it.niedermann.nextcloud.deck.databinding.ActivityExceptionBinding; +import it.niedermann.nextcloud.deck.ui.exception.tips.TipsAdapter; import it.niedermann.nextcloud.deck.util.ExceptionUtil; import static it.niedermann.nextcloud.deck.util.ClipboardUtil.copyToClipboard; @@ -41,6 +42,11 @@ public class ExceptionActivity extends AppCompatActivity { binding.stacktrace.setText(debugInfo); + final TipsAdapter adapter = new TipsAdapter(this::startActivity); + binding.tips.setAdapter(adapter); + binding.tips.setNestedScrollingEnabled(false); + adapter.setThrowable(this, null, throwable); + binding.copy.setOnClickListener((v) -> copyToClipboard(this, getString(R.string.simple_exception), "```\n" + debugInfo + "\n```")); binding.close.setOnClickListener((v) -> finish()); } diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/exception/ExceptionDialogFragment.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/exception/ExceptionDialogFragment.java index 666deb0db..6c0d0ba79 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/exception/ExceptionDialogFragment.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/exception/ExceptionDialogFragment.java @@ -2,12 +2,7 @@ package it.niedermann.nextcloud.deck.ui.exception; import android.app.Dialog; import android.content.Context; -import android.content.Intent; -import android.net.Uri; -import android.os.Build.VERSION; -import android.os.Build.VERSION_CODES; import android.os.Bundle; -import android.provider.Settings; import android.view.View; import androidx.annotation.NonNull; @@ -16,27 +11,13 @@ import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatDialogFragment; import androidx.fragment.app.DialogFragment; -import com.nextcloud.android.sso.exceptions.NextcloudApiNotRespondingException; -import com.nextcloud.android.sso.exceptions.NextcloudFilesAppNotSupportedException; -import com.nextcloud.android.sso.exceptions.NextcloudHttpRequestFailedException; -import com.nextcloud.android.sso.exceptions.TokenMismatchException; - -import org.json.JSONException; - -import java.net.ConnectException; -import java.net.SocketTimeoutException; - -import it.niedermann.nextcloud.deck.BuildConfig; import it.niedermann.nextcloud.deck.DeckLog; import it.niedermann.nextcloud.deck.R; import it.niedermann.nextcloud.deck.databinding.DialogExceptionBinding; -import it.niedermann.nextcloud.deck.exceptions.DeckException; -import it.niedermann.nextcloud.deck.exceptions.UploadAttachmentFailedException; import it.niedermann.nextcloud.deck.model.Account; import it.niedermann.nextcloud.deck.ui.exception.tips.TipsAdapter; import it.niedermann.nextcloud.deck.util.ExceptionUtil; -import static android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS; import static it.niedermann.nextcloud.deck.util.ClipboardUtil.copyToClipboard; public class ExceptionDialogFragment extends AppCompatDialogFragment { @@ -78,74 +59,7 @@ public class ExceptionDialogFragment extends AppCompatDialogFragment { DeckLog.logError(throwable); - if (throwable instanceof TokenMismatchException) { - adapter.add(R.string.error_dialog_tip_token_mismatch_retry); - adapter.add(R.string.error_dialog_tip_token_mismatch_clear_storage); - Intent intent = new Intent(ACTION_APPLICATION_DETAILS_SETTINGS) - .setData(Uri.parse("package:" + BuildConfig.APPLICATION_ID)) - .putExtra(INTENT_EXTRA_BUTTON_TEXT, R.string.error_action_open_deck_info); - adapter.add(R.string.error_dialog_tip_clear_storage, intent); - } else if (throwable instanceof NextcloudFilesAppNotSupportedException) { - adapter.add(R.string.error_dialog_tip_files_outdated); - } else if (throwable instanceof NextcloudApiNotRespondingException) { - if (VERSION.SDK_INT >= VERSION_CODES.M) { - adapter.add(R.string.error_dialog_tip_disable_battery_optimizations, new Intent().setAction(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS).putExtra(INTENT_EXTRA_BUTTON_TEXT, R.string.error_action_open_battery_settings)); - } else { - adapter.add(R.string.error_dialog_tip_disable_battery_optimizations); - } - adapter.add(R.string.error_dialog_tip_files_force_stop); - adapter.add(R.string.error_dialog_tip_files_delete_storage); - } else if (throwable instanceof SocketTimeoutException || throwable instanceof ConnectException) { - adapter.add(R.string.error_dialog_timeout_instance); - adapter.add(R.string.error_dialog_timeout_toggle, new Intent(Settings.ACTION_WIFI_SETTINGS).putExtra(INTENT_EXTRA_BUTTON_TEXT, R.string.error_action_open_network)); - } else if (throwable instanceof JSONException || throwable instanceof NullPointerException) { - adapter.add(R.string.error_dialog_check_server); - } else if (throwable instanceof NextcloudHttpRequestFailedException) { - int statusCode = ((NextcloudHttpRequestFailedException) throwable).getStatusCode(); - switch (statusCode) { - case 302: - adapter.add(R.string.error_dialog_redirect); - break; - case 500: - if (account != null) { - adapter.add(R.string.error_dialog_check_server_logs, new Intent(Intent.ACTION_VIEW) - .putExtra(INTENT_EXTRA_BUTTON_TEXT, R.string.error_action_server_logs) - .setData(Uri.parse(account.getUrl() + getString(R.string.url_fragment_server_logs)))); - } else { - adapter.add(R.string.error_dialog_check_server_logs); - } - break; - case 503: - adapter.add(R.string.error_dialog_check_maintenance); - break; - case 507: - adapter.add(R.string.error_dialog_insufficient_storage); - break; - } - } else if (throwable instanceof UploadAttachmentFailedException) { - adapter.add(R.string.error_dialog_attachment_upload_failed); - } else if (throwable instanceof DeckException) { - switch (((DeckException) throwable).getHint()) { - case CAPABILITIES_VERSION_NOT_PARSABLE: - if (account != null) { - adapter.add(R.string.error_dialog_version_not_parsable, new Intent(Intent.ACTION_VIEW) - .putExtra(INTENT_EXTRA_BUTTON_TEXT, R.string.error_action_install) - .setData(Uri.parse(account.getUrl() + getString(R.string.url_fragment_install_deck)))); - } else { - adapter.add(R.string.error_dialog_version_not_parsable); - } - break; - case CAPABILITIES_NOT_PARSABLE: - default: - if (account != null) { - adapter.add(R.string.error_dialog_capabilities_not_parsable, new Intent(Intent.ACTION_VIEW) - .putExtra(INTENT_EXTRA_BUTTON_TEXT, R.string.error_action_server_logs) - .setData(Uri.parse(account.getUrl() + getString(R.string.url_fragment_server_logs)))); - } else { - adapter.add(R.string.error_dialog_capabilities_not_parsable); - } - } - } + adapter.setThrowable(requireContext(), account, throwable); return new AlertDialog.Builder(requireActivity()) .setView(binding.getRoot()) diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/exception/tips/TipsAdapter.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/exception/tips/TipsAdapter.java index 8ca1a4e09..fa4113b1e 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/exception/tips/TipsAdapter.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/exception/tips/TipsAdapter.java @@ -1,6 +1,11 @@ package it.niedermann.nextcloud.deck.ui.exception.tips; +import android.content.Context; import android.content.Intent; +import android.net.Uri; +import android.os.Build.VERSION; +import android.os.Build.VERSION_CODES; +import android.provider.Settings; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -11,10 +16,26 @@ import androidx.annotation.StringRes; import androidx.core.util.Consumer; import androidx.recyclerview.widget.RecyclerView; +import com.nextcloud.android.sso.exceptions.NextcloudApiNotRespondingException; +import com.nextcloud.android.sso.exceptions.NextcloudFilesAppNotSupportedException; +import com.nextcloud.android.sso.exceptions.NextcloudHttpRequestFailedException; +import com.nextcloud.android.sso.exceptions.TokenMismatchException; + +import org.json.JSONException; + +import java.net.ConnectException; +import java.net.SocketTimeoutException; import java.util.LinkedList; import java.util.List; +import it.niedermann.nextcloud.deck.BuildConfig; import it.niedermann.nextcloud.deck.R; +import it.niedermann.nextcloud.deck.exceptions.DeckException; +import it.niedermann.nextcloud.deck.exceptions.UploadAttachmentFailedException; +import it.niedermann.nextcloud.deck.model.Account; + +import static android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS; +import static it.niedermann.nextcloud.deck.ui.exception.ExceptionDialogFragment.INTENT_EXTRA_BUTTON_TEXT; public class TipsAdapter extends RecyclerView.Adapter<TipsViewHolder> { @@ -44,6 +65,77 @@ public class TipsAdapter extends RecyclerView.Adapter<TipsViewHolder> { return tips.size(); } + public void setThrowable(@NonNull Context context, @Nullable Account account, @NonNull Throwable throwable) { + if (throwable instanceof TokenMismatchException) { + add(R.string.error_dialog_tip_token_mismatch_retry); + add(R.string.error_dialog_tip_token_mismatch_clear_storage); + Intent intent = new Intent(ACTION_APPLICATION_DETAILS_SETTINGS) + .setData(Uri.parse("package:" + BuildConfig.APPLICATION_ID)) + .putExtra(INTENT_EXTRA_BUTTON_TEXT, R.string.error_action_open_deck_info); + add(R.string.error_dialog_tip_clear_storage, intent); + } else if (throwable instanceof NextcloudFilesAppNotSupportedException) { + add(R.string.error_dialog_tip_files_outdated); + } else if (throwable instanceof NextcloudApiNotRespondingException) { + if (VERSION.SDK_INT >= VERSION_CODES.M) { + add(R.string.error_dialog_tip_disable_battery_optimizations, new Intent().setAction(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS).putExtra(INTENT_EXTRA_BUTTON_TEXT, R.string.error_action_open_battery_settings)); + } else { + add(R.string.error_dialog_tip_disable_battery_optimizations); + } + add(R.string.error_dialog_tip_files_force_stop); + add(R.string.error_dialog_tip_files_delete_storage); + } else if (throwable instanceof SocketTimeoutException || throwable instanceof ConnectException) { + add(R.string.error_dialog_timeout_instance); + add(R.string.error_dialog_timeout_toggle, new Intent(Settings.ACTION_WIFI_SETTINGS).putExtra(INTENT_EXTRA_BUTTON_TEXT, R.string.error_action_open_network)); + } else if (throwable instanceof JSONException || throwable instanceof NullPointerException) { + add(R.string.error_dialog_check_server); + } else if (throwable instanceof NextcloudHttpRequestFailedException) { + int statusCode = ((NextcloudHttpRequestFailedException) throwable).getStatusCode(); + switch (statusCode) { + case 302: + add(R.string.error_dialog_redirect); + break; + case 500: + if (account != null) { + add(R.string.error_dialog_check_server_logs, new Intent(Intent.ACTION_VIEW) + .putExtra(INTENT_EXTRA_BUTTON_TEXT, R.string.error_action_server_logs) + .setData(Uri.parse(account.getUrl() + context.getString(R.string.url_fragment_server_logs)))); + } else { + add(R.string.error_dialog_check_server_logs); + } + break; + case 503: + add(R.string.error_dialog_check_maintenance); + break; + case 507: + add(R.string.error_dialog_insufficient_storage); + break; + } + } else if (throwable instanceof UploadAttachmentFailedException) { + add(R.string.error_dialog_attachment_upload_failed); + } else if (throwable instanceof DeckException) { + switch (((DeckException) throwable).getHint()) { + case CAPABILITIES_VERSION_NOT_PARSABLE: + if (account != null) { + add(R.string.error_dialog_version_not_parsable, new Intent(Intent.ACTION_VIEW) + .putExtra(INTENT_EXTRA_BUTTON_TEXT, R.string.error_action_install) + .setData(Uri.parse(account.getUrl() + context.getString(R.string.url_fragment_install_deck)))); + } else { + add(R.string.error_dialog_version_not_parsable); + } + break; + case CAPABILITIES_NOT_PARSABLE: + default: + if (account != null) { + add(R.string.error_dialog_capabilities_not_parsable, new Intent(Intent.ACTION_VIEW) + .putExtra(INTENT_EXTRA_BUTTON_TEXT, R.string.error_action_server_logs) + .setData(Uri.parse(account.getUrl() + context.getString(R.string.url_fragment_server_logs)))); + } else { + add(R.string.error_dialog_capabilities_not_parsable); + } + } + } + } + public void add(@StringRes int text) { add(text, null); } diff --git a/app/src/main/res/layout/activity_exception.xml b/app/src/main/res/layout/activity_exception.xml index 9bcaa5bc3..5e9519476 100644 --- a/app/src/main/res/layout/activity_exception.xml +++ b/app/src/main/res/layout/activity_exception.xml @@ -35,23 +35,45 @@ </LinearLayout> - <HorizontalScrollView + <ScrollView android:layout_width="match_parent" android:layout_height="0dp" - android:layout_marginStart="@dimen/spacer_2x" - android:layout_marginEnd="@dimen/spacer_2x" - android:layout_weight="1" - android:background="@color/bg_highlighted"> + android:layout_weight="1"> - <TextView - android:id="@+id/stacktrace" - android:layout_width="wrap_content" + <LinearLayout + android:layout_width="match_parent" android:layout_height="wrap_content" - android:padding="@dimen/spacer_1x" - android:textIsSelectable="true" - android:typeface="monospace" - tools:text="@string/android_get_accounts_permission_not_granted_exception_message" /> - </HorizontalScrollView> + android:orientation="vertical"> + + <androidx.recyclerview.widget.RecyclerView + android:id="@+id/tips" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:padding="@dimen/spacer_2x" + app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" + tools:itemCount="2" + tools:listitem="@layout/item_tip" /> + + <HorizontalScrollView + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_marginStart="@dimen/spacer_2x" + android:layout_marginEnd="@dimen/spacer_2x" + android:layout_weight="1" + android:background="@color/bg_highlighted"> + + <TextView + android:id="@+id/stacktrace" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:padding="@dimen/spacer_1x" + android:textIsSelectable="true" + android:typeface="monospace" + tools:text="@string/android_get_accounts_permission_not_granted_exception_message" /> + </HorizontalScrollView> + </LinearLayout> + </ScrollView> <LinearLayout android:layout_width="match_parent" |