24 lectures on how to learn and use Flutter quickly--20 Security: Flutter implements tools to achieve online security and stability

In this class, a general Flutter exception reporting module will be implemented to provide reporting and monitoring security for online operations. Secondly, the Sentry platform will be used to implement exception alarm and management functions. Let’s first take a look at what the online security of the App includes.

Online security operations

When launching each client version, we must have a crash standard. Since the client cannot be rolled back after it is released, data needs to be used to assist judgment when publishing. Here we need to use the crash rate to assist in judging whether it is necessary. Further grayscale more users. To do this, you need to report abnormal client error reports to the platform. Both Android and iOS have similar functional modules. The corresponding theoretical methods are also introduced on the Flutter official website . You can go to the official website to learn more. The purpose of writing this column is to use this function as a common module and practice the process.

Next, let's take a look at how to use the theoretical knowledge of the official website to encapsulate this function into a general exception reporting module.

Universal reporting module

According to the documentation on the official website, we divide the process into three steps:

  1. Modify the main function in main.dart;

  2. Exception catching;

  3. Capture content reporting.

Next, we will look at the implementation principles of the three processes respectively.

Step 1: Modify the main function in main.dart

In the main function of our previous project code logic, the following code method is used to start and run the Flutter project.

/// App 核心入口文件 
void main() { 
  runApp(MyApp()); 
}

Since we need to catch exceptions, we put the runApp execution into the exception capture module and modify it as follows.

import 'package:two_you_friend/util/tools/app_sentry.dart'; 
/// App 核心入口文件 
void main() { 
  AppSentry.runWithCatchError(MyApp()); 
}

A general exception capture module is introduced here. You can also use this module directly to implement reporting in your project later. Next, let's take a look at the exception capture logic implemented by AppSentry.

Step 2: Exception catching

The implementation of this function will apply to two knowledge points: FlutterError and runZonedGuarded.

In Flutter, FlutterError can be used to capture errors during runtime, including during construction, layout and drawing.

runZonedGuarded uses Zone.fork to create a new area to run the code logic, that is, runApp. When an error is encountered, its callback function onError will be executed. Secondly, if Zone.current.handleUncaughtError is used in the project, the error will also be thrown. Execute onError logic, let's look at the code specifically, as follows:

/// catch 组件异常 
/// 
/// 开发模式下,本地打印,上线时则调用 sentry 平台 
static void runWithCatchError(Widget appMain) { 
  // 捕获并上报 Flutter 异常 
  FlutterError.onError = (FlutterErrorDetails details) async { 
    if (!inProduction) { 
      FlutterError.dumpErrorToConsole(details); 
    } else { 
      Zone.current.handleUncaughtError(details.exception, details.stack); 
    } 
  }; 
  runZonedGuarded<Future<Null>>(() async { 
    runApp(appMain); 
  }, (error, stackTrace) async { 
    await _reportError(error, stackTrace); 
  }); 
}

FlutterError.onError is used to catch exceptions. It will be judged whether it is in a formal environment. If so, the error log will be printed locally. If not, the runZonedGuarded onError logic will be executed. RunApp is executed in the runZonedGuarded code. When an exception is encountered, _reportError is called to implement error reporting. Next, let's take a look at the implementation part of _reportError.

Step 3: Report exceptions

The specific exception information of the client has been obtained above. Next, we use the Sentry platform to report the exception information. Before applying the Sentry platform, you need to apply for access. The specific access method is introduced in "Sentry Platform" in this lesson. After successfully accessing the Sentry platform, a dsn will be provided. Here we need to configure it in the file, as shown in the following code. Because Sentry is a third-party library, you need to add library dependencies to pubspec.yaml and update the local library.

/// 创建 SentryClient 用于将异常日志上报给 sentry 平台 
final SentryClient _sentry = SentryClient( 
  dsn: 'https://[email protected]/5362342', 
); 
/// 判断当前环境类型 
const bool inProduction = bool.fromEnvironment("dart.vm.product");

_sentry is the reporting handle created using the Sentry third-party library, and dsn is the reporting identifier for our test. Please apply for it yourself when testing, otherwise you will not be able to see your own exception reporting content. In the above code, inProduction is the logic used to obtain whether it is a formal environment. Next, let’s take a look at the reporting logic. The code is as follows:

/// 上报异常的函数 
static Future<void> _reportError(dynamic error, dynamic stackTrace) async { 
  if (!inProduction) { // 判断是否为正式环境 
    print(stackTrace); 
  } 
  // sentry 上报 
  final SentryResponse response = await _sentry.captureException( 
    exception: error, 
    stackTrace: stackTrace, 
  ); 
  if (response.isSuccessful) { 
    print('Success! Event ID: ${response.eventId}'); 
  } else { 
    print('Failed to report to Sentry.io: ${response.error}'); 
  } 
}

First, determine whether it is a formal environment. If not, print it directly. You can also use the following code to print local logs. If it is a formal environment, use _sentry.captureException to report the exception, and finally print whether the execution is successful. The latter paragraph can be removed, mainly for viewing during real machine debugging.

FlutterError.dumpErrorToConsole(FlutterErrorDetails(exception: error));

The above completes the code of the universal reporting tool. Next, we will teach you how to register Sentry and create a project to obtain a dsn.

Sentry Platform

Let’s take a look at the specific creation steps:

1. Create a registered account and go to the official website . Please fill in the details according to your own information. After the registration is completed, log in directly;

2. Create a project. If there are no groups in this process, you will be asked to fill in the groups. Just fill in the groups as required;

3. Report for testing. There will be examples of various SDKs, but there is no Flutter. You can ignore it and enter the project or personal page directly. You can see the interface as shown in Figure 1.

image.png

Figure 1 Sentry Platform

4. Follow the method in Figure 2 to see the dsn we need. If it is newly registered, you can click Setup Sentry in Figure 2 to quickly find it;

image (1).png

Figure 2 dsn query guide

5. Replace the dsn in the project code.

After the above 5 steps, the project access can be completed. Next, we will verify whether the report is normal.

Report test

In order to verify this function, we need to specifically modify the normal code to make it abnormal. Here we modify the code in the "Image Flow" menu on the left as follows:

Widget build(BuildContext context) { 
  if (contentList == null) { // 判断是否为空 
    return Loading(); 
  } 
  List<StructContentDetail> tmpList = []; 
  return ListView.separated( 
    scrollDirection: Axis.vertical, 
    shrinkWrap: true, 
    itemCount: contentList.length + 1, // 增加异常 
    ......

The above is only part of the code in pages/home_page/img_flow.dart. Line 10 of the code adds an exception. Since the array length exceeds the limit, this will cause an array boundary exception to be thrown in ListView.separated. Please note that this exception catching logic will only take effect in release mode, so you need to formally build the app. Using the knowledge from the previous lesson, we will build the App as an apk file and then install it on the Android phone.

After successful installation, open the App and select "Image Stream" from the left menu. At this time, you will see an exception in the interface. After about 1-2 minutes, we go to the Sentry platform and select our creation project. You will see Figure 3 below. content to be reported.

image (2).png

Figure 3 Sentry exception example

Click on the specific report content to see the detailed error information. The error file and specific function have been described, and the call stack has been printed. You can view the specific error file img_flow.dart and the specific error content RangeError in the prompt message. Through the file and error details, you can easily locate the specific problem.

The above is the tool module for exception reporting. In this way, we can quickly collect and solve problems. Since main.dart has been optimized in this lesson, the reconstruction part is also introduced here.

AppProvider

In order to lighten the code in main.dart and make it more streamlined, we moved the logic of the Provider part into a new tool module, which is located in util/tools/app_provider. In main.dart, the original _getProviders method inside the function was changed to calling the getProviders method in AppProvider. The main.dart code is as follows:

/// App 核心入口文件 
void main() { 
  AppSentry.runWithCatchError(MyApp()); 
} 
/// MyApp 核心入口界面 
class MyApp extends StatelessWidget { 
  // This widget is the root of your application. 
  @override 
  Widget build(BuildContext context) { 
    return FutureBuilder<Widget>( 
        future: AppProvider.getProviders( 
          context, 
          MaterialApp( 
              title: 'Two You', // APP 名字 
              debugShowCheckedModeBanner: false, 
              theme: ThemeData( 
                primarySwatch: Colors.blue, // App 主题 
              ), 
              routes: Router().registerRouter(), 
              home: Entrance()), 
        ), 
        builder: (BuildContext context, AsyncSnapshot<Widget> snapshot) { 
          if (snapshot.error != null) { 
            return Container( 
              child: CommonError(), 
            ); 
          } 
          return Container( 
            child: snapshot.data, 
          ); 
        }); 
  } 
}

The code is very streamlined. The calling method is modified in line 12 of the code, and component exception handling is added in line 23. The getProviders method in AppProvider is the logic of the original homepage, which is basically unchanged. You can check it out by yourself in the github source code .

Summarize

This lesson focuses on the implementation method of the general reporting module, and also introduces the application of the Sentry platform in practice. Finally, it briefly introduces the reconstruction logic in main.dart. After completing this course, you will need to master Flutter exception capture and processing methods, and be able to use the Sentry platform to assist in analyzing exception problems.

In the next lesson we will move to the next stage and we will continue to improve the functionality on the Two You App.

Click this link to view the source code of this lesson

Guess you like

Origin blog.csdn.net/g_z_q_/article/details/129718940