@nativescript/android 8.8.0-alpha.11 → 8.8.0-alpha.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/framework/app/build.gradle +10 -4
- package/framework/app/libs/runtime-libs/nativescript-optimized-with-inspector.aar +0 -0
- package/framework/app/libs/runtime-libs/nativescript-optimized.aar +0 -0
- package/framework/app/libs/runtime-libs/nativescript-regular.aar +0 -0
- package/framework/app/src/main/assets/internal/ts_helpers.js +3 -1
- package/framework/build-tools/android-metadata-generator.jar +0 -0
- package/framework/build-tools/dts-generator.jar +0 -0
- package/framework/build-tools/jsparser/js_parser.js +1 -1
- package/framework/build-tools/static-binding-generator.jar +0 -0
- package/framework/settings.gradle +7 -0
- package/package.json +1 -1
- package/framework/app/src/debug/java/com/tns/ErrorReport.java +0 -512
- package/framework/app/src/debug/java/com/tns/ErrorReportActivity.java +0 -52
- package/framework/app/src/debug/java/com/tns/NativeScriptSyncService.java +0 -346
- package/framework/app/src/debug/java/com/tns/NativeScriptSyncServiceSocketImpl.java +0 -448
- package/framework/app/src/debug/res/layout/error_activity.xml +0 -62
- package/framework/app/src/debug/res/layout/exception_tab.xml +0 -71
- package/framework/app/src/debug/res/layout/logcat_tab.xml +0 -71
- package/framework/app/src/debug/res/values/colors.xml +0 -7
- package/framework/app/src/main/java/com/tns/AndroidJsV8Inspector.java +0 -361
- package/framework/app/src/main/java/com/tns/DefaultExtractPolicy.java +0 -151
- package/framework/app/src/main/java/com/tns/EqualityComparator.java +0 -7
- package/framework/app/src/main/java/com/tns/LogcatLogger.java +0 -45
- package/framework/app/src/main/java/com/tns/NativeScriptUncaughtExceptionHandler.java +0 -72
- package/framework/app/src/main/java/com/tns/RuntimeHelper.java +0 -343
- package/framework/app/src/main/java/com/tns/Util.java +0 -105
- package/framework/app/src/main/java/com/tns/internal/AppBuilderCallback.java +0 -21
- package/framework/app/src/main/java/com/tns/internal/Plugin.java +0 -5
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,512 +0,0 @@
|
|
|
1
|
-
package com.tns;
|
|
2
|
-
|
|
3
|
-
import java.io.BufferedReader;
|
|
4
|
-
import java.io.ByteArrayOutputStream;
|
|
5
|
-
import java.io.File;
|
|
6
|
-
import java.io.FileOutputStream;
|
|
7
|
-
import java.io.IOException;
|
|
8
|
-
import java.io.InputStreamReader;
|
|
9
|
-
import java.io.OutputStreamWriter;
|
|
10
|
-
import java.io.PrintStream;
|
|
11
|
-
import java.io.UnsupportedEncodingException;
|
|
12
|
-
import java.lang.reflect.Method;
|
|
13
|
-
import java.text.SimpleDateFormat;
|
|
14
|
-
import java.util.Date;
|
|
15
|
-
|
|
16
|
-
import android.Manifest;
|
|
17
|
-
import android.app.Activity;
|
|
18
|
-
import android.app.PendingIntent;
|
|
19
|
-
import android.app.PendingIntent.CanceledException;
|
|
20
|
-
import android.content.ClipData;
|
|
21
|
-
import android.content.ClipboardManager;
|
|
22
|
-
import android.content.ComponentName;
|
|
23
|
-
import android.content.Context;
|
|
24
|
-
import android.content.Intent;
|
|
25
|
-
import android.content.pm.PackageManager;
|
|
26
|
-
import android.graphics.Color;
|
|
27
|
-
import android.os.Build;
|
|
28
|
-
import android.os.Bundle;
|
|
29
|
-
import android.os.Environment;
|
|
30
|
-
import com.google.android.material.tabs.TabLayout;
|
|
31
|
-
|
|
32
|
-
import androidx.annotation.NonNull;
|
|
33
|
-
import androidx.core.app.ActivityCompat;
|
|
34
|
-
import androidx.fragment.app.Fragment;
|
|
35
|
-
import androidx.fragment.app.FragmentManager;
|
|
36
|
-
import androidx.fragment.app.FragmentStatePagerAdapter;
|
|
37
|
-
import androidx.viewpager.widget.ViewPager;
|
|
38
|
-
import androidx.appcompat.app.AppCompatActivity;
|
|
39
|
-
import androidx.appcompat.widget.Toolbar;
|
|
40
|
-
|
|
41
|
-
import android.text.SpannableString;
|
|
42
|
-
import android.text.SpannableStringBuilder;
|
|
43
|
-
import android.text.method.LinkMovementMethod;
|
|
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;
|
|
49
|
-
import android.util.Log;
|
|
50
|
-
import android.view.LayoutInflater;
|
|
51
|
-
import android.view.View;
|
|
52
|
-
import android.view.ViewGroup;
|
|
53
|
-
import android.widget.Button;
|
|
54
|
-
import android.widget.TextView;
|
|
55
|
-
import android.widget.Toast;
|
|
56
|
-
|
|
57
|
-
class ErrorReport implements TabLayout.OnTabSelectedListener {
|
|
58
|
-
public static final String ERROR_FILE_NAME = "hasError";
|
|
59
|
-
private static AppCompatActivity activity;
|
|
60
|
-
|
|
61
|
-
private TabLayout tabLayout;
|
|
62
|
-
private ViewPager viewPager;
|
|
63
|
-
private Context context;
|
|
64
|
-
|
|
65
|
-
private static String exceptionMsg;
|
|
66
|
-
private static String logcatMsg;
|
|
67
|
-
|
|
68
|
-
private static boolean checkingForPermissions = false;
|
|
69
|
-
|
|
70
|
-
private final static String EXTRA_NATIVESCRIPT_ERROR_REPORT = "NativeScriptErrorMessage";
|
|
71
|
-
private final static String EXTRA_ERROR_REPORT_MSG = "msg";
|
|
72
|
-
private final static String EXTRA_PID = "pID";
|
|
73
|
-
private final static int EXTRA_ERROR_REPORT_VALUE = 1;
|
|
74
|
-
|
|
75
|
-
private static final int REQUEST_EXTERNAL_STORAGE = 1;
|
|
76
|
-
private static String[] PERMISSIONS_STORAGE = {
|
|
77
|
-
Manifest.permission.READ_EXTERNAL_STORAGE,
|
|
78
|
-
Manifest.permission.WRITE_EXTERNAL_STORAGE
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
// Will prevent error activity from killing process if permission request dialog pops up
|
|
82
|
-
public static boolean isCheckingForPermissions() {
|
|
83
|
-
return checkingForPermissions;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
public static void resetCheckingForPermissions() {
|
|
87
|
-
checkingForPermissions = false;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// The following will not compile if uncommented with compileSdk lower than 23
|
|
91
|
-
public static void verifyStoragePermissions(Activity activity) {
|
|
92
|
-
// Check if we have write permission
|
|
93
|
-
final int version = Build.VERSION.SDK_INT;
|
|
94
|
-
if (version >= 23) {
|
|
95
|
-
try {
|
|
96
|
-
// Necessary to work around compile errors with compileSdk 22 and lower
|
|
97
|
-
Method checkSelfPermissionMethod;
|
|
98
|
-
try {
|
|
99
|
-
checkSelfPermissionMethod = ActivityCompat.class.getMethod("checkSelfPermission", Context.class, String.class);
|
|
100
|
-
} catch (NoSuchMethodException e) {
|
|
101
|
-
// method wasn't found, so there is no need to handle permissions explicitly
|
|
102
|
-
if (Util.isDebuggableApp(activity)) {
|
|
103
|
-
e.printStackTrace();
|
|
104
|
-
}
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
int permission = (int) checkSelfPermissionMethod.invoke(null, activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);
|
|
109
|
-
|
|
110
|
-
if (permission != PackageManager.PERMISSION_GRANTED) {
|
|
111
|
-
// We don't have permission so prompt the user
|
|
112
|
-
Method requestPermissionsMethod = ActivityCompat.class.getMethod("requestPermissions", Activity.class, PERMISSIONS_STORAGE.getClass(), int.class);
|
|
113
|
-
|
|
114
|
-
checkingForPermissions = true;
|
|
115
|
-
|
|
116
|
-
requestPermissionsMethod.invoke(null, activity, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);
|
|
117
|
-
}
|
|
118
|
-
} catch (Exception e) {
|
|
119
|
-
Toast.makeText(activity, "Couldn't resolve permissions", Toast.LENGTH_LONG).show();
|
|
120
|
-
if (Util.isDebuggableApp(activity)) {
|
|
121
|
-
e.printStackTrace();
|
|
122
|
-
}
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
public ErrorReport(AppCompatActivity activity) {
|
|
129
|
-
ErrorReport.activity = activity;
|
|
130
|
-
this.context = activity.getApplicationContext();
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
static boolean startActivity(final Context context, String errorMessage) {
|
|
134
|
-
final Intent intent = getIntent(context);
|
|
135
|
-
if (intent == null) {
|
|
136
|
-
return false; // (if in release mode) don't do anything
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
intent.putExtra(EXTRA_ERROR_REPORT_MSG, errorMessage);
|
|
140
|
-
|
|
141
|
-
String PID = Integer.toString(android.os.Process.myPid());
|
|
142
|
-
intent.putExtra(EXTRA_PID, PID);
|
|
143
|
-
|
|
144
|
-
createErrorFile(context);
|
|
145
|
-
|
|
146
|
-
try {
|
|
147
|
-
startPendingErrorActivity(context, intent);
|
|
148
|
-
} catch (CanceledException e) {
|
|
149
|
-
Log.d("ErrorReport", "Couldn't send pending intent! Exception: " + e.getMessage());
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
killProcess(context);
|
|
153
|
-
|
|
154
|
-
return true;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
static void killProcess(Context context) {
|
|
158
|
-
// finish current activity and all below it first
|
|
159
|
-
if (context instanceof Activity) {
|
|
160
|
-
((Activity) context).finishAffinity();
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
// kill process
|
|
164
|
-
android.os.Process.killProcess(android.os.Process.myPid());
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
static void startPendingErrorActivity(Context context, Intent intent) throws CanceledException {
|
|
168
|
-
int flags = PendingIntent.FLAG_CANCEL_CURRENT;
|
|
169
|
-
if (Build.VERSION.SDK_INT >= 31) {
|
|
170
|
-
flags = PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_MUTABLE;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, flags);
|
|
174
|
-
|
|
175
|
-
pendingIntent.send(context, 0, intent);
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
static String getErrorMessage(Throwable ex) {
|
|
179
|
-
String content;
|
|
180
|
-
PrintStream ps = null;
|
|
181
|
-
|
|
182
|
-
try {
|
|
183
|
-
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
184
|
-
ps = new PrintStream(baos);
|
|
185
|
-
ex.printStackTrace(ps);
|
|
186
|
-
|
|
187
|
-
try {
|
|
188
|
-
content = baos.toString("UTF-8");
|
|
189
|
-
} catch (UnsupportedEncodingException e) {
|
|
190
|
-
content = e.getMessage();
|
|
191
|
-
}
|
|
192
|
-
} finally {
|
|
193
|
-
if (ps != null) {
|
|
194
|
-
ps.close();
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
return content;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
/*
|
|
202
|
-
* Gets the process Id of the running app and filters all
|
|
203
|
-
* output that doesn't belong to that process
|
|
204
|
-
* */
|
|
205
|
-
public static String getLogcat(String pId) {
|
|
206
|
-
String content;
|
|
207
|
-
|
|
208
|
-
try {
|
|
209
|
-
String logcatCommand = "logcat -d";
|
|
210
|
-
Process process = java.lang.Runtime.getRuntime().exec(logcatCommand);
|
|
211
|
-
|
|
212
|
-
BufferedReader bufferedReader = new BufferedReader(
|
|
213
|
-
new InputStreamReader(process.getInputStream()));
|
|
214
|
-
|
|
215
|
-
StringBuilder log = new StringBuilder();
|
|
216
|
-
String line = "";
|
|
217
|
-
String lineSeparator = System.getProperty("line.separator");
|
|
218
|
-
while ((line = bufferedReader.readLine()) != null) {
|
|
219
|
-
if (line.contains(pId)) {
|
|
220
|
-
log.append(line);
|
|
221
|
-
log.append(lineSeparator);
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
content = log.toString();
|
|
226
|
-
} catch (IOException e) {
|
|
227
|
-
content = "Failed to read logcat";
|
|
228
|
-
Log.e("TNS.Android", content);
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
return content;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
static Intent getIntent(Context context) {
|
|
235
|
-
Class<?> errorActivityClass;
|
|
236
|
-
|
|
237
|
-
if (Util.isDebuggableApp(context)) {
|
|
238
|
-
errorActivityClass = ErrorReportActivity.class;
|
|
239
|
-
} else {
|
|
240
|
-
return null;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
Intent intent = new Intent(context, errorActivityClass);
|
|
244
|
-
|
|
245
|
-
intent.putExtra(EXTRA_NATIVESCRIPT_ERROR_REPORT, EXTRA_ERROR_REPORT_VALUE);
|
|
246
|
-
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
247
|
-
|
|
248
|
-
return intent;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
static boolean hasIntent(Intent intent) {
|
|
252
|
-
int value = intent.getIntExtra(EXTRA_NATIVESCRIPT_ERROR_REPORT, 0);
|
|
253
|
-
|
|
254
|
-
return value == EXTRA_ERROR_REPORT_VALUE;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
void buildUI() {
|
|
258
|
-
Intent intent = activity.getIntent();
|
|
259
|
-
|
|
260
|
-
exceptionMsg = intent.getStringExtra(EXTRA_ERROR_REPORT_MSG);
|
|
261
|
-
|
|
262
|
-
String processId = intent.getStringExtra(EXTRA_PID);
|
|
263
|
-
logcatMsg = getLogcat(processId);
|
|
264
|
-
|
|
265
|
-
int errActivityId = this.context.getResources().getIdentifier("error_activity", "layout", this.context.getPackageName());
|
|
266
|
-
|
|
267
|
-
activity.setContentView(errActivityId);
|
|
268
|
-
|
|
269
|
-
int toolBarId = this.context.getResources().getIdentifier("toolbar", "id", this.context.getPackageName());
|
|
270
|
-
|
|
271
|
-
Toolbar toolbar = (Toolbar) activity.findViewById(toolBarId);
|
|
272
|
-
activity.setSupportActionBar(toolbar);
|
|
273
|
-
|
|
274
|
-
final int tabLayoutId = this.context.getResources().getIdentifier("tabLayout", "id", this.context.getPackageName());
|
|
275
|
-
|
|
276
|
-
tabLayout = (TabLayout) activity.findViewById(tabLayoutId);
|
|
277
|
-
tabLayout.addTab(tabLayout.newTab().setText("Exception"));
|
|
278
|
-
tabLayout.addTab(tabLayout.newTab().setText("Logcat"));
|
|
279
|
-
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
|
|
280
|
-
int pagerId = this.context.getResources().getIdentifier("pager", "id", this.context.getPackageName());
|
|
281
|
-
|
|
282
|
-
viewPager = (ViewPager) activity.findViewById(pagerId);
|
|
283
|
-
|
|
284
|
-
Pager adapter = new Pager(activity.getSupportFragmentManager(), tabLayout.getTabCount());
|
|
285
|
-
|
|
286
|
-
viewPager.setAdapter(adapter);
|
|
287
|
-
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
|
|
288
|
-
@Override
|
|
289
|
-
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
|
|
290
|
-
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
@Override
|
|
294
|
-
public void onPageSelected(int position) {
|
|
295
|
-
tabLayout.getTabAt(position).select();
|
|
296
|
-
viewPager.setCurrentItem(position);
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
@Override
|
|
300
|
-
public void onPageScrollStateChanged(int state) {
|
|
301
|
-
|
|
302
|
-
}
|
|
303
|
-
});
|
|
304
|
-
|
|
305
|
-
this.addOnTabSelectedListener(tabLayout);
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
private void addOnTabSelectedListener(TabLayout tabLayout) {
|
|
309
|
-
tabLayout.addOnTabSelectedListener(this);
|
|
310
|
-
}
|
|
311
|
-
private static void createErrorFile(final Context context) {
|
|
312
|
-
try {
|
|
313
|
-
File errFile = new File(context.getFilesDir(), ERROR_FILE_NAME);
|
|
314
|
-
errFile.createNewFile();
|
|
315
|
-
} catch (IOException e) {
|
|
316
|
-
Log.d("ErrorReport", e.getMessage());
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
@Override
|
|
321
|
-
public void onTabSelected(TabLayout.Tab tab) {
|
|
322
|
-
viewPager.setCurrentItem(tab.getPosition());
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
@Override
|
|
326
|
-
public void onTabUnselected(TabLayout.Tab tab) {
|
|
327
|
-
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
@Override
|
|
331
|
-
public void onTabReselected(TabLayout.Tab tab) {
|
|
332
|
-
viewPager.setCurrentItem(tab.getPosition());
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
private class Pager extends FragmentStatePagerAdapter {
|
|
336
|
-
|
|
337
|
-
int tabCount;
|
|
338
|
-
|
|
339
|
-
@SuppressWarnings("deprecation")
|
|
340
|
-
public Pager(FragmentManager fm, int tabCount) {
|
|
341
|
-
super(fm);
|
|
342
|
-
this.tabCount = tabCount;
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
@Override
|
|
346
|
-
public Fragment getItem(int position) {
|
|
347
|
-
switch (position) {
|
|
348
|
-
case 0:
|
|
349
|
-
return new ExceptionTab();
|
|
350
|
-
case 1:
|
|
351
|
-
return new LogcatTab();
|
|
352
|
-
default:
|
|
353
|
-
return null;
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
@Override
|
|
358
|
-
public int getCount() {
|
|
359
|
-
return tabCount;
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
|
|
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
|
-
|
|
411
|
-
@Override
|
|
412
|
-
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
|
413
|
-
int exceptionTabId = container.getContext().getResources().getIdentifier("exception_tab", "layout", container.getContext().getPackageName());
|
|
414
|
-
View view = inflater.inflate(exceptionTabId, container, false);
|
|
415
|
-
|
|
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);
|
|
440
|
-
|
|
441
|
-
int btnCopyExceptionId = container.getContext().getResources().getIdentifier("btnCopyException", "id", container.getContext().getPackageName());
|
|
442
|
-
Button copyToClipboard = (Button) view.findViewById(btnCopyExceptionId);
|
|
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);
|
|
453
|
-
});
|
|
454
|
-
|
|
455
|
-
return view;
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
public static class LogcatTab extends Fragment {
|
|
460
|
-
@Override
|
|
461
|
-
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
|
462
|
-
int logcatTabId = container.getContext().getResources().getIdentifier("logcat_tab", "layout", container.getContext().getPackageName());
|
|
463
|
-
View view = inflater.inflate(logcatTabId, container, false);
|
|
464
|
-
|
|
465
|
-
int textViewId = container.getContext().getResources().getIdentifier("logcatMsg", "id", container.getContext().getPackageName());
|
|
466
|
-
TextView txtlogcatMsg = (TextView) view.findViewById(textViewId);
|
|
467
|
-
txtlogcatMsg.setText(logcatMsg);
|
|
468
|
-
|
|
469
|
-
txtlogcatMsg.setMovementMethod(new ScrollingMovementMethod());
|
|
470
|
-
|
|
471
|
-
final String logName = "Log-" + new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date());
|
|
472
|
-
|
|
473
|
-
int btnCopyLogcatId = container.getContext().getResources().getIdentifier("btnCopyLogcat", "id", container.getContext().getPackageName());
|
|
474
|
-
Button copyToClipboard = (Button) view.findViewById(btnCopyLogcatId);
|
|
475
|
-
copyToClipboard.setOnClickListener(new View.OnClickListener() {
|
|
476
|
-
@Override
|
|
477
|
-
public void onClick(View v) {
|
|
478
|
-
verifyStoragePermissions(activity);
|
|
479
|
-
|
|
480
|
-
if (!isCheckingForPermissions()) {
|
|
481
|
-
try {
|
|
482
|
-
File dir = new File(Environment.getExternalStorageDirectory().getPath() + "/logcat-reports/");
|
|
483
|
-
dir.mkdirs();
|
|
484
|
-
|
|
485
|
-
File logcatReportFile = new File(dir, logName);
|
|
486
|
-
FileOutputStream stream = new FileOutputStream(logcatReportFile);
|
|
487
|
-
OutputStreamWriter writer = new OutputStreamWriter(stream, "UTF-8");
|
|
488
|
-
writer.write(logcatMsg);
|
|
489
|
-
writer.close();
|
|
490
|
-
|
|
491
|
-
String logPath = dir.getPath() + "/" + logName;
|
|
492
|
-
|
|
493
|
-
ClipboardManager clipboard = (ClipboardManager) activity.getSystemService(Context.CLIPBOARD_SERVICE);
|
|
494
|
-
ClipData clip = ClipData.newPlainText("logPath", logPath);
|
|
495
|
-
clipboard.setPrimaryClip(clip);
|
|
496
|
-
|
|
497
|
-
Toast.makeText(activity, "Path copied to clipboard: " + logPath, Toast.LENGTH_LONG).show();
|
|
498
|
-
} catch (Exception e) {
|
|
499
|
-
String err = "Could not write logcat report to sdcard. Make sure you have allowed access to external storage!";
|
|
500
|
-
Toast.makeText(activity, err, Toast.LENGTH_LONG).show();
|
|
501
|
-
if (Util.isDebuggableApp(container.getContext())) {
|
|
502
|
-
e.printStackTrace();
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
});
|
|
508
|
-
|
|
509
|
-
return view;
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
}
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
package com.tns;
|
|
2
|
-
|
|
3
|
-
import android.app.Application;
|
|
4
|
-
import android.os.Bundle;
|
|
5
|
-
import androidx.annotation.NonNull;
|
|
6
|
-
import androidx.appcompat.app.AppCompatActivity;
|
|
7
|
-
import android.widget.Toast;
|
|
8
|
-
|
|
9
|
-
import java.lang.reflect.Method;
|
|
10
|
-
|
|
11
|
-
import static com.tns.ErrorReport.isCheckingForPermissions;
|
|
12
|
-
import static com.tns.ErrorReport.resetCheckingForPermissions;
|
|
13
|
-
|
|
14
|
-
public class ErrorReportActivity extends AppCompatActivity {
|
|
15
|
-
public void onCreate(Bundle savedInstanceState) {
|
|
16
|
-
setTheme(androidx.appcompat.R.style.Theme_AppCompat_NoActionBar);
|
|
17
|
-
|
|
18
|
-
super.onCreate(savedInstanceState);
|
|
19
|
-
Application app = this.getApplication();
|
|
20
|
-
Logger logger = new LogcatLogger(app);
|
|
21
|
-
|
|
22
|
-
RuntimeHelper.initLiveSync(null, logger, app);
|
|
23
|
-
|
|
24
|
-
new ErrorReport(this).buildUI();
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
@Override
|
|
28
|
-
protected void onUserLeaveHint() {
|
|
29
|
-
super.onUserLeaveHint();
|
|
30
|
-
|
|
31
|
-
if (!isCheckingForPermissions()) {
|
|
32
|
-
ErrorReport.killProcess(this);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// @Override
|
|
37
|
-
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
|
38
|
-
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
|
39
|
-
try {
|
|
40
|
-
Method onRequestPermissionsResultMethod = AppCompatActivity.class.getMethod("onRequestPermissionsResult", int.class, permissions.getClass(), grantResults.getClass());
|
|
41
|
-
onRequestPermissionsResultMethod.invoke(new AppCompatActivity() /* never do this */, requestCode, permissions, grantResults);
|
|
42
|
-
|
|
43
|
-
resetCheckingForPermissions();
|
|
44
|
-
} catch (Exception e) {
|
|
45
|
-
if (Util.isDebuggableApp(this)) {
|
|
46
|
-
e.printStackTrace();
|
|
47
|
-
}
|
|
48
|
-
Toast.makeText(this, "Couldn't resolve permissions", Toast.LENGTH_LONG).show();
|
|
49
|
-
resetCheckingForPermissions();
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
}
|