|
19 | 19 | import android.app.PendingIntent.CanceledException;
|
20 | 20 | import android.content.ClipData;
|
21 | 21 | import android.content.ClipboardManager;
|
| 22 | +import android.content.ComponentName; |
22 | 23 | import android.content.Context;
|
23 | 24 | import android.content.Intent;
|
24 | 25 | import android.content.pm.PackageManager;
|
| 26 | +import android.graphics.Color; |
25 | 27 | import android.os.Build;
|
26 | 28 | import android.os.Bundle;
|
27 | 29 | import android.os.Environment;
|
28 | 30 | import com.google.android.material.tabs.TabLayout;
|
| 31 | + |
| 32 | +import androidx.annotation.NonNull; |
29 | 33 | import androidx.core.app.ActivityCompat;
|
30 | 34 | import androidx.fragment.app.Fragment;
|
31 | 35 | import androidx.fragment.app.FragmentManager;
|
32 | 36 | import androidx.fragment.app.FragmentStatePagerAdapter;
|
33 | 37 | import androidx.viewpager.widget.ViewPager;
|
34 | 38 | import androidx.appcompat.app.AppCompatActivity;
|
35 | 39 | import androidx.appcompat.widget.Toolbar;
|
| 40 | + |
| 41 | +import android.text.SpannableString; |
| 42 | +import android.text.SpannableStringBuilder; |
| 43 | +import android.text.method.LinkMovementMethod; |
36 | 44 | 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; |
37 | 49 | import android.util.Log;
|
38 | 50 | import android.view.LayoutInflater;
|
39 | 51 | import android.view.View;
|
|
42 | 54 | import android.widget.TextView;
|
43 | 55 | import android.widget.Toast;
|
44 | 56 |
|
45 |
| - |
46 | 57 | class ErrorReport implements TabLayout.OnTabSelectedListener {
|
47 | 58 | public static final String ERROR_FILE_NAME = "hasError";
|
48 | 59 | private static AppCompatActivity activity;
|
@@ -349,26 +360,96 @@ public int getCount() {
|
349 | 360 | }
|
350 | 361 | }
|
351 | 362 |
|
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 | + |
353 | 411 | @Override
|
354 | 412 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
355 | 413 | int exceptionTabId = container.getContext().getResources().getIdentifier("exception_tab", "layout", container.getContext().getPackageName());
|
356 | 414 | View view = inflater.inflate(exceptionTabId, container, false);
|
357 | 415 |
|
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); |
362 | 440 |
|
363 | 441 | int btnCopyExceptionId = container.getContext().getResources().getIdentifier("btnCopyException", "id", container.getContext().getPackageName());
|
364 | 442 | 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); |
372 | 453 | });
|
373 | 454 |
|
374 | 455 | return view;
|
|
0 commit comments