-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #4 from loup-v/upgrade_project
Upgrade to flutter 1.12 structure.
- Loading branch information
Showing
71 changed files
with
919 additions
and
677 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,8 +3,5 @@ | |
|
||
.packages | ||
.pub/ | ||
pubspec.lock | ||
|
||
build/ | ||
|
||
.idea/workspace.xml |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# This file tracks properties of this Flutter project. | ||
# Used by Flutter tool to assess capabilities and perform upgrades etc. | ||
# | ||
# This file should be version controlled and should not be manually edited. | ||
|
||
version: | ||
revision: 9f5ff2306bb3e30b2b98eee79cd231b1336f41f4 | ||
channel: stable | ||
|
||
project_type: plugin |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,4 @@ | ||
org.gradle.jvmargs=-Xmx1536M | ||
android.enableR8=true | ||
android.useAndroidX=true | ||
android.enableJetifier=true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
distributionBase=GRADLE_USER_HOME | ||
distributionPath=wrapper/dists | ||
zipStoreBase=GRADLE_USER_HOME | ||
zipStorePath=wrapper/dists | ||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" | ||
package="io.intheloup.streamschannel"> | ||
package="app.loup.streams_channel"> | ||
</manifest> |
200 changes: 200 additions & 0 deletions
200
android/src/main/java/app/loup/streams_channel/StreamsChannel.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,200 @@ | ||
// Copyright (c) 2018 Loup Inc. | ||
// Licensed under Apache License v2.0 | ||
|
||
package app.loup.streams_channel; | ||
|
||
import android.annotation.SuppressLint; | ||
import android.util.Log; | ||
|
||
import androidx.annotation.UiThread; | ||
|
||
import java.nio.ByteBuffer; | ||
import java.util.concurrent.ConcurrentHashMap; | ||
import java.util.concurrent.atomic.AtomicBoolean; | ||
|
||
import io.flutter.plugin.common.BinaryMessenger; | ||
import io.flutter.plugin.common.BinaryMessenger.BinaryMessageHandler; | ||
import io.flutter.plugin.common.BinaryMessenger.BinaryReply; | ||
import io.flutter.plugin.common.EventChannel; | ||
import io.flutter.plugin.common.MethodCall; | ||
import io.flutter.plugin.common.MethodCodec; | ||
import io.flutter.plugin.common.StandardMethodCodec; | ||
|
||
/** | ||
* Inspired from https://github.com/flutter/engine/blob/master/shell/platform/android/io/flutter/plugin/common/EventChannel.java | ||
*/ | ||
public final class StreamsChannel { | ||
|
||
public interface StreamHandlerFactory { | ||
EventChannel.StreamHandler create(Object arguments); | ||
} | ||
|
||
private static final String TAG = "StreamsChannel#"; | ||
|
||
private final BinaryMessenger messenger; | ||
private final String name; | ||
private final MethodCodec codec; | ||
|
||
public StreamsChannel(BinaryMessenger messenger, String name) { | ||
this(messenger, name, StandardMethodCodec.INSTANCE); | ||
} | ||
|
||
public StreamsChannel(BinaryMessenger messenger, String name, MethodCodec codec) { | ||
if (BuildConfig.DEBUG) { | ||
if (messenger == null) { | ||
Log.e(TAG, "Parameter messenger must not be null."); | ||
} | ||
if (name == null) { | ||
Log.e(TAG, "Parameter name must not be null."); | ||
} | ||
if (codec == null) { | ||
Log.e(TAG, "Parameter codec must not be null."); | ||
} | ||
} | ||
this.messenger = messenger; | ||
this.name = name; | ||
this.codec = codec; | ||
} | ||
|
||
@UiThread | ||
public void setStreamHandlerFactory(final StreamHandlerFactory factory) { | ||
messenger.setMessageHandler(name, factory == null ? null : new IncomingStreamRequestHandler(factory)); | ||
} | ||
|
||
private final class IncomingStreamRequestHandler implements BinaryMessageHandler { | ||
private final StreamHandlerFactory factory; | ||
private final ConcurrentHashMap<Integer, Stream> streams = new ConcurrentHashMap<>(); | ||
|
||
IncomingStreamRequestHandler(StreamHandlerFactory factory) { | ||
this.factory = factory; | ||
} | ||
|
||
@Override | ||
public void onMessage(ByteBuffer message, final BinaryReply reply) { | ||
final MethodCall call = codec.decodeMethodCall(message); | ||
final String[] methodParts = call.method.split("#"); | ||
|
||
if (methodParts.length != 2) { | ||
reply.reply(null); | ||
return; | ||
} | ||
|
||
final int id; | ||
try { | ||
id = Integer.parseInt(methodParts[1]); | ||
} catch (NumberFormatException e) { | ||
reply.reply(codec.encodeErrorEnvelope("error", e.getMessage(), null)); | ||
return; | ||
} | ||
|
||
final String method = methodParts[0]; | ||
switch (method) { | ||
case "listen": | ||
onListen(id, call.arguments, reply); | ||
break; | ||
case "cancel": | ||
onCancel(id, call.arguments, reply); | ||
break; | ||
default: | ||
reply.reply(null); | ||
break; | ||
} | ||
} | ||
|
||
private void onListen(int id, Object arguments, BinaryReply callback) { | ||
final Stream stream = new Stream(new EventSinkImplementation(id), factory.create(arguments)); | ||
final Stream oldStream = streams.putIfAbsent(id, stream); | ||
|
||
if (oldStream != null) { | ||
// Repeated calls to onListen may happen during hot restart. | ||
// We separate them with a call to onCancel. | ||
try { | ||
oldStream.handler.onCancel(null); | ||
} catch (RuntimeException e) { | ||
logError(id, "Failed to close existing event stream", e); | ||
} | ||
} | ||
|
||
try { | ||
stream.handler.onListen(arguments, stream.sink); | ||
callback.reply(codec.encodeSuccessEnvelope(null)); | ||
} catch (RuntimeException e) { | ||
streams.remove(id); | ||
logError(id, "Failed to open event stream", e); | ||
callback.reply(codec.encodeErrorEnvelope("error", e.getMessage(), null)); | ||
} | ||
} | ||
|
||
private void onCancel(int id, Object arguments, BinaryReply callback) { | ||
final Stream oldStream = streams.remove(id); | ||
|
||
if (oldStream != null) { | ||
try { | ||
oldStream.handler.onCancel(arguments); | ||
callback.reply(codec.encodeSuccessEnvelope(null)); | ||
} catch (RuntimeException e) { | ||
logError(id, "Failed to close event stream", e); | ||
callback.reply(codec.encodeErrorEnvelope("error", e.getMessage(), null)); | ||
} | ||
} else { | ||
callback.reply(codec.encodeErrorEnvelope("error", "No active stream to cancel", null)); | ||
} | ||
} | ||
|
||
private void logError(int id, String message, Throwable e) { | ||
Log.e(TAG + name, String.format("%s [id=%d]", message, id), e); | ||
} | ||
|
||
private final class EventSinkImplementation implements EventChannel.EventSink { | ||
|
||
final int id; | ||
final String name; | ||
final AtomicBoolean hasEnded = new AtomicBoolean(false); | ||
|
||
@SuppressLint("DefaultLocale") | ||
private EventSinkImplementation(int id) { | ||
this.id = id; | ||
this.name = String.format("%s#%d", StreamsChannel.this.name, id); | ||
} | ||
|
||
@Override | ||
@UiThread | ||
public void success(Object event) { | ||
if (hasEnded.get() || streams.get(id).sink != this) { | ||
return; | ||
} | ||
StreamsChannel.this.messenger.send(name, codec.encodeSuccessEnvelope(event)); | ||
} | ||
|
||
@Override | ||
@UiThread | ||
public void error(String errorCode, String errorMessage, Object errorDetails) { | ||
if (hasEnded.get() || streams.get(id).sink != this) { | ||
return; | ||
} | ||
StreamsChannel.this.messenger.send( | ||
name, | ||
codec.encodeErrorEnvelope(errorCode, errorMessage, errorDetails)); | ||
} | ||
|
||
@Override | ||
@UiThread | ||
public void endOfStream() { | ||
if (hasEnded.getAndSet(true) || streams.get(id).sink != this) { | ||
return; | ||
} | ||
StreamsChannel.this.messenger.send(name, null); | ||
} | ||
} | ||
} | ||
|
||
private static class Stream { | ||
final EventChannel.EventSink sink; | ||
final EventChannel.StreamHandler handler; | ||
|
||
private Stream(EventChannel.EventSink sink, EventChannel.StreamHandler handler) { | ||
this.sink = sink; | ||
this.handler = handler; | ||
} | ||
} | ||
} |
Oops, something went wrong.