Реализация 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 для получения ресурсов, событий и гораздо больше, что поможет вам быстрее создавать лучшие модели машинного обучения.