# Integrating with Other Code

Flutter stands out for creating visually appealing apps across multiple platforms with a single codebase. However, developers often face situations where Flutter needs to interact with platform-specific code or native libraries.&#x20;

This integration is crucial for accessing device capabilities or incorporating existing native code into Flutter apps. Let's explore how Flutter achieves this seamless integration.

## Platform Channels: Bridging Dart and Native Code

Platform channels are the primary way Flutter communicates with native code. This method is essential when your app needs to use device-specific features not available in Flutter's framework, such as accessing battery level, using Bluetooth, or implementing a native third-party SDK.

### How Platform Channels Work

Platform channels use a simple yet powerful system for message passing. You define a channel in your Dart code and specify how it communicates with the native side of your app, whether it's written in Kotlin/Java for Android or Swift/Objective-C for iOS.

<figure><img src="https://docs.flutter.dev/assets/images/docs/arch-overview/platform-channels.png" alt="" width="563"><figcaption><p>Platform channel diagram from official flutter documentation.</p></figcaption></figure>

#### **Dart Side:**

You initiate communication with a method call over the channel, specifying the method name and any arguments.

```dart
const channel = MethodChannel('com.example/battery');
final batteryLevel = await channel.invokeMethod('getBatteryLevel');
```

#### **Native Side (Kotlin for Android example):**

You respond to these method calls on the native side, implementing the logic required and returning the result back to Dart.

```kotlin
MethodChannel(flutterEngine.dartExecutor, "com.example/battery").setMethodCallHandler {
    call, result ->
    if (call.method == "getBatteryLevel") {
        val batteryLevel = getBatteryLevel()
        result.success(batteryLevel)
    } else {
        result.notImplemented()
    }
}
```

This two-way communication channel allows Flutter apps to utilize native features and libraries seamlessly.

## Foreign Function Interface (FFI): Direct Native Code Invocation

For direct interaction with C-based libraries, Flutter offers the Foreign Function Interface (FFI). This interface is more direct and often faster than platform channels because it allows Dart code to call C functions directly, without the need for message serialization.

### C Function Example

Imagine we have a C function that multiplies two numbers.

```c
// multiply.c
#include <stdint.h>

int32_t multiply(int32_t x, int32_t y) {
    return x * y;
}
```

### Compiling C Code to a Library

You compile this C code into a shared library (`libmultiply.so` or `libmultiply.dylib`), depending on your operating system.

### Dart FFI with Typedef

In Dart, you use `dart:ffi` to interoperate with this C function. First, define the `typedef`s matching the C function signature, then load the library and call the function.

```dart
import 'dart:ffi';
import 'package:ffi/ffi.dart';

// Typedefs for the C function
typedef MultiplyC = Int32 Function(Int32 x, Int32 y);
typedef MultiplyDart = int Function(int x, int y);

void main() {
  // Load the shared library
  final dylib = DynamicLibrary.open('libmultiply.so'); // Adjust the library name as needed

  // Get a reference to the multiply function
  final MultiplyDart multiply = dylib
      .lookupFunction<MultiplyC, MultiplyDart>('multiply');

  // Call the C function from Dart
  final result = multiply(4, 5);
  print('4 * 5 = $result');
}
```

In this streamlined example, `DynamicLibrary.open` loads the compiled C library, `lookupFunction` maps the `multiply` C function to a callable Dart function, and then you can use `multiply` just like any Dart function. This demonstrates the basic steps for integrating C code into a Dart (Flutter) application using FFI and `typedef` for clear and type-safe function signatures.

This approach is particularly useful for CPU-intensive tasks like image processing, cryptographic operations, or direct interaction with native system APIs.

## Rendering Native Controls within Flutter Widgets

In some cases, you might want to display native Android or iOS controls within your Flutter app. Flutter accommodates this through platform views (`AndroidView` and `UiKitView`), allowing you to embed native components directly within your Flutter widget tree.

### Implementing Platform Views

You can use `AndroidView` or `UiKitView` widgets to embed native components. This method is typically used for complex controls that would be impractical to recreate in Flutter, such as a web view or a map view.

```dart
Widget build(BuildContext context) {
  return Platform.isAndroid 
    ? AndroidView(viewType: 'native-view')
    : UiKitView(viewType: 'native-view');
}
```

While powerful, platform views should be used judiciously due to their performance implications, as they introduce overhead in rendering and event handling.

## Embedding Flutter in Existing Applications

Conversely, Flutter allows embedding its content into existing Android or iOS applications. This feature is invaluable for gradually migrating an existing app to Flutter or adding new Flutter-based features to an established app.

### Integrating Flutter Modules

To integrate Flutter into an existing app, you create a Flutter module and include it in your Android or iOS project. This process involves configuring the native project to host Flutter content, ensuring a smooth user experience and performance.

```kotlin
// Android example
val flutterFragment = FlutterFragment.createDefault()
supportFragmentManager
    .beginTransaction()
    .add(R.id.flutter_container, flutterFragment)
    .commit()
```

This flexibility enables developers to leverage Flutter's productivity and UI capabilities without rewriting their entire application.

## Key Takeaways

* **Platform Channels** offer a flexible way to communicate between Dart and native code, enabling Flutter apps to use native features.
* **Foreign Function Interface (FFI)** provides direct access to C functions from Dart, suitable for performance-critical native operations.
* **Platform Views** allow embedding native Android and iOS controls within Flutter apps, useful for complex native components.
* **Flutter Integration in Native Apps** enables adding Flutter modules to existing Android or iOS applications, facilitating gradual migration or feature enhancement.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://flutteruniversity.gitbook.io/docs/learn-flutter/professional/flutter-architecture/integrating-with-other-code.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
