io.flutter.run.daemon.DaemonEvent.java Source code

Java tutorial

Introduction

Here is the source code for io.flutter.run.daemon.DaemonEvent.java

Source

/*
 * Copyright 2017 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
package io.flutter.run.daemon;

import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSyntaxException;
import com.intellij.openapi.diagnostic.Logger;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
 * <p>A message received from a Flutter process that's not in response to a particular request.
 *
 * <p>The protocol is specified in
 * <a href="https://github.com/flutter/flutter/wiki/The-flutter-daemon-mode"
 * >The Flutter Daemon Mode</a>.
 */
abstract class DaemonEvent {

    /**
     * Parses an event and sends it to the listener.
     */
    static void dispatch(@NotNull JsonObject obj, @NotNull Listener listener) {
        final JsonPrimitive primEvent = obj.getAsJsonPrimitive("event");
        if (primEvent == null) {
            LOG.error("Missing event field in JSON from flutter process: " + obj);
            return;
        }

        final String eventName = primEvent.getAsString();
        if (eventName == null) {
            LOG.error("Unexpected event field in JSON from flutter process: " + obj);
            return;
        }

        final JsonObject params = obj.getAsJsonObject("params");
        if (params == null) {
            LOG.error("Missing parameters in event from flutter process: " + obj);
            return;
        }

        final DaemonEvent event = create(eventName, params);
        if (event == null) {
            return; // Drop unknown event.
        }

        event.accept(listener);
    }

    private static @Nullable DaemonEvent create(@NotNull String eventName, @NotNull JsonObject params) {
        try {
            switch (eventName) {
            case "daemon.logMessage":
                return GSON.fromJson(params, LogMessage.class);
            case "app.start":
                return GSON.fromJson(params, AppStarting.class);
            case "app.debugPort":
                return GSON.fromJson(params, AppDebugPort.class);
            case "app.started":
                return GSON.fromJson(params, AppStarted.class);
            case "app.log":
                return GSON.fromJson(params, AppLog.class);
            case "app.progress":
                return GSON.fromJson(params, AppProgress.class);
            case "app.stop":
                return GSON.fromJson(params, AppStopped.class);
            case "device.added":
                return GSON.fromJson(params, DeviceAdded.class);
            case "device.removed":
                return GSON.fromJson(params, DeviceRemoved.class);
            default:
                return null; // Drop an unknown event.
            }
        } catch (JsonSyntaxException e) {
            LOG.error("Unexpected parameters in event from flutter process: " + params);
            return null;
        }
    }

    abstract void accept(Listener listener);

    @Override
    public String toString() {
        return GSON.toJson(this, getClass());
    }

    /**
     * Receives events from a Flutter daemon process.
     */
    interface Listener {

        // process lifecycle

        default void processWillTerminate() {
        }

        default void processTerminated() {
        }

        // daemon domain

        default void onDaemonLogMessage(LogMessage event) {
        }

        // app domain

        default void onAppStarting(AppStarting event) {
        }

        default void onAppDebugPort(AppDebugPort event) {
        }

        default void onAppStarted(AppStarted event) {
        }

        default void onAppLog(AppLog event) {
        }

        default void onAppProgressStarting(AppProgress event) {
        }

        default void onAppProgressFinished(AppProgress event) {
        }

        default void onAppStopped(AppStopped event) {
        }

        // device domain

        default void onDeviceAdded(DeviceAdded event) {
        }

        default void onDeviceRemoved(DeviceRemoved event) {
        }
    }

    // daemon domain

    @SuppressWarnings("unused")
    static class LogMessage extends DaemonEvent {
        // "event":"daemon.eventLogMessage"
        String level;
        String message;
        String stackTrace;

        void accept(Listener listener) {
            listener.onDaemonLogMessage(this);
        }
    }

    // app domain

    @SuppressWarnings("unused")
    static class AppStarting extends DaemonEvent {
        // "event":"app.start"
        String appId;
        String deviceId;
        String directory;
        boolean supportsRestart;

        void accept(Listener listener) {
            listener.onAppStarting(this);
        }
    }

    @SuppressWarnings("unused")
    static class AppDebugPort extends DaemonEvent {
        // "event":"app.eventDebugPort"
        String appId;
        // port seems to be deprecated
        // int port;
        String wsUri;
        String baseUri;

        void accept(Listener listener) {
            listener.onAppDebugPort(this);
        }
    }

    @SuppressWarnings("unused")
    static class AppStarted extends DaemonEvent {
        // "event":"app.started"
        String appId;

        void accept(Listener listener) {
            listener.onAppStarted(this);
        }
    }

    @SuppressWarnings("unused")
    static class AppLog extends DaemonEvent {
        // "event":"app.log"
        String appId;
        String log;
        boolean error;

        void accept(Listener listener) {
            listener.onAppLog(this);
        }
    }

    @SuppressWarnings("unused")
    static class AppProgress extends DaemonEvent {
        // "event":"app.progress"

        // (technically undocumented)
        String appId;
        String id;

        /**
         * Undocumented, optional field; seems to be a progress event subtype.
         * See <a href="https://github.com/flutter/flutter/search?q=startProgress+progressId">code</a>.
         */
        private String progressId;

        String message;

        private Boolean finished;

        @NotNull
        String getType() {
            return progressId == null ? "" : progressId;
        }

        boolean isStarting() {
            return !isFinished();
        }

        boolean isFinished() {
            return finished != null && finished;
        }

        void accept(Listener listener) {
            if (isStarting()) {
                listener.onAppProgressStarting(this);
            } else {
                listener.onAppProgressFinished(this);
            }
        }
    }

    @SuppressWarnings("unused")
    static class AppStopped extends DaemonEvent {
        // "event":"app.stop"
        String appId;

        void accept(Listener listener) {
            listener.onAppStopped(this);
        }
    }

    // device domain

    static class DeviceAdded extends DaemonEvent {
        // "event":"device.added"
        String id;
        String name;
        String platform;
        boolean emulator;

        void accept(Listener listener) {
            listener.onDeviceAdded(this);
        }
    }

    @SuppressWarnings("unused")
    static class DeviceRemoved extends DaemonEvent {
        // "event":"device.removed"
        String id;
        String name;
        String platform;
        boolean emulator;

        void accept(Listener listener) {
            listener.onDeviceRemoved(this);
        }
    }

    private static final Gson GSON = new Gson();
    private static final Logger LOG = Logger.getInstance(DaemonEvent.class.getName());
}