Skip to content

Commit

Permalink
Merge pull request #162 from bugsnag/releases/v2.2.0
Browse files Browse the repository at this point in the history
v2.2.0 Release
  • Loading branch information
lemnik committed Aug 3, 2022
2 parents ec25daa + 963067b commit 4e7e7c9
Show file tree
Hide file tree
Showing 44 changed files with 379 additions and 55 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# Changelog

## 2.2.0 (2022-08-03)

- Added `telemetry` option to `bugsnag.start` to allow sending of internal errors to be disabled.
- Update bugsnag-android from v5.23.1 to [v5.25.0](https://github.com/bugsnag/bugsnag-android/blob/master/CHANGELOG.md#5250-2022-07-19)
- Update bugsnag-cocoa from v6.18.1 to [v6.21.0](https://github.com/bugsnag/bugsnag-cocoa/blob/master/CHANGELOG.md#6210-2022-07-20)
- Fixed 'Unhandled Exception' in JSON encoding of metadata containing list objects
[#160](https://github.com/bugsnag/bugsnag-flutter/pull/160)
- Add specific handling for 'invalid Dart instruction address' native stack frames
[#161](https://github.com/bugsnag/bugsnag-flutter/pull/161)

## 2.1.1 (2022-06-28)

- Added `BugsnagFlutterConfiguration` to allow `bugsnag.attach` behaviour to be configured from native code.
Expand Down
8 changes: 5 additions & 3 deletions examples/native/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@
android:theme="@style/Theme.BugsnagFlutter"
android:name=".ExampleApp"
tools:targetApi="31">
<meta-data
android:name="com.bugsnag.android.API_KEY"
android:value="your-api-key-here" />

<activity
android:name=".MainActivity"
android:exported="true"
Expand All @@ -30,6 +28,10 @@
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize"
/>

<meta-data
android:name="com.bugsnag.android.API_KEY"
android:value="your-api-key-here" />
</application>

</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,20 @@ package com.example.bugsnag.flutter.android

import android.app.Application
import com.bugsnag.android.Bugsnag
import com.bugsnag.android.Configuration
import com.bugsnag.flutter.BugsnagFlutterConfiguration

class ExampleApp : Application() {
override fun onCreate() {
super.onCreate()

val config = Configuration.load(this)

// Add the names of Dart packages that should be displayed as "in-project" on your dashboard
config.projectPackages = setOf(packageName, "example_flutter")

// Start Bugsnag Android SDK
Bugsnag.start(this)
Bugsnag.start(this, config)

// Uncomment to disable automatic detection of Dart errors:
// BugsnagFlutterConfiguration.enabledErrorTypes.dartErrors = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,8 @@ class MainActivity : AppCompatActivity() {
fun showFlutterView(view: View) {
startActivity(FlutterActivity.createDefaultIntent(applicationContext))
}

fun unhandledException(view: View) {
throw RuntimeException("this is an unhandled crash")
}
}
15 changes: 13 additions & 2 deletions examples/native/android/app/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,27 @@
android:layout_height="match_parent">

<Button
android:id="@+id/button_first"
android:id="@+id/showFlutter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Show Flutter"
android:onClick="showFlutterView"
android:text="Show Flutter"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<Button
android:id="@+id/unhandledException"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:onClick="unhandledException"
android:text="Throw Unhandled Exception"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/showFlutter" />

</androidx.constraintlayout.widget.ConstraintLayout>

</androidx.coordinatorlayout.widget.CoordinatorLayout>
68 changes: 56 additions & 12 deletions examples/native/example_flutter/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,14 @@ class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);

@override
Widget build(BuildContext context) => const MaterialApp(
Widget build(BuildContext context) => MaterialApp(
title: 'Bugsnag Flutter Example',
home: ExampleHomeScreen(),
initialRoute: '/',
navigatorObservers: [BugsnagNavigatorObserver()],
routes: {
'/': (context) => const ExampleHomeScreen(),
'/login': (context) => LoginScreen(),
},
);
}

Expand Down Expand Up @@ -43,7 +48,7 @@ class ExampleHomeScreen extends StatelessWidget {
// Use leaveBreadcrumb() to log potentially useful events in order to
// understand what happened in your app before each error.
void _leaveBreadcrumb() async =>
bugsnag.leaveBreadcrumb('This is a custom breadcrumb',
bugsnag.leaveBreadcrumb('This is a custom breadcrumb from Flutter',
// Additional data can be attached to breadcrumbs as metadata
metadata: {'from': 'a', 'to': 'z'});

Expand Down Expand Up @@ -76,15 +81,6 @@ class ExampleHomeScreen extends StatelessWidget {
onPressed: _handledException,
child: const Text('Notify Handled Error'),
),
ElevatedButton(
child: const Text('Native Errors'),
onPressed: () {
Navigator.pushNamed(context, '/native-crashes');
},
style: ElevatedButton.styleFrom(
primary: Colors.redAccent.shade200,
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 16),
child: Text(
Expand All @@ -96,9 +92,57 @@ class ExampleHomeScreen extends StatelessWidget {
onPressed: _leaveBreadcrumb,
child: const Text('Leave a breadcrumb'),
),
ElevatedButton(
onPressed: () async {
final email = await Navigator.of(context).pushNamed('/login');
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text('User logged in as $email'),
));
},
child: const Text('Login (bugsnag.setUser)'),
),
],
),
),
);
}
}

class LoginScreen extends StatelessWidget {
final TextEditingController _email = TextEditingController();

LoginScreen({Key? key}) : super(key: key);

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Login'),
),
body: Center(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Column(
children: [
TextField(
controller: _email,
decoration: const InputDecoration(
labelText: 'Email Address',
),
),
ElevatedButton(
onPressed: () async {
bugsnag.setUser(email: _email.value.text);
bugsnag.leaveBreadcrumb('User has logged in');

Navigator.of(context).pop(_email.value.text);
},
child: const Text('Login'),
),
],
),
),
),
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@
name = "[CP-User] Run Flutter Build example_flutter Script";
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "set -e\nset -u\nsource \"${SRCROOT}/../example_flutter/.ios/Flutter/flutter_export_environment.sh\"\nexport VERBOSE_SCRIPT_LOGGING=1 && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/xcode_backend.sh build\n";
shellScript = "set -e\nset -u\nsource \"${SRCROOT}/../example_flutter/.ios/Flutter/flutter_export_environment.sh\"\nexport VERBOSE_SCRIPT_LOGGING=1 && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/xcode_backend.sh build";
};
E89B3AC476390C585D0BE274 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
Expand Down
3 changes: 3 additions & 0 deletions examples/native/ios/BugsnagFlutter/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ class AppDelegate: FlutterAppDelegate {
// Start Bugsnag iOS SDK
Bugsnag.start()

// Specify the names of Dart packages that should be displayed as "in-project" on your dashboard.
BugsnagFlutterConfiguration.projectPackages = ["example_flutter"];

// Uncomment to disable automatic detection of Dart errors:
// BugsnagFlutterConfiguration.enabledErrorTypes.dartErrors = false

Expand Down
13 changes: 11 additions & 2 deletions examples/native/ios/BugsnagFlutter/Base.lproj/Main.storyboard
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="19529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
Expand Down Expand Up @@ -30,13 +30,22 @@
<action selector="showFlutter" destination="BYZ-38-t0r" eventType="touchUpInside" id="lc4-pn-mps"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" ambiguous="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="uOG-q7-gNr">
<rect key="frame" x="138" y="471.5" width="141" height="31"/>
<state key="normal" title="Button"/>
<buttonConfiguration key="configuration" style="filled" title="Trigger Fatal Error"/>
<connections>
<action selector="unhandledError" destination="BYZ-38-t0r" eventType="touchUpInside" id="0Rr-LM-yLl"/>
</connections>
</button>
</subviews>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstItem="uQu-uc-Imx" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="1Ls-Rs-AB1"/>
<constraint firstItem="yfB-10-brY" firstAttribute="top" secondItem="6Tk-OE-BBY" secondAttribute="top" constant="16" id="4TH-EX-e1q"/>
<constraint firstItem="yfB-10-brY" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="Crp-8Q-lNX"/>
<constraint firstItem="uOG-q7-gNr" firstAttribute="top" secondItem="uQu-uc-Imx" secondAttribute="bottom" constant="8" id="cuh-Ib-eS8"/>
<constraint firstItem="uQu-uc-Imx" firstAttribute="centerY" secondItem="8bC-Xf-vdC" secondAttribute="centerY" id="pez-pw-KGy"/>
</constraints>
</view>
Expand Down
4 changes: 4 additions & 0 deletions examples/native/ios/BugsnagFlutter/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,8 @@ class ViewController: UIViewController {
let viewController = FlutterViewController(engine: flutterEngine, nibName: nil, bundle: nil)
present(viewController, animated: true, completion: nil)
}

@IBAction func unhandledError() {
fatalError("oops!")
}
}
3 changes: 0 additions & 3 deletions examples/native/ios/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@ target 'BugsnagFlutter' do
# Comment the next line if you don't want to use dynamic frameworks
use_frameworks!

# Pods for BugsnagFlutter
pod 'Bugsnag'

install_all_flutter_pods(flutter_application_path)
end

Expand Down
5 changes: 5 additions & 0 deletions features/breadcrumbs.feature
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,10 @@ Feature: Start Bugsnag from Flutter
And the error payload field "events.0.breadcrumbs.0.type" equals "state"
And the error payload field "events.0.breadcrumbs.1.metaData.foo" equals "bar"
And the error payload field "events.0.breadcrumbs.1.metaData.object.test" equals "hello"
And the error payload field "events.0.breadcrumbs.1.metaData.object.bool" is true
And the error payload field "events.0.breadcrumbs.1.metaData.object.number" equals 1234
And the error payload field "events.0.breadcrumbs.1.metaData.object.list.0" equals 'abc'
And the error payload field "events.0.breadcrumbs.1.metaData.object.list.1" equals 4321
And the error payload field "events.0.breadcrumbs.1.metaData.object.list.2" is true
And the error payload field "events.0.breadcrumbs.1.name" equals "Manual breadcrumb"
And the error payload field "events.0.breadcrumbs.1.type" equals "manual"
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
import com.bugsnag.flutter.BugsnagFlutterConfiguration;
import com.bugsnag.flutter.test.app.scenario.Scenario;

import org.json.JSONException;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
Expand Down Expand Up @@ -136,7 +138,7 @@ private void runScenario(@NonNull MethodCall call, @NonNull MethodChannel.Result
if (scenario != null) {
// we push all scenarios to the main thread to stop Flutter catching the exceptions
mainHandler.post(() -> {
scenario.run(call.argument("extraConfig"));
scenario.run(context, call);
result.success(null);
});
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package com.bugsnag.flutter.test.app.scenario;

import androidx.annotation.Nullable;
import android.content.Context;

import io.flutter.plugin.common.MethodCall;

public class NativeCrashScenario extends Scenario {
@Override
public void run(@Nullable String extraConfig) {
public void run(Context context, MethodCall call) {
throw new RuntimeException("crash from Java");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.bugsnag.flutter.test.app.scenario;

import android.content.Context;

import com.bugsnag.android.Bugsnag;
import com.bugsnag.android.Configuration;
import com.bugsnag.android.EndpointConfiguration;

import java.util.LinkedHashSet;
import java.util.Objects;
import java.util.Set;

import io.flutter.plugin.common.MethodCall;

public class NativeProjectPackagesScenario extends Scenario {
@Override
public void run(Context context, MethodCall call) {

Configuration configuration = Configuration.load(context);
configuration.setApiKey("abc12312312312312312312312312312");
configuration.setEndpoints(new EndpointConfiguration(
Objects.requireNonNull(call.argument("notifyEndpoint")),
Objects.requireNonNull(call.argument("sessionEndpoint"))));

Set<String> projectPackages = new LinkedHashSet<>();
projectPackages.add("test_package");
projectPackages.add("MazeRunner");
projectPackages.add("com.bugsnag.flutter.test.app");
configuration.setProjectPackages(projectPackages);

Bugsnag.start(context, configuration);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.bugsnag.flutter.test.app.scenario;

import androidx.annotation.Nullable;
import android.content.Context;

import io.flutter.plugin.common.MethodCall;

public abstract class Scenario {
public abstract void run(@Nullable String extraConfig);
public abstract void run(Context context, MethodCall call);
}

0 comments on commit 4e7e7c9

Please sign in to comment.