55import android .app .ApplicationExitInfo ;
66import android .content .Context ;
77import android .os .Build ;
8+ import androidx .annotation .NonNull ;
89import androidx .annotation .RequiresApi ;
10+ import io .sentry .Attachment ;
911import io .sentry .DateUtils ;
1012import io .sentry .Hint ;
1113import io .sentry .ILogger ;
1214import io .sentry .IScopes ;
1315import io .sentry .Integration ;
16+ import io .sentry .SentryEnvelope ;
17+ import io .sentry .SentryEnvelopeItem ;
1418import io .sentry .SentryEvent ;
19+ import io .sentry .SentryItemType ;
1520import io .sentry .SentryLevel ;
1621import io .sentry .SentryOptions ;
1722import io .sentry .android .core .ApplicationExitInfoHistoryDispatcher .ApplicationExitInfoPolicy ;
@@ -180,37 +185,78 @@ public boolean shouldReportHistorical() {
180185 final long tombstoneTimestamp = exitInfo .getTimestamp ();
181186 event .setTimestamp (DateUtils .getDateTime (tombstoneTimestamp ));
182187
183- // Try to find and remove matching native event from outbox
184- final @ Nullable NativeEventData matchingNativeEvent =
185- nativeEventCollector .findAndRemoveMatchingNativeEvent (tombstoneTimestamp );
188+ final TombstoneHint tombstoneHint =
189+ new TombstoneHint (
190+ options .getFlushTimeoutMillis (), options .getLogger (), tombstoneTimestamp , enrich );
191+ final Hint hint = HintUtils .createWithTypeCheckHint (tombstoneHint );
186192
187- if (matchingNativeEvent != null ) {
193+ try {
194+ mergeWithMatchingNativeEvents (tombstoneTimestamp , event , hint );
195+ } catch (Throwable e ) {
188196 options
189197 .getLogger ()
190198 .log (
191- SentryLevel .DEBUG ,
192- "Found matching native event for tombstone, removing from outbox: %s" ,
193- matchingNativeEvent .getFile ().getName ());
199+ SentryLevel .WARNING ,
200+ "Failed to merge native event with tombstone, continuing without merge: %s" ,
201+ e .getMessage ());
202+ }
194203
195- // Delete from outbox so OutboxSender doesn't send it
196- boolean deletionSuccess = nativeEventCollector . deleteNativeEventFile ( matchingNativeEvent );
204+ return new ApplicationExitInfoHistoryDispatcher . Report ( event , hint , tombstoneHint );
205+ }
197206
198- if (deletionSuccess ) {
199- event = mergeNativeCrashes (matchingNativeEvent .getEvent (), event );
200- }
201- } else {
207+ private void mergeWithMatchingNativeEvents (
208+ long tombstoneTimestamp , SentryEvent event , Hint hint ) {
209+ // Try to find and remove matching native event from outbox
210+ final @ Nullable NativeEventData matchingNativeEvent =
211+ nativeEventCollector .findAndRemoveMatchingNativeEvent (tombstoneTimestamp );
212+
213+ if (matchingNativeEvent == null ) {
202214 options .getLogger ().log (SentryLevel .DEBUG , "No matching native event found for tombstone." );
215+ return ;
203216 }
204217
205- final TombstoneHint tombstoneHint =
206- new TombstoneHint (
207- options .getFlushTimeoutMillis (), options .getLogger (), tombstoneTimestamp , enrich );
208- final Hint hint = HintUtils .createWithTypeCheckHint (tombstoneHint );
218+ options
219+ .getLogger ()
220+ .log (
221+ SentryLevel .DEBUG ,
222+ "Found matching native event for tombstone, removing from outbox: %s" ,
223+ matchingNativeEvent .getFile ().getName ());
209224
210- return new ApplicationExitInfoHistoryDispatcher .Report (event , hint , tombstoneHint );
225+ // Delete from outbox so OutboxSender doesn't send it
226+ boolean deletionSuccess = nativeEventCollector .deleteNativeEventFile (matchingNativeEvent );
227+
228+ if (deletionSuccess ) {
229+ mergeNativeCrashes (matchingNativeEvent .getEvent (), event );
230+ addNativeAttachmentsToTombstoneHint (matchingNativeEvent , hint );
231+ }
232+ }
233+
234+ private void addNativeAttachmentsToTombstoneHint (
235+ @ NonNull NativeEventData matchingNativeEvent , Hint hint ) {
236+ @ NotNull SentryEnvelope nativeEnvelope = matchingNativeEvent .getEnvelope ();
237+ for (SentryEnvelopeItem item : nativeEnvelope .getItems ()) {
238+ try {
239+ @ Nullable String attachmentFileName = item .getHeader ().getFileName ();
240+ if (item .getHeader ().getType () != SentryItemType .Attachment
241+ || attachmentFileName == null ) {
242+ continue ;
243+ }
244+ hint .addAttachment (
245+ new Attachment (
246+ item .getData (),
247+ attachmentFileName ,
248+ item .getHeader ().getContentType (),
249+ item .getHeader ().getAttachmentType (),
250+ false ));
251+ } catch (Throwable e ) {
252+ options
253+ .getLogger ()
254+ .log (SentryLevel .DEBUG , "Failed to process envelope item: %s" , e .getMessage ());
255+ }
256+ }
211257 }
212258
213- private SentryEvent mergeNativeCrashes (
259+ private void mergeNativeCrashes (
214260 final @ NotNull SentryEvent nativeEvent , final @ NotNull SentryEvent tombstoneEvent ) {
215261 // we take the event data verbatim from the Native SDK and only apply tombstone data where we
216262 // are sure that it will improve the outcome:
@@ -236,8 +282,6 @@ private SentryEvent mergeNativeCrashes(
236282 nativeEvent .setDebugMeta (tombstoneDebugMeta );
237283 nativeEvent .setThreads (tombstoneThreads );
238284 }
239-
240- return nativeEvent ;
241285 }
242286 }
243287
0 commit comments