Last updated:
0 purchases
flight recorder
Delivering rich, cost-effective, in-context video of your users' experiences on your app. With just a shake, screenshot, or tap.
Install #
Run this command:
$ flutter pub add flight_recorder
copied to clipboard
Alternatively, add flight_recorder as a dependency in your pubspec.yaml file.
Head over to our main documentation to learn how to integrate and customise FlightRecorder, or read on here for a quick start.
Required Changes to Android Project #
Make the following updates to your android project:
Update MainActivity to extend FlutterFragmentActivity #
In order for the screen recording to work, the MainActivity needs to extend FlutterFragmentActivity rather than FlutterActivity. Update the code as follows:
Open your Flutter app in your coding editor.
Open the file at ./android/app/src/main/kotlin/{your app path}/MainActivity.kt.
Replace the line import io.flutter.embedding.android.FlutterActivitywith import io.flutter.embedding.android.FlutterFragmentActivity.
import io.flutter.embedding.android.FlutterFragmentActivity // ← Update
class MainActivity: FlutterActivity() {
// ...
copied to clipboard
Replace class MainActivity: FlutterActivity() { with class MainActivity: FlutterFragmentActivity().
import io.flutter.embedding.android.FlutterFragmentActivity
class MainActivity: FlutterFragmentActivity() { // ← Update
// ...
copied to clipboard
Update the minSdkVersion and compileSdkVersion #
flight_recorder is compatible only from version 21 of Android SDK, the required compileSdkVersion is 34. Update these settings as follows:
Open the file at ./android/app/build.gradle.
Locate the android section, and inside there, the defaultConfig section.
Replace the line minSdkVersion flutter.minSdkVersion with minSdkVersion 21, as per the following code snippet:
// ...
android {
// ...
default {
// ...
minSdkVersion 21 // ← Update the minSdkVersion
targetSdkVersion flutter.targetSdkVersion
// ...
copied to clipboard
Insert the line compileSdkVersion 34 underneath minSdkVersion 21 as follows:
// ...
android {
// ...
default {
// ...
minSdkVersion 21
compileSdkVersion 34 // ← Insert the compileSdkVersion
targetSdkVersion flutter.targetSdkVersion
// ...
copied to clipboard
Add Proguard rules #
Add the following to your proguard rules
-keepclassmembers class * extends com.google.protobuf.GeneratedMessageLite {
<fields>;
}
copied to clipboard
If you do not have a proguard-rules.pro file, create one in the following folder
android/app/proguard-rules.pro
copied to clipboard
Configure #
Open the file ./lib/main.dart, or the file which contains the runApp method call.
Locate the main() function. Locate the runApp method call, and the Widget which is passed in, for example, MyApp, App etc. We refer to this as the ROOT WIDGET. If this widget is one you have declared inside your own code, move on to step 3. Continue reading this step if your main() function directly returns a third party widget such as this example returning MaterialApp:
void main() {
runApp(const MaterialApp(
title: 'Navigation Basics',
home: FirstRoute(),
));
}
copied to clipboard
You must first extract MaterialApp into its own Widget. You can use VSCode and the Refactor menu to easily achieve this task.
Place the cursor in the Widget's symbol, e.g. MaterialApp, pull up the Refactor menu, and select Extract Widget. Type RootWidget or a name of your choosing, and press Enter.
Here is what our example now looks like:
void main() {
runApp(RootWidget());
}
class RootWidget extends StatelessWidget {
const RootWidget({
super.key,
});
@override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'Navigation Basics',
home: FirstRoute(),
);
}
}
copied to clipboard
We refer to RootWidget (or whatever you named your Widget), as ROOT WIDGET in the remainder of this tutorial.
Go to the class declaration of the ROOT WIDGET. This may be in a different file.
If your ROOT WIDGET is App, this will look like one of the following:
class App extends StatelessWidget {
copied to clipboard
or
class App extends StatefulWidget {
copied to clipboard
Add the following import statements at the top of the file containing the class declaration of the ROOT WIDGET:
import 'package:flight_recorder/flight_recorder.dart';
import 'package:flight_recorder/screen_recorder.dart';
copied to clipboard
If the ROOT WIDGET class extends StatefulWidget, move on to the step Option 1: Adding the SDK to a Stateful Root Widget.
If the class extends StatelessWidget, move on to the step Option 2: Adding the SDK to a Stateful Root Widget.
Option 1: Adding the SDK to a Stateful Root Widget #
Make sure you have followed the instructions at the top of the Launch FlightRecorder in your Flutter App section before following these instructions.
These instructions are for those projects where the main() function's runApp method call returns a widget which extends StatefulWidget. We refer to this widget as the ROOT WIDGET.
Open the file containing to the class declaration of the ROOT WIDGET. This is probably ./lib/main.dart.
Locate the implementation of createState() in the ROOT WIDGET class. If your ROOT WIDGET is MyApp, this might look like this:
@override
State<MyApp> createState() => _MyAppState();
copied to clipboard
Identiy the name of the class returned by the createState(). We refer to this as {ROOT WIDGET STATE SUBCLASS}. Go to the class declaration of the {ROOT WIDGET STATE SUBCLASS}. In our example, this is:
class _MyAppState extends State<MyAppState> {
copied to clipboard
Inside the {ROOT WIDGET STATE SUBCLASS}, create the final _flightRecorderPlugin constant, and set it to FlightRecorder() as shown below in our example:
class _MyAppState extends State<MyAppState> {
final _flightRecorderPlugin = FlightRecorder(); // ← Add this constant
// ...
copied to clipboard
Inside the {ROOT WIDGET STATE SUBCLASS}, implement initState as shown below, which initializes FlightRecorder. Replace YOUR_API_KEY with your projects API Key.
class _MyAppState extends State<MyAppState> {
final _flightRecorderPlugin = FlightRecorder();
// ↓ Add this block
@override
void initState() {
_flightRecorderPlugin.initFlightRecorder('YOUR_API_KEY', true); // ← Replace with your own API Key
super.initState();
}
// ...
copied to clipboard
Inside the {ROOT WIDGET STATE SUBCLASS}, locate the build() method. The build() method returns an instance of a Widget.
You will need to wrap the returned widget with the ScreenRecorder widget. The ScreenRecorder widget has a flightRecorderPlugin property, which you will set to the _flightRecorderPlugin, and the child property which you will set to return the widget originally returned by the build() method.
You can use VSCode and the Refactor menu to easily achieve this task. We will follow through an example, shown below, which returns a single widget, via MyWidget(). Whatever your app returns from your build() method, the principles remain the same.
@override
Widget build(BuildContext context) {
return MyWidget();
}
copied to clipboard
Place your cursor on the symbol after the return statement (MyWidget in our example), pull up the Refactor menu, and select Wrap with widget.... Type ScreenRecorder, and press Enter. Here is what our example looks like, yours should also have the ScreenRecorder widget returned, and the original widget set to the value of the child property:
@override
Widget build(BuildContext context) {
return ScreenRecorder(
child: MyWidget(),
);
}
copied to clipboard
Insert a newline after the line return ScreenRecorder( and then insert flightRecorderPlugin: _flightRecorderPlugin, as shown below:
@override
Widget build(BuildContext context) {
return ScreenRecorder(
flightRecorderPlugin: _flightRecorderPlugin, // ← Insert this line
child: MyWidget(),
);
}
copied to clipboard
You have finished! Run the app and you can shake or take a screenshot to capture the video content and send a report.
Option 2: Adding the SDK to a Stateless Root Widget #
Make sure you have followed the instructions at the top of the Launch FlightRecorder in your Flutter App section before following these instructions.
These instructions are for those projects where the main() function's runApp method call returns a widget which extends StatelessWidget. We refer to this wiget as the ROOT WIDGET.
Open the file containing to the class declaration of the ROOT WIDGET. This is probably ./lib/main.dart.
Locate the declaration of the ROOT WIDGET class. If your ROOT WIDGET is MyApp, this might look like this:
class MyApp extends StatelessWidget {
copied to clipboard
Inside the ROOT WIDGET class, below the const {ROOT WIDGET}({super.key}) declaration, create a reference to flightRecorderPlugin as shown below, where ROOT WIDGET is MyApp.
class MyApp extends StatelessWidget {
const MyApp({
super.key,
});
final FlightRecorder flightRecorderPlugin; // ← Insert
// ...
copied to clipboard
Inside the same class, add the required this.flightRecorderPlugin property to the ROOT WIDGET function call:
class MyApp extends StatelessWidget {
const MyApp({
super.key,
required this.flightRecorderPlugin, // ← Insert
});
final FlightRecorder flightRecorderPlugin;
// ..
copied to clipboard
Go to the main() method. Update the call to your Widget (e.g. MyApp()), to pass in the property flightRecorderPlugin set to FlightRecorder() as per the below example:
void main() {
runApp(RootWidget(
flightRecorderPlugin: FlightRecorder(), // ← Insert
));
}
copied to clipboard
Inside the ROOT WIDGET class, below the flightRecorderPlugin declaration, insert the createElement override as shown below, replacing YOUR_API_KEY with the API Key for your project:
class MyApp extends StatelessWidget {
const MyApp({
super.key,
required this.flightRecorderPlugin,
});
final FlightRecorder flightRecorderPlugin;
// ↓ Add this block
@override
StatelessElement createElement() {
flightRecorderPlugin.initFlightRecorder('YOUR_API_KEY', true);
return super.createElement();
}
// ...
copied to clipboard
Inside the same class, find the build() method. The build() method returns an instance of a Widget.
You will need to wrap the returned widget with the ScreenRecorder widget. The ScreenRecorder widget has a flightRecorderPlugin property, which you will set to the flightRecorderPlugin, and the child property which you will set to return the widget originally returned by the build() method.
You can use VSCode and the Refactor menu to easily achieve this task. We will follow through an example, shown below, which returns a single widget, via MyWidget(). Whatever your app returns from your build() method, the principles remain the same.
@override
Widget build(BuildContext context) {
return MyWidget();
}
copied to clipboard
Place your cursor on the symbol after the return statement (MyWidget in our example), pull up the Refactor menu, and select Wrap with widget.... Type ScreenRecorder, and press Enter. Here is what our example looks like, yours should also have the ScreenRecorder widget returned, and the original widget set to the value of the child property:
@override
Widget build(BuildContext context) {
return ScreenRecorder(
child: MyWidget(),
);
}
copied to clipboard
Insert a newline after the code ScreenRecorder( and insert the flightRecorderPlugin: flightRecorderPlugin, line as shown below:
@override
Widget build(BuildContext context) {
return ScreenRecorder(
flightRecorderPlugin: flightRecorderPlugin, // ← Insert this line
child: MyWidget(),
);
}
copied to clipboard
You have finished! Run the app and you can shake or take a screenshot to capture the video content and send a report.
If you are running on iOS, you need to use a real device to see the screen recording. An Error: Unexpected Error with an error code of 260 will appear when shaking on an iOS simulator. On Android you can use an emulator or a real device.
For personal and professional use. You cannot resell or redistribute these repositories in their original state.
There are no reviews.