Skip to content

Commit ee3e354

Browse files
authored
feat: improved error activity ui (#1776)
1 parent d21d6aa commit ee3e354

File tree

7 files changed

+263
-100
lines changed

7 files changed

+263
-100
lines changed

test-app/app/src/debug/java/com/tns/ErrorReport.java

Lines changed: 94 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,21 +19,33 @@
1919
import android.app.PendingIntent.CanceledException;
2020
import android.content.ClipData;
2121
import android.content.ClipboardManager;
22+
import android.content.ComponentName;
2223
import android.content.Context;
2324
import android.content.Intent;
2425
import android.content.pm.PackageManager;
26+
import android.graphics.Color;
2527
import android.os.Build;
2628
import android.os.Bundle;
2729
import android.os.Environment;
2830
import com.google.android.material.tabs.TabLayout;
31+
32+
import androidx.annotation.NonNull;
2933
import androidx.core.app.ActivityCompat;
3034
import androidx.fragment.app.Fragment;
3135
import androidx.fragment.app.FragmentManager;
3236
import androidx.fragment.app.FragmentStatePagerAdapter;
3337
import androidx.viewpager.widget.ViewPager;
3438
import androidx.appcompat.app.AppCompatActivity;
3539
import androidx.appcompat.widget.Toolbar;
40+
41+
import android.text.SpannableString;
42+
import android.text.SpannableStringBuilder;
43+
import android.text.method.LinkMovementMethod;
3644
import android.text.method.ScrollingMovementMethod;
45+
import android.text.style.AbsoluteSizeSpan;
46+
import android.text.style.ClickableSpan;
47+
import android.text.style.ForegroundColorSpan;
48+
import android.text.style.StyleSpan;
3749
import android.util.Log;
3850
import android.view.LayoutInflater;
3951
import android.view.View;
@@ -42,7 +54,6 @@
4254
import android.widget.TextView;
4355
import android.widget.Toast;
4456

45-
4657
class ErrorReport implements TabLayout.OnTabSelectedListener {
4758
public static final String ERROR_FILE_NAME = "hasError";
4859
private static AppCompatActivity activity;
@@ -349,26 +360,96 @@ public int getCount() {
349360
}
350361
}
351362

352-
public static class ExceptionTab extends Fragment {
363+
364+
public static class ExceptionTab extends Fragment {
365+
366+
public SpannableStringBuilder getStyledStacktrace(String trace) {
367+
if (trace == null) return null;
368+
String[] traceLines = trace.trim().split("\n");
369+
SpannableStringBuilder builder = new SpannableStringBuilder();
370+
boolean firstLine = true;
371+
for (String line: traceLines) {
372+
if (firstLine) {
373+
firstLine = false;
374+
} else {
375+
builder.append("\n");
376+
builder.append("\n");
377+
}
378+
379+
String[] nameAndPath = line.trim().split("\\(");
380+
SpannableString nameSpan = new SpannableString(nameAndPath[0]);
381+
nameSpan.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), 0, nameAndPath[0].length(), 0);
382+
builder.append(nameSpan);
383+
384+
builder.append(" ");
385+
if (nameAndPath.length > 1) {
386+
SpannableString pathSpan = new SpannableString("(" + nameAndPath[1]);
387+
pathSpan.setSpan(new AbsoluteSizeSpan(13, true),0, nameAndPath[1].length() + 1, 0);
388+
pathSpan.setSpan(new ClickableSpan() {
389+
@Override
390+
public void onClick(@NonNull View widget) {
391+
Log.d("JS", line.trim());
392+
}
393+
}, 0,nameAndPath[1].length() + 1, 0);
394+
pathSpan.setSpan(new ForegroundColorSpan(Color.GRAY),0, nameAndPath[1].length() + 1, 0);
395+
396+
builder.append(pathSpan);
397+
}
398+
}
399+
return builder;
400+
}
401+
402+
public static void restartApp(Context context) {
403+
PackageManager packageManager = context.getPackageManager();
404+
Intent intent = packageManager.getLaunchIntentForPackage(context.getPackageName());
405+
ComponentName componentName = intent.getComponent();
406+
Intent mainIntent = Intent.makeRestartActivityTask(componentName);
407+
context.startActivity(mainIntent);
408+
java.lang.Runtime.getRuntime().exit(0);
409+
}
410+
353411
@Override
354412
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
355413
int exceptionTabId = container.getContext().getResources().getIdentifier("exception_tab", "layout", container.getContext().getPackageName());
356414
View view = inflater.inflate(exceptionTabId, container, false);
357415

358-
int txtViewId = container.getContext().getResources().getIdentifier("txtErrorMsg", "id", container.getContext().getPackageName());
359-
TextView txtErrorMsg = (TextView) view.findViewById(txtViewId);
360-
txtErrorMsg.setText(exceptionMsg);
361-
txtErrorMsg.setMovementMethod(new ScrollingMovementMethod());
416+
int errorExceptionViewId = activity.getResources().getIdentifier("errorException", "id", activity.getPackageName());
417+
TextView errorExceptionView = (TextView) activity.findViewById(errorExceptionViewId);
418+
errorExceptionView.setMovementMethod(new ScrollingMovementMethod());
419+
420+
int errorStackTraceViewId = container.getContext().getResources().getIdentifier("errorStacktrace", "id", container.getContext().getPackageName());
421+
TextView errorStackTraceView = (TextView) view.findViewById(errorStackTraceViewId);
422+
423+
String[] exceptionParts = exceptionMsg.split("StackTrace:");
424+
String error = exceptionParts[0];
425+
String trace = "";
426+
427+
if (exceptionParts.length > 1) {
428+
for (int i=0;i < exceptionParts.length;i++) {
429+
if (i == 0) continue;
430+
trace += exceptionParts[i];
431+
}
432+
}
433+
434+
errorExceptionView.setText(error.trim());
435+
436+
errorStackTraceView.setText(trace != null ? getStyledStacktrace(trace) : "", TextView.BufferType.SPANNABLE);
437+
errorStackTraceView.setMovementMethod(new ScrollingMovementMethod());
438+
errorStackTraceView.setMovementMethod(LinkMovementMethod.getInstance());
439+
errorStackTraceView.setEnabled(true);
362440

363441
int btnCopyExceptionId = container.getContext().getResources().getIdentifier("btnCopyException", "id", container.getContext().getPackageName());
364442
Button copyToClipboard = (Button) view.findViewById(btnCopyExceptionId);
365-
copyToClipboard.setOnClickListener(new View.OnClickListener() {
366-
@Override
367-
public void onClick(View v) {
368-
ClipboardManager clipboard = (ClipboardManager) activity.getSystemService(Context.CLIPBOARD_SERVICE);
369-
ClipData clip = ClipData.newPlainText("nsError", exceptionMsg);
370-
clipboard.setPrimaryClip(clip);
371-
}
443+
444+
int btnRestartAppId = container.getContext().getResources().getIdentifier("btnRestartApp", "id", container.getContext().getPackageName());
445+
Button restartApp = (Button) view.findViewById(btnRestartAppId);
446+
restartApp.setOnClickListener(v -> {
447+
restartApp(getContext().getApplicationContext());
448+
});
449+
copyToClipboard.setOnClickListener(v -> {
450+
ClipboardManager clipboard = (ClipboardManager) activity.getSystemService(Context.CLIPBOARD_SERVICE);
451+
ClipData clip = ClipData.newPlainText("nsError", exceptionMsg);
452+
clipboard.setPrimaryClip(clip);
372453
});
373454

374455
return view;
Lines changed: 55 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,62 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
3-
xmlns:tools="http://schemas.android.com/tools"
4-
android:layout_width="match_parent"
5-
android:layout_height="match_parent"
6-
xmlns:app="http://schemas.android.com/apk/res-auto"
7-
tools:context="com.tns.ErrorReportActivity"
8-
android:theme="@style/Widget.AppCompat.Light.ActionBar">
9-
10-
<androidx.appcompat.widget.Toolbar
11-
android:id="@+id/toolbar"
12-
android:layout_width="match_parent"
13-
android:layout_height="wrap_content"
14-
android:minHeight="?attr/actionBarSize"/>
3+
xmlns:tools="http://schemas.android.com/tools"
4+
android:layout_width="match_parent"
5+
android:layout_height="match_parent"
6+
xmlns:app="http://schemas.android.com/apk/res-auto"
7+
android:background="@color/gray"
8+
tools:context="com.tns.ErrorReportActivity"
9+
android:theme="@style/Widget.AppCompat.Light.ActionBar">
1510

16-
<androidx.viewpager.widget.ViewPager
17-
android:id="@+id/pager"
18-
android:layout_width="match_parent"
19-
android:layout_height="fill_parent"
20-
android:layout_below="@+id/toolbar"
21-
android:scrollbarAlwaysDrawVerticalTrack="false">
2211

23-
</androidx.viewpager.widget.ViewPager>
24-
25-
<com.google.android.material.tabs.TabLayout
26-
android:id="@+id/tabLayout"
12+
<TextView
13+
android:id="@+id/errorException"
2714
android:layout_width="match_parent"
2815
android:layout_height="wrap_content"
29-
android:background="?attr/colorPrimary"
30-
android:minHeight="?attr/actionBarSize"
31-
app:tabIndicatorColor="@color/nativescript_blue"
32-
android:layout_alignParentTop="true"
33-
android:layout_alignParentStart="true"
34-
android:scrollbarStyle="insideOverlay"
16+
android:text=""
17+
android:background="@color/red"
18+
android:textSize="16sp"
19+
android:paddingLeft="16dp"
20+
android:textIsSelectable="true"
21+
android:maxHeight="200dp"
3522
android:scrollbars="vertical"
36-
tools:tabBackground="@android:color/darker_gray"
37-
android:scrollbarAlwaysDrawVerticalTrack="false"
38-
/>
39-
</RelativeLayout>
23+
android:textColor="@color/white"
24+
android:paddingVertical="10dp"
25+
android:paddingRight="16dp" />
26+
27+
<RelativeLayout
28+
android:layout_below="@id/errorException"
29+
android:layout_width="wrap_content"
30+
android:layout_height="wrap_content">
31+
32+
<androidx.appcompat.widget.Toolbar
33+
android:id="@+id/toolbar"
34+
android:layout_width="match_parent"
35+
android:layout_height="wrap_content"
36+
android:minHeight="?attr/actionBarSize" />
37+
38+
<androidx.viewpager.widget.ViewPager
39+
android:id="@+id/pager"
40+
android:layout_width="match_parent"
41+
android:layout_height="fill_parent"
42+
android:layout_below="@+id/toolbar"
43+
android:scrollbarAlwaysDrawVerticalTrack="false">
44+
45+
</androidx.viewpager.widget.ViewPager>
46+
47+
<com.google.android.material.tabs.TabLayout
48+
android:id="@+id/tabLayout"
49+
android:layout_width="match_parent"
50+
android:layout_height="wrap_content"
51+
android:background="@color/gray"
52+
android:minHeight="?attr/actionBarSize"
53+
app:tabIndicatorColor="@color/nativescript_blue"
54+
android:layout_alignParentTop="true"
55+
android:layout_alignParentStart="true"
56+
android:scrollbarStyle="insideOverlay"
57+
android:scrollbars="vertical"
58+
tools:tabBackground="@color/gray_color"
59+
android:scrollbarAlwaysDrawVerticalTrack="false" />
60+
</RelativeLayout>
61+
62+
</RelativeLayout>
Lines changed: 49 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,71 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
3-
xmlns:tools="http://schemas.android.com/tools"
4-
android:layout_width="match_parent"
5-
android:layout_height="match_parent"
6-
android:orientation="vertical"
7-
android:paddingBottom="10dp"
8-
android:paddingLeft="16dp"
9-
android:paddingRight="16dp"
10-
android:paddingTop="10dp">
11-
12-
<Button
13-
android:id="@+id/btnCopyException"
14-
android:layout_width="match_parent"
15-
android:layout_height="wrap_content"
16-
android:layout_alignParentBottom="true"
17-
android:layout_centerHorizontal="true"
18-
android:background="@color/nativescript_blue"
19-
android:paddingLeft="20dp"
20-
android:paddingRight="20dp"
21-
android:text="Copy to clipboard"
22-
android:textAlignment="textStart"
23-
android:textColor="@android:color/white"
24-
tools:layout_width="match_parent"/>
3+
xmlns:tools="http://schemas.android.com/tools"
4+
android:layout_width="match_parent"
5+
android:background="@color/gray"
6+
android:layout_height="match_parent"
7+
android:orientation="vertical">
8+
259

2610
<LinearLayout
2711
android:id="@+id/linearLayout"
2812
android:layout_width="match_parent"
2913
android:layout_height="wrap_content"
30-
android:layout_above="@+id/btnCopyException"
14+
android:layout_above="@+id/bottomButtonRow"
3115
android:layout_alignParentStart="true"
3216
android:layout_alignParentTop="true"
3317
android:orientation="vertical"
34-
android:paddingBottom="10dp"
3518
android:weightSum="100">
3619

20+
3721
<TextView
38-
android:id="@+id/txtErrorMsg"
22+
android:id="@+id/errorStacktrace"
3923
android:layout_width="match_parent"
4024
android:layout_height="wrap_content"
4125
android:text=""
42-
android:textAppearance="?android:attr/textAppearanceSmall"
43-
android:paddingLeft="2dp"
44-
android:paddingRight="2dp"
4526
android:scrollbars="vertical"
4627
android:scrollbarStyle="outsideOverlay"
47-
android:scrollbarAlwaysDrawVerticalTrack="true"/>
28+
android:paddingLeft="16dp"
29+
android:paddingRight="16dp"
30+
android:scrollbarAlwaysDrawVerticalTrack="true" />
31+
32+
</LinearLayout>
33+
34+
<LinearLayout
35+
android:id="@+id/bottomButtonRow"
36+
android:layout_width="match_parent"
37+
android:orientation="horizontal"
38+
android:layout_alignParentBottom="true"
39+
android:layout_centerHorizontal="true"
40+
android:paddingBottom="10dp"
41+
android:paddingLeft="16dp"
42+
android:paddingRight="16dp"
43+
android:paddingTop="10dp"
44+
android:layout_height="wrap_content">
45+
46+
<Button
47+
android:id="@+id/btnRestartApp"
48+
android:text="Restart APP"
49+
android:textAlignment="center"
50+
android:textColor="@android:color/white"
51+
android:background="@drawable/button_accented"
52+
android:layout_width="0dp"
53+
android:layout_height="wrap_content"
54+
android:layout_weight="1"
55+
android:layout_marginRight="10dp" />
56+
57+
<Button
58+
android:id="@+id/btnCopyException"
59+
android:textColor="@android:color/white"
60+
android:text="Copy"
61+
android:background="@drawable/button"
62+
android:textAlignment="center"
63+
android:layout_width="0dp"
64+
android:layout_height="wrap_content"
65+
android:layout_weight="1" />
66+
4867

4968
</LinearLayout>
5069

5170

52-
</RelativeLayout>
71+
</RelativeLayout>

0 commit comments

Comments
 (0)