Реализация Java в приложениях Flutter

Flutter имеет богатый набор пакетов и виджетов. Вы можете добиться большинства вещей, используя богатый пул виджетов, который предлагает Flutter, или используя пакет.

Однако иногда вы можете оказаться в ситуациях, требующих написания собственного кода Java *.

В этой четвертой части нашей серии статей о Flutter мы рассмотрим, как можно написать код Java, который взаимодействует с вашим приложением Flutter.

* Примечание: Flutter также позволяет писать другие типы нативного кода (Obj-C, Swift), но в этом руководстве мы сосредоточимся на Java.

Основы

Flutter позволяет отправлять сообщения между разными платформами через канал платформы. Сообщение отправляется в операционную систему хоста, которая затем отправляет ответ Flutter. В этой транзакции Flutter является клиентом, а собственный код - хостом. Эта транзакция работает асинхронно и возвращает Future, как мы сейчас увидим.

На стороне клиента (Flutter) мы должны определить MethodChannel, целью которого является взаимодействие с плагинами платформы с помощью вызовов асинхронных методов. Имя, данное этому каналу, совпадает с каналом, который мы должны объявить в коде Java. В противном случае связь не удастся.

В Java мы объявляем это как CHANNEL. Важно отметить, что Flutter и Java имеют разные типы данных. Процесс передачи сериализации данных и десериализации типов данных выполняется автоматически.

Вызов кода Android с использованием каналов платформы

Разобравшись с основами, давайте рассмотрим два примера, которые покажут вам, как можно вызывать код Android с помощью каналов платформы. Первый пример, над которым мы будем работать, - это вызов PowerManager для отображения атрибутов, зависящих от мощности. После этого мы увидим, как вы можете запустить камеру во Flutter с помощью кода Android.

Android Power Manager

Давайте реализуем класс PowerManager, который дает вам контроль над состоянием питания устройства. Класс можно найти здесь:



На момент написания этой статьи языком по умолчанию для файла MainActivity является Kotlin. Следовательно, при создании приложения вам необходимо явно заявить, что вы хотите использовать Java.

flutter create -i objc -a java native_code

Мы собираемся реализовать функцию isDeviceIdleMode, которая возвращает истину, если устройство находится в режиме ожидания.

Чтобы это работало, нам нужно импортировать пакеты services и async:

import ‘package:flutter/services.dart’;
import ‘dart:async’;

Затем мы определяем MethodChannel.. Вы можете выбрать любое имя, только убедитесь, что вы используете то же имя, что и в коде Java:

static const platformMethodChannel =
const MethodChannel(‘heartbeat.fritz.ai/native’);

Теперь давайте определим функцию, которая будет обрабатывать связь между хостом и Flutter. Как упоминалось ранее, это процесс async, поэтому мы определяем функцию, которая возвращает Future.

Мы заключаем эту функцию в оператор try-catch, чтобы мы могли отловить любые возможные ошибки. Затем нам нужно вызвать метод, который будет находиться в нашем коде Android. Мы делаем это с помощью platformMethodChannel.invokeMethod:

Future<Null> _managePower() async {
String _message;
try {
final String result =
await platformMethodChannel.invokeMethod(‘powerManage’);
_message = result;
} on PlatformException catch (e) {
_message = “Can’t do native stuff ${e.message}.”;
}
setState(() {
nativeMessage = _message;
});
}

Мы запускаем эту функцию при нажатии значка питания в приложении:

FlatButton.icon(
icon: Icon(
Icons.power_settings_new,
size: 100,
),
label: Text(‘’),
textColor: Colors.white,
onPressed: _managePower,
),

Затем мы отобразим полученный ответ в виде текста:

Text(
nativeMessage,
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w500,
fontSize: 23.0),
)

Вот полный файл Dart для справки:

Сторона Android

В mainActivity.java определите CHANNEL с тем же именем, что и во Flutter. mainActivity.java находится в папке Android:

private static final String CHANNEL = “heartbeat.fritz.ai/native”;

Затем определите MethodChannel и установите MethodCallHandler. Обратите внимание на преобразование логического значения в строку, чтобы избежать ошибок типа на стороне Flutter:

new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL)
.setMethodCallHandler((call, result) -> {
if (call.method.equals(“powerManage”)) {
boolean deviceStatus = getDeviceStatus();
String myMessage = Boolean.toString(deviceStatus);
result.success(myMessage);
}
});

Затем мы должны реализовать функцию powerManager, которая будет вызываться:

private boolean getDeviceStatus() {
boolean deviceStatus = false;
if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
deviceStatus = powerManager.isDeviceIdleMode();
}
return deviceStatus;
}

Вот полный mainActivity.java код:

Запуск камеры с помощью собственного кода

Давайте теперь посмотрим, как мы можем использовать наш недавно приобретенный набор навыков для запуска камеры с использованием собственного кода.

Наш основной файл Dart останется прежним. Мы просто немного изменим имена переменных и значок:

В MainActivity мы определим channel с тем же именем, что и имя, которое мы определили в файле Dart. Затем мы создадим MethodChannel и setMethodCallHandler:

public class MainActivity extends FlutterActivity {
private static final String CHANNEL = “heartbeat.fritz.ai/native”;
@Override
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
GeneratedPluginRegistrant.registerWith(flutterEngine);
new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL)
.setMethodCallHandler((call, result) -> {
if (call.method.equals(“takePhoto”)) {
readyCamera();
}
});
}
public void readyCamera() {
Intent intent = new Intent(“android.media.action.IMAGE_CAPTURE”);
startActivity(intent);
}
}

Далее мы определяем функцию, которая будет запускать камеру. Используем Intent для запуска камеры.

На этом этапе вы можете получить такую ​​ошибку:

Эту проблему можно решить, установив правильные разрешения в файле манифеста Android.

<uses-feature
android:name=”android.hardware.camera.any”
android:required=”true” />

Исходный код

Вот репо с исходным кодом:



Последние мысли

В этой статье мы увидели, как писать собственный код Java в ваших приложениях Flutter. При написании кода на Swift, Kotlin и Objective-C используется аналогичный подход.

Чтобы получить полное руководство для всех платформ, ознакомьтесь с официальной документацией.



Примечание редактора. Heartbeat - это онлайн-публикация и сообщество, созданное авторами и посвященное предоставлению первоклассных образовательных ресурсов для специалистов по науке о данных, машинному обучению и глубокому обучению. Мы стремимся поддерживать и вдохновлять разработчиков и инженеров из всех слоев общества.

Являясь независимой редакцией, Heartbeat спонсируется и публикуется Comet, платформой MLOps, которая позволяет специалистам по данным и группам машинного обучения отслеживать, сравнивать, объяснять и оптимизировать свои эксперименты. Мы платим участникам и не продаем рекламу.

Если вы хотите внести свой вклад, отправляйтесь на наш призыв к участникам. Вы также можете подписаться на наши еженедельные информационные бюллетени (Deep Learning Weekly и Comet Newsletter), присоединиться к нам в » «Slack и подписаться на Comet в Twitter и LinkedIn для получения ресурсов, событий и гораздо больше, что поможет вам быстрее создавать лучшие модели машинного обучения.