mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Reporting back native stacktrace to dart side for crash reporting. (flutter/engine#20280)
* Add native stacktrace on iOS * Add native stacktrace on Android * format and changing naming to errorWithCode on iOS * reformat * Remove stacktrace from decodeEnvelope, not needed. * Separate encodeErrorEnvelopeWithStacktrace with original encode function * Add unit tests * re-format * change comments for stacktrace * Remove changes for iOS Co-authored-by: Ben Li <libe@google.com>
This commit is contained in:
parent
3c1d67e975
commit
38ad113515
@ -70,6 +70,17 @@ public final class JSONMethodCodec implements MethodCodec {
|
||||
.put(JSONUtil.wrap(errorDetails)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer encodeErrorEnvelopeWithStacktrace(
|
||||
String errorCode, String errorMessage, Object errorDetails, String errorStacktrace) {
|
||||
return JSONMessageCodec.INSTANCE.encodeMessage(
|
||||
new JSONArray()
|
||||
.put(errorCode)
|
||||
.put(JSONUtil.wrap(errorMessage))
|
||||
.put(JSONUtil.wrap(errorDetails))
|
||||
.put(JSONUtil.wrap(errorStacktrace)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object decodeEnvelope(ByteBuffer envelope) {
|
||||
try {
|
||||
|
||||
@ -11,6 +11,9 @@ import androidx.annotation.UiThread;
|
||||
import io.flutter.BuildConfig;
|
||||
import io.flutter.plugin.common.BinaryMessenger.BinaryMessageHandler;
|
||||
import io.flutter.plugin.common.BinaryMessenger.BinaryReply;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
@ -247,8 +250,16 @@ public class MethodChannel {
|
||||
});
|
||||
} catch (RuntimeException e) {
|
||||
Log.e(TAG + name, "Failed to handle method call", e);
|
||||
reply.reply(codec.encodeErrorEnvelope("error", e.getMessage(), null));
|
||||
reply.reply(
|
||||
codec.encodeErrorEnvelopeWithStacktrace(
|
||||
"error", e.getMessage(), null, getStackTrace(e)));
|
||||
}
|
||||
}
|
||||
|
||||
private String getStackTrace(Exception e) {
|
||||
Writer result = new StringWriter();
|
||||
e.printStackTrace(new PrintWriter(result));
|
||||
return result.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,6 +55,20 @@ public interface MethodCodec {
|
||||
*/
|
||||
ByteBuffer encodeErrorEnvelope(String errorCode, String errorMessage, Object errorDetails);
|
||||
|
||||
/**
|
||||
* Encodes an error result into a binary envelope message with the native stacktrace.
|
||||
*
|
||||
* @param errorCode An error code String.
|
||||
* @param errorMessage An error message String, possibly null.
|
||||
* @param errorDetails Error details, possibly null. Consider supporting {@link Throwable} in your
|
||||
* codec. This is the most common value passed to this field.
|
||||
* @param errorStacktrace Platform stacktrace for the error. possibly null.
|
||||
* @return a {@link ByteBuffer} containing the encoding between position 0 and the current
|
||||
* position.
|
||||
*/
|
||||
ByteBuffer encodeErrorEnvelopeWithStacktrace(
|
||||
String errorCode, String errorMessage, Object errorDetails, String errorStacktrace);
|
||||
|
||||
/**
|
||||
* Decodes a result envelope from binary.
|
||||
*
|
||||
|
||||
@ -79,6 +79,24 @@ public final class StandardMethodCodec implements MethodCodec {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer encodeErrorEnvelopeWithStacktrace(
|
||||
String errorCode, String errorMessage, Object errorDetails, String errorStacktrace) {
|
||||
final ExposedByteArrayOutputStream stream = new ExposedByteArrayOutputStream();
|
||||
stream.write(1);
|
||||
messageCodec.writeValue(stream, errorCode);
|
||||
messageCodec.writeValue(stream, errorMessage);
|
||||
if (errorDetails instanceof Throwable) {
|
||||
messageCodec.writeValue(stream, getStackTrace((Throwable) errorDetails));
|
||||
} else {
|
||||
messageCodec.writeValue(stream, errorDetails);
|
||||
}
|
||||
messageCodec.writeValue(stream, errorStacktrace);
|
||||
final ByteBuffer buffer = ByteBuffer.allocateDirect(stream.size());
|
||||
buffer.put(stream.buffer(), 0, stream.size());
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object decodeEnvelope(ByteBuffer envelope) {
|
||||
envelope.order(ByteOrder.nativeOrder());
|
||||
|
||||
@ -7,6 +7,7 @@ import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.junit.Test;
|
||||
@ -89,4 +90,27 @@ public class StandardMethodCodecTest {
|
||||
"at io.flutter.plugin.common.StandardMethodCodecTest.encodeErrorEnvelopeWithThrowableTest(StandardMethodCodecTest.java:"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void encodeErrorEnvelopeWithStacktraceTest() {
|
||||
final Exception e = new IllegalArgumentException("foo");
|
||||
final ByteBuffer buffer =
|
||||
StandardMethodCodec.INSTANCE.encodeErrorEnvelopeWithStacktrace(
|
||||
"code", e.getMessage(), e, "error stacktrace");
|
||||
assertNotNull(buffer);
|
||||
buffer.flip();
|
||||
buffer.order(ByteOrder.nativeOrder());
|
||||
final byte flag = buffer.get();
|
||||
final Object code = StandardMessageCodec.INSTANCE.readValue(buffer);
|
||||
final Object message = StandardMessageCodec.INSTANCE.readValue(buffer);
|
||||
final Object details = StandardMessageCodec.INSTANCE.readValue(buffer);
|
||||
final Object stacktrace = StandardMessageCodec.INSTANCE.readValue(buffer);
|
||||
assertEquals("code", (String) code);
|
||||
assertEquals("foo", (String) message);
|
||||
String stack = (String) details;
|
||||
assertTrue(
|
||||
stack.contains(
|
||||
"at io.flutter.plugin.common.StandardMethodCodecTest.encodeErrorEnvelopeWithStacktraceTest(StandardMethodCodecTest.java:"));
|
||||
assertEquals("error stacktrace", (String) stacktrace);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user