-
Notifications
You must be signed in to change notification settings - Fork 205
/
NativeInterface.java
468 lines (420 loc) · 13.6 KB
/
NativeInterface.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
package com.bugsnag.android;
import android.annotation.SuppressLint;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Observer;
import java.util.Queue;
/**
* Used as the entry point for native code to allow proguard to obfuscate other areas if needed
*/
public class NativeInterface {
public enum MessageType {
/**
* Add a breadcrumb. The Message object should be the breadcrumb
*/
ADD_BREADCRUMB,
/**
* Add a new metadata value. The Message object should be an array
* containing [tab, key, value]
*/
ADD_METADATA,
/**
* Clear all breadcrumbs
*/
CLEAR_BREADCRUMBS,
/**
* Clear all metadata on a tab. The Message object should be the tab
* name
*/
CLEAR_METADATA_TAB,
/**
* Deliver all pending reports
*/
DELIVER_PENDING,
/**
* Set up Bugsnag. The message object should be a Configuration.
*/
INSTALL,
/**
* Send a report for a handled Java exception
*/
NOTIFY_HANDLED,
/**
* Send a report for an unhandled error in the Java layer
*/
NOTIFY_UNHANDLED,
/**
* Remove a metadata value. The Message object should be a string array
* containing [tab, key]
*/
REMOVE_METADATA,
/**
* A new session was started. The Message object should be a string
* array
* containing [id, startDateIsoString]
*/
START_SESSION,
/**
* A session was stopped.
*/
STOP_SESSION,
/**
* Set a new app version. The Message object should be the new app
* version
*/
UPDATE_APP_VERSION,
/**
* Set a new build UUID. The Message object should be the new build
* UUID string
*/
UPDATE_BUILD_UUID,
/**
* Set a new context. The message object should be the new context
*/
UPDATE_CONTEXT,
/**
* Set a new value for `app.inForeground`. The message object should be a
* List containing the values [inForeground (Boolean),
* foregroundActivityName (String)]
*/
UPDATE_IN_FOREGROUND,
/**
* Set a new value for `app.lowMemory`. The message object should be a
* Boolean
*/
UPDATE_LOW_MEMORY,
/**
* Set a new value for all custom metadata. The message object should be
* MetaData.
*/
UPDATE_METADATA,
/**
* Set a new value for `device.orientation`. The message object should
* be the orientation in degrees
*/
UPDATE_ORIENTATION,
/**
* Set a new value for `app.releaseStage`. The message object should be
* the new release stage
*/
UPDATE_RELEASE_STAGE,
/**
* Set a new value for user email. The message object is a string
*/
UPDATE_USER_EMAIL,
/**
* Set a new value for user name. The message object is a string
*/
UPDATE_USER_NAME,
/**
* Set a new value for user id. The message object is a string
*/
UPDATE_USER_ID,
}
/**
* Wrapper for messages sent to native observers
*/
public static class Message {
@NonNull
public final MessageType type;
@Nullable
public final Object value;
public Message(@NonNull MessageType type, @Nullable Object value) {
this.type = type;
this.value = value;
}
}
/**
* Static reference used if not using Bugsnag.init()
*/
@SuppressLint("StaticFieldLeak")
private static Client client;
@NonNull
private static Client getClient() {
if (client != null) {
return client;
} else {
return Bugsnag.getClient();
}
}
/**
* Caches a client instance for responding to future events
*/
public static void setClient(@NonNull Client client) {
if (NativeInterface.client == client) {
return;
}
NativeInterface.client = client;
configureClientObservers(client);
}
/**
* Sets up observers for the NDK client
* @param client the client
*/
public static void configureClientObservers(@NonNull Client client) {
try {
String className = "com.bugsnag.android.ndk.NativeBridge";
Class<?> clz = Class.forName(className);
Observer observer = (Observer) clz.newInstance();
client.addObserver(observer);
} catch (ClassNotFoundException exception) {
// ignore this one, will happen if the NDK plugin is not present
Logger.info("Bugsnag NDK integration not available");
} catch (InstantiationException exception) {
Logger.warn("Failed to instantiate NDK observer", exception);
} catch (IllegalAccessException exception) {
Logger.warn("Could not access NDK observer", exception);
}
// Configure NDK components
client.sendNativeSetupNotification();
}
@Nullable
public static String getContext() {
return getClient().getContext();
}
public static boolean getLoggingEnabled() {
return Logger.getEnabled();
}
@NonNull
public static String getNativeReportPath() {
return getClient().appContext.getCacheDir().getAbsolutePath() + "/bugsnag-native/";
}
/**
* Retrieve user data from the static Client instance as a Map
*/
@NonNull
@SuppressWarnings("unused")
public static Map<String,String> getUserData() {
HashMap<String, String> userData = new HashMap<>();
User user = getClient().getUser();
userData.put("id", user.getId());
userData.put("name", user.getName());
userData.put("email", user.getEmail());
return userData;
}
/**
* Retrieve app data from the static Client instance as a Map
*/
@NonNull
@SuppressWarnings("unused")
public static Map<String,Object> getAppData() {
HashMap<String,Object> data = new HashMap<>();
AppData source = getClient().getAppData();
data.putAll(source.getAppData());
data.putAll(source.getAppDataMetaData());
return data;
}
/**
* Retrieve device data from the static Client instance as a Map
*/
@NonNull
@SuppressWarnings("unused")
public static Map<String,Object> getDeviceData() {
HashMap<String,Object> deviceData = new HashMap<>();
DeviceData source = getClient().getDeviceData();
deviceData.putAll(source.getDeviceMetaData());
deviceData.putAll(source.getDeviceData()); // wat
return deviceData;
}
/**
* Retrieve the CPU ABI(s) for the current device
*/
@NonNull
public static String[] getCpuAbi() {
return getClient().deviceData.cpuAbi;
}
/**
* Retrieves global metadata from the static Client instance as a Map
*/
@NonNull
public static Map<String, Object> getMetaData() {
return new HashMap<>(getClient().getMetaData().store);
}
/**
* Retrieves breadcrumbs from the static Client instance as a Map
*/
@NonNull
public static List<Breadcrumb> getBreadcrumbs() {
Queue<Breadcrumb> store = getClient().breadcrumbs.store;
return new ArrayList<>(store);
}
/**
* Sets the user
*
* @param id id
* @param email email
* @param name name
*/
@SuppressWarnings("unused")
public static void setUser(@Nullable final String id,
@Nullable final String email,
@Nullable final String name) {
Client client = getClient();
client.setUserId(id);
client.setUserEmail(email);
client.setUserName(name);
}
/**
* Leave a "breadcrumb" log message
*/
public static void leaveBreadcrumb(@NonNull final String name,
@NonNull final BreadcrumbType type) {
getClient().leaveBreadcrumb(name, type, new HashMap<String, String>());
}
/**
* Leaves a breadcrumb on the static client instance
*/
public static void leaveBreadcrumb(@NonNull String name,
@NonNull String type,
@NonNull Map<String, String> metadata) {
String typeName = type.toUpperCase(Locale.US);
Map<String, String> map = metadata == null ? new HashMap<String, String>() : metadata;
getClient().leaveBreadcrumb(name, BreadcrumbType.valueOf(typeName), map);
}
/**
* Add metadata to subsequent exception reports
*/
public static void addToTab(@NonNull final String tab,
@NonNull final String key,
@Nullable final Object value) {
getClient().addToTab(tab, key, value);
}
/**
* Set the client report release stage
*/
public static void setReleaseStage(@Nullable final String stage) {
getClient().setReleaseStage(stage);
}
/**
* Return the client report release stage
*/
@Nullable
public static String getReleaseStage() {
return getClient().getConfig().getReleaseStage();
}
/**
* Return the client session endpoint
*/
@NonNull
public static String getSessionEndpoint() {
return getClient().getConfig().getSessionEndpoint();
}
/**
* Return the client report endpoint
*/
@NonNull
public static String getEndpoint() {
return getClient().getConfig().getEndpoint();
}
/**
* Set the client session endpoint
*/
@SuppressWarnings("deprecation")
public static void setSessionEndpoint(@NonNull final String endpoint) {
getClient().getConfig().setSessionEndpoint(endpoint);
}
/**
* Set the client report endpoint
*/
@SuppressWarnings("deprecation")
public static void setEndpoint(@NonNull final String endpoint) {
getClient().getConfig().setEndpoint(endpoint);
}
/**
* Set the client report context
*/
public static void setContext(@Nullable final String context) {
getClient().setContext(context);
}
/**
* Set the client report app version
*/
public static void setAppVersion(@NonNull final String version) {
getClient().setAppVersion(version);
}
/**
* Set the binary arch used in the application
*/
public static void setBinaryArch(@NonNull final String binaryArch) {
getClient().setBinaryArch(binaryArch);
}
/**
* Return the client report app version
*/
@NonNull
public static String getAppVersion() {
return getClient().getConfig().getAppVersion();
}
public static boolean getDetectAnrs() {
return getClient().getConfig().getDetectAnrs();
}
public static long getAnrThresholdMs() {
return getClient().getConfig().getAnrThresholdMs();
}
public static void setDetectAnrs(boolean newValue) {
getClient().getConfig().setDetectAnrs(newValue);
}
public static void setAnrThresholdMs(long newValue) {
getClient().getConfig().setAnrThresholdMs(newValue);
}
/**
* Return which release stages notify
*/
@Nullable
public static String[] getNotifyReleaseStages() {
return getClient().getConfig().getNotifyReleaseStages();
}
/**
* Set which release stages notify
*/
public static void setNotifyReleaseStages(@Nullable String[] notifyReleaseStages) {
getClient().getConfig().setNotifyReleaseStages(notifyReleaseStages);
}
/**
* Deliver a report, serialized as an event JSON payload.
*
* @param releaseStage The release stage in which the event was captured. Used to determin
* whether the report should be discarded, based on configured release
* stages
*/
@SuppressWarnings("unused")
public static void deliverReport(@Nullable String releaseStage, @NonNull String payload) {
Client client = getClient();
if (releaseStage == null
|| releaseStage.length() == 0
|| client.getConfig().shouldNotifyForReleaseStage(releaseStage)) {
client.getErrorStore().enqueueContentForDelivery(payload);
client.getErrorStore().flushAsync();
}
}
/**
* Notifies using the Android SDK
*
* @param name the error name
* @param message the error message
* @param severity the error severity
* @param stacktrace a stacktrace
*/
public static void notify(@NonNull final String name,
@NonNull final String message,
@NonNull final Severity severity,
@NonNull final StackTraceElement[] stacktrace) {
getClient().notify(name, message, stacktrace, new Callback() {
@Override
public void beforeNotify(@NonNull Report report) {
Error error = report.getError();
if (error != null) {
if (severity != null) {
error.setSeverity(severity);
}
error.getExceptions().setExceptionType("c");
}
}
});
}
}