Move crash report UI to fragment

Show error report when bootstrap installation fails
This commit is contained in:
Akash Yadav
2022-01-10 17:48:25 +05:30
parent adc24144e4
commit ac26609441
8 changed files with 301 additions and 148 deletions
+2
View File
@@ -13,9 +13,11 @@
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/layout/activity_designer.xml" value="0.264" />
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/layout/activity_download.xml" value="0.1188034188034188" />
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/layout/activity_editor.xml" value="0.264" />
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/layout/activity_terminal.xml" value="0.21851851851851853" />
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/layout/fragment_editor.xml" value="0.20512820512820512" />
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/layout/fragment_non_editable_editor.xml" value="0.20512820512820512" />
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/layout/layout_about_items.xml" value="0.20512820512820512" />
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/layout/layout_crash_report.xml" value="0.25" />
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/layout/layout_diagnostic_info.xml" value="0.20512820512820512" />
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/layout/layout_editor_bottom_sheet.xml" value="0.20512820512820512" />
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/layout/layout_symbol_item.xml" value="0.20512820512820512" />
@@ -33,6 +33,7 @@ import com.blankj.utilcode.util.ClipboardUtils;
import com.itsaky.androidide.app.BaseApplication;
import com.itsaky.androidide.app.StudioActivity;
import com.itsaky.androidide.databinding.ActivityCrashHandlerBinding;
import com.itsaky.androidide.fragments.CrashReportFragment;
public class CrashHandlerActivity extends StudioActivity {
@@ -50,43 +51,19 @@ public class CrashHandlerActivity extends StudioActivity {
@Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate (savedInstanceState);
binding.closeButton.setOnClickListener (v -> finishAffinity ());
final var extra = getIntent ().getExtras ();
if (extra == null) {
binding.closeButton.performClick ();
finishAffinity ();
return;
}
final var report = buildReportText (extra.getString (TRACE_KEY, "Unable to get logs."));
binding.logText.setText (report);
binding.reportButton.setOnClickListener (v -> reportTrace (report));
}
private void reportTrace (String report) {
ClipboardUtils.copyText ("AndroidIDE CrashLog", report);
final var url = BaseApplication.GITHUB_URL.concat ("/issues");
final var intent = new Intent ();
intent.setAction(Intent.ACTION_VIEW);
intent.setData (Uri.parse (url));
intent.addFlags (Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity (intent);
}
@NonNull
private String buildReportText (String trace) {
return "AndroidIDE crash report\n" +
"Manufacturer: " +
getManufacturer () +
"\n" +
"Device: " +
getModel () +
"\n" +
"App version: " +
getAppVersionName () +
" (" +
getAppVersionCode () +
")\n\n Stacktrace: \n" +
trace;
final var report = extra.getString (TRACE_KEY, "Unable to get logs.");
final var fragment = CrashReportFragment.newInstance (report);
getSupportFragmentManager ().beginTransaction ()
.replace (binding.getRoot ().getId (), fragment, "crash_report_fragment")
.addToBackStack (null)
.commit ();
}
}
@@ -21,17 +21,22 @@ package com.itsaky.androidide;
import static com.itsaky.androidide.utils.Environment.*;
import android.graphics.Typeface;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
import com.blankj.utilcode.util.ClipboardUtils;
import com.blankj.utilcode.util.KeyboardUtils;
import com.blankj.utilcode.util.SizeUtils;
import com.blankj.utilcode.util.ThrowableUtils;
import com.itsaky.androidide.app.StudioActivity;
import com.itsaky.androidide.databinding.ActivityTerminalBinding;
import com.itsaky.androidide.fragments.CrashReportFragment;
import com.itsaky.androidide.fragments.sheets.ProgressSheet;
import com.itsaky.androidide.managers.PreferenceManager;
import com.itsaky.androidide.models.ConstantsBridge;
@@ -57,8 +62,10 @@ import java.util.Map;
import org.json.JSONException;
import android.os.Bundle;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
public class TerminalActivity extends StudioActivity {
@@ -113,13 +120,7 @@ public class TerminalActivity extends StudioActivity {
if (future.isCompletedExceptionally () || throwable != null) {
LOG.error ("Future has been completed exceptionally.");
final var builder = DialogUtils.newMaterialDialogBuilder (TerminalActivity.this);
builder.setTitle (getString (R.string.title_installation_failed));
builder.setMessage (getString (R.string.msg_installation_error, throwable.getMessage ()));
builder.setPositiveButton (android.R.string.ok, null);
builder.setCancelable (false);
builder.show ();
showInstallationError (throwable);
return;
}
@@ -129,6 +130,22 @@ public class TerminalActivity extends StudioActivity {
}
}
private void showInstallationError (Throwable throwable) {
binding.virtualKeyTable.setVisibility (View.GONE);
final var frag = CrashReportFragment.newInstance (
getString (R.string.title_installation_failed),
getString (R.string.msg_bootstrap_installation_error),
ThrowableUtils.getFullStackTrace (throwable))
.setCloseAppOnClick (false);
getSupportFragmentManager ().beginTransaction ()
.replace (binding.root.getId (), frag, "bootstrap_install_error_fragment")
.addToBackStack (null)
.commit ();
}
private void setupTerminalView () {
terminal = new TerminalView (this, null);
terminal.setTerminalViewClient (client);
@@ -0,0 +1,149 @@
/*
* This file is part of AndroidIDE.
*
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
*/
package com.itsaky.androidide.fragments;
import static com.blankj.utilcode.util.AppUtils.getAppVersionCode;
import static com.blankj.utilcode.util.AppUtils.getAppVersionName;
import static com.blankj.utilcode.util.DeviceUtils.getManufacturer;
import static com.blankj.utilcode.util.DeviceUtils.getModel;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.blankj.utilcode.util.ClipboardUtils;
import com.itsaky.androidide.R;
import com.itsaky.androidide.app.BaseApplication;
import com.itsaky.androidide.databinding.LayoutCrashReportBinding;
public class CrashReportFragment extends Fragment {
private LayoutCrashReportBinding binding;
private boolean closeAppOnClick = true;
public static final String KEY_TITLE = "crash_title";
public static final String KEY_MESSAGE = "crash_message";
public static final String KEY_TRACE = "crash_trace";
@NonNull
public static CrashReportFragment newInstance (@NonNull final String trace) {
return CrashReportFragment.newInstance (null, null, trace);
}
@NonNull
public static CrashReportFragment newInstance (@Nullable final String title, @Nullable final String message, @NonNull final String trace) {
final var frag = new CrashReportFragment ();
final var args = new Bundle ();
args.putString (KEY_TRACE, trace);
if (title != null) {
args.putString (KEY_TITLE, title);
}
if (message != null) {
args.putString (KEY_MESSAGE, message);
}
frag.setArguments (args);
return frag;
}
public CrashReportFragment setCloseAppOnClick (boolean closeAppOnClick) {
this.closeAppOnClick = closeAppOnClick;
return this;
}
@Nullable
@Override
public View onCreateView (@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return (binding = LayoutCrashReportBinding.inflate (inflater, container, false)).getRoot ();
}
@Override
public void onViewCreated (@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated (view, savedInstanceState);
final var args = requireArguments ();
var title = getString (R.string.msg_ide_crashed);
var message = getString (R.string.msg_report_crash);
var trace = "";
if (args.containsKey (KEY_TITLE)) {
title = args.getString (KEY_TITLE);
}
if (args.containsKey (KEY_MESSAGE)) {
message = args.getString (KEY_MESSAGE);
}
if (args.containsKey (KEY_TRACE)) {
trace = args.getString (KEY_TRACE);
trace = buildReportText (trace);
} else {
trace = "No stack strace was provided for the report";
}
binding.crashTitle.setText (title);
binding.crashSubtitle.setText (message);
binding.logText.setText (trace);
final var report = trace;
binding.closeButton.setOnClickListener (v -> {
if (closeAppOnClick) {
requireActivity ().finishAffinity ();
} else {
requireActivity ().finish ();
}
});
binding.reportButton.setOnClickListener (v -> reportTrace (report));
}
private void reportTrace (String report) {
ClipboardUtils.copyText ("AndroidIDE CrashLog", report);
final var url = BaseApplication.GITHUB_URL.concat ("/issues");
final var intent = new Intent ();
intent.setAction(Intent.ACTION_VIEW);
intent.setData (Uri.parse (url));
intent.addFlags (Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity (intent);
}
@NonNull
private String buildReportText (String trace) {
return "AndroidIDE crash report\n" +
"Manufacturer: " +
getManufacturer () +
"\n" +
"Device: " +
getModel () +
"\n" +
"App version: " +
getAppVersionName () +
" (" +
getAppVersionCode () +
")\n\n Stacktrace: \n" +
trace;
}
}
@@ -15,117 +15,12 @@
~ You should have received a copy of the GNU General Public License
~ along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
-->
<!--
~ This file is part of AndroidIDE.
~
~ AndroidIDE is free software: you can redistribute it and/or modify
~ it under the terms of the GNU General Public License as published by
~ the Free Software Foundation, either version 3 of the License, or
~ (at your option) any later version.
~
~ AndroidIDE is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
~ GNU General Public License for more details.
~
~ You should have received a copy of the GNU General Public License
~ along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
-->
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".CrashHandlerActivity">
<ImageButton
android:id="@+id/close_button"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_margin="16dp"
android:background="@drawable/bg_ripple"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_close" />
<TextView
android:id="@+id/crash_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:text="@string/msg_ide_crashed"
android:textColor="@color/primaryTextColor"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/crash_subtitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginTop="4dp"
android:text="@string/msg_report_crash"
android:textColor="@color/secondaryTextColor_light"
android:textSize="14sp"
app:layout_constraintEnd_toStartOf="@+id/close_button"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/crash_title" />
<androidx.core.widget.NestedScrollView
android:id="@+id/log_text_container"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_margin="16dp"
android:fillViewport="true"
app:layout_constraintBottom_toTopOf="@+id/textView4"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/crash_subtitle">
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<TextView
android:id="@+id/log_text"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:textColor="@color/secondaryColor"
tools:text="This is an error message."/>
</HorizontalScrollView>
</androidx.core.widget.NestedScrollView>
<TextView
android:id="@+id/textView4"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:text="@string/msg_crash_report_hint"
android:textColor="@color/secondaryTextColor"
app:layout_constraintBottom_toTopOf="@+id/report_button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="@+id/report_button"
style="@style/Widget.MaterialComponents.Button.TextButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:backgroundTint="@color/secondaryColor"
android:text="@string/msg_copy_report_action"
android:textColor="@color/primaryTextColor"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/root"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
@@ -0,0 +1,112 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ This file is part of AndroidIDE.
~
~ AndroidIDE is free software: you can redistribute it and/or modify
~ it under the terms of the GNU General Public License as published by
~ the Free Software Foundation, either version 3 of the License, or
~ (at your option) any later version.
~
~ AndroidIDE is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
~ GNU General Public License for more details.
~
~ You should have received a copy of the GNU General Public License
~ along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
-->
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".CrashHandlerActivity">
<ImageButton
android:id="@+id/close_button"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_margin="16dp"
android:background="@drawable/bg_ripple"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_close" />
<TextView
android:id="@+id/crash_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:text="@string/msg_ide_crashed"
android:textColor="@color/primaryTextColor"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/crash_subtitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginTop="4dp"
android:text="@string/msg_report_crash"
android:textColor="@color/secondaryTextColor_light"
android:textSize="14sp"
app:layout_constraintEnd_toStartOf="@+id/close_button"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/crash_title" />
<androidx.core.widget.NestedScrollView
android:id="@+id/log_text_container"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_margin="16dp"
android:fillViewport="true"
app:layout_constraintBottom_toTopOf="@+id/textView4"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/crash_subtitle">
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<TextView
android:id="@+id/log_text"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:textColor="@color/secondaryColor"
tools:text="This is an error message."/>
</HorizontalScrollView>
</androidx.core.widget.NestedScrollView>
<TextView
android:id="@+id/textView4"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:text="@string/msg_crash_report_hint"
android:textColor="@color/secondaryTextColor"
app:layout_constraintBottom_toTopOf="@+id/report_button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="@+id/report_button"
style="@style/Widget.MaterialComponents.Button.TextButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:backgroundTint="@color/secondaryColor"
android:text="@string/msg_copy_report_action"
android:textColor="@color/primaryTextColor"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
+1 -1
View File
@@ -347,6 +347,6 @@
<string name="msg_crash_report_hint">Click on the button below to copy log and open issues page.</string>
<string name="msg_copy_report_action">Copy and report</string>
<string name="msg_reading_bootstrap">Reading bootstrap archive…</string>
<string name="msg_installation_error">Installation error was: %s</string>
<string name="msg_bootstrap_installation_error">Bootstrap installation failed with the following exception.</string>
</resources>