Commit 77ef993a authored by Jidong Chen's avatar Jidong Chen

init

parents
## 0.0.1
* TODO: Describe initial release.
The MIT License (MIT)
Copyright (c) 2019 Alibaba Group
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<p align="center">
<img src="flutter_boost.png">
<b></b><br>
<a href="README_CN.md">中文文档</a>
<br><br>
</p>
# FlutterBoost
A next-generation Flutter-Native hybrid solution. FlutterBoost is a Flutter plugin which enables hybrid integration of Flutter for your existing native apps with minimum efforts.The philosophy of FlutterBoost is to use Flutter as easy as using a WebView. Managing Native pages and Flutter pages at the same time is non-trivial in an existing App. FlutterBoost takes care of page resolution for you. The only thing you need to care about is the name of the page(usually could be an URL). 
<a name="bf647454"></a>
# Prerequisites
You need to add Flutter to your project before moving on.
# Getting Started
## Add a dependency in you Flutter project.
Open you pubspec.yaml and add the following line to dependencies:
Before release 1.0
```java
flutter_boost: 0.0.34
```
After Release 1.0
```java
flutter_boost: ^0.0.39
```
## Integration with Flutter code.
Add init code to you App
```dart
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
void initState() {
super.initState();
///register page widget builders,the key is pageName
FlutterBoost.singleton.registerPageBuilders({
'sample://firstPage': (pageName, params, _) => FirstRouteWidget(),
'sample://secondPage': (pageName, params, _) => SecondRouteWidget(),
});
///query current top page and load it
FlutterBoost.handleOnStartPage();
}
@override
Widget build(BuildContext context) => MaterialApp(
title: 'Flutter Boost example',
builder: FlutterBoost.init(), ///init container manager
home: Container());
}
```
## Integration with iOS code.
Use FLBFlutterAppDelegate as the superclass of your AppDelegate
```objc
@interface AppDelegate : FLBFlutterAppDelegate <UIApplicationDelegate>
@end
```
Implement FLBPlatform protocol methods for your App.
```objc
@interface DemoRouter : NSObject<FLBPlatform>
@property (nonatomic,strong) UINavigationController *navigationController;
+ (DemoRouter *)sharedRouter;
@end
@implementation DemoRouter
- (void)openPage:(NSString *)name
params:(NSDictionary *)params
animated:(BOOL)animated
completion:(void (^)(BOOL))completion
{
if([params[@"present"] boolValue]){
FLBFlutterViewContainer *vc = FLBFlutterViewContainer.new;
[vc setName:name params:params];
[self.navigationController presentViewController:vc animated:animated completion:^{}];
}else{
FLBFlutterViewContainer *vc = FLBFlutterViewContainer.new;
[vc setName:name params:params];
[self.navigationController pushViewController:vc animated:animated];
}
}
- (void)closePage:(NSString *)uid animated:(BOOL)animated params:(NSDictionary *)params completion:(void (^)(BOOL))completion
{
FLBFlutterViewContainer *vc = (id)self.navigationController.presentedViewController;
if([vc isKindOfClass:FLBFlutterViewContainer.class] && [vc.uniqueIDString isEqual: uid]){
[vc dismissViewControllerAnimated:animated completion:^{}];
}else{
[self.navigationController popViewControllerAnimated:animated];
}
}
@end
```
Initialize FlutterBoost with FLBPlatform at the beginning of your App.
```objc
[FlutterBoostPlugin.sharedInstance startFlutterWithPlatform:router
onStart:^(FlutterViewController *fvc) {
}];
```
## Integration with Android code.
Init FlutterBoost in Application.onCreate() 
```java
public class MyApplication extends FlutterApplication {
@Override
public void onCreate() {
super.onCreate();
FlutterBoostPlugin.init(new IPlatform() {
@Override
public Application getApplication() {
return MyApplication.this;
}
/**
* get the main activity, this activity should always at the bottom of task stack.
*/
@Override
public Activity getMainActivity() {
return MainActivity.sRef.get();
}
@Override
public boolean isDebug() {
return false;
}
/**
* start a new activity from flutter page, you may need a activity router.
*/
@Override
public boolean startActivity(Context context, String url, int requestCode) {
return PageRouter.openPageByUrl(context,url,requestCode);
}
@Override
public Map getSettings() {
return null;
}
});
}
```
# Basic Usage
## Concepts
All page routing requests are being sent to the native router. Native router communicates with Native Container Manager, Native Container Manager takes care of building and destroying of Native Containers. 
## Use Flutter Boost Native Container to show a Flutter page in native code.
iOS
```objc
FLBFlutterViewContainer *vc = FLBFlutterViewContainer.new;
[vc setName:name params:params];
[self.navigationController presentViewController:vc animated:animated completion:^{}];
```
Android
```java
public class FlutterPageActivity extends BoostFlutterActivity {
@Override
public void onRegisterPlugins(PluginRegistry registry) {
//register flutter plugins
GeneratedPluginRegistrant.registerWith(registry);
}
@Override
public String getContainerName() {
//specify the page name register in FlutterBoost
return "sample://firstPage";
}
@Override
public Map getContainerParams() {
//params of the page
Map<String,String> params = new HashMap<>();
params.put("key","value");
return params;
}
}
```
or
```java
public class FlutterFragment extends BoostFlutterFragment {
@Override
public void onRegisterPlugins(PluginRegistry registry) {
GeneratedPluginRegistrant.registerWith(registry);
}
@Override
public String getContainerName() {
return "sample://firstPage";
}
@Override
public Map getContainerParams() {
Map<String,String> params = new HashMap<>();
params.put("key","value");
return params;
}
}
```
## Use Flutter Boost to open a page in dart code.
Dart
```objc
FlutterBoost.singleton.openPage("pagename", {}, true);
```
## Use Flutter Boost to close a page in dart code.
```objc
FlutterBoost.singleton.closePageForContext(context);
```
# Running the Demo
Please see the example for details.
# License
This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details
# Acknowledgments
* Flutter
<p align="center">
<img src="flutter_boost.png">
</p>
# FlutterBoost
新一代Flutter-Native混合解决方案。 FlutterBoost是一个Flutter插件,它可以轻松地为现有原生应用程序提供Flutter混合集成方案。FlutterBoost的理念是将Flutter像Webview那样来使用。在现有应用程序中同时管理Native页面和Flutter页面并非易事。 FlutterBoost帮你处理页面的映射和跳转,你只需关心页面的名字和参数即可(通常可以是URL)。
# 前置条件
在继续之前,您需要将Flutter集成到你现有的项目中。
# 安装
## 在Flutter项目中添加依赖项。
打开pubspec.yaml并将以下行添加到依赖项:
Release 1.0 之前的版本
```JSON
flutter_boost:0.0.34
```
1.0之后版本
```
flutter_boost:^ 0.0.39
```
## Dart代码的集成
将init代码添加到App App
```dart
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
void initState() {
super.initState();
///register page widget builders,the key is pageName
FlutterBoost.singleton.registerPageBuilders({
'sample://firstPage': (pageName, params, _) => FirstRouteWidget(),
'sample://secondPage': (pageName, params, _) => SecondRouteWidget(),
});
///query current top page and load it
FlutterBoost.handleOnStartPage();
}
@override
Widget build(BuildContext context) => MaterialApp(
title: 'Flutter Boost example',
builder: FlutterBoost.init(), ///init container manager
home: Container());
}
```
## iOS代码集成。
使用FLBFlutterAppDelegate作为AppDelegate的超类
```objectivec
@interface AppDelegate : FLBFlutterAppDelegate <UIApplicationDelegate>
@end
```
为您的应用程序实现FLBPlatform协议方法。
```objectivec
@interface DemoRouter : NSObject<FLBPlatform>
@property (nonatomic,strong) UINavigationController *navigationController;
+ (DemoRouter *)sharedRouter;
@end
@implementation DemoRouter
- (void)openPage:(NSString *)name
params:(NSDictionary *)params
animated:(BOOL)animated
completion:(void (^)(BOOL))completion
{
if([params[@"present"] boolValue]){
FLBFlutterViewContainer *vc = FLBFlutterViewContainer.new;
[vc setName:name params:params];
[self.navigationController presentViewController:vc animated:animated completion:^{}];
}else{
FLBFlutterViewContainer *vc = FLBFlutterViewContainer.new;
[vc setName:name params:params];
[self.navigationController pushViewController:vc animated:animated];
}
}
- (void)closePage:(NSString *)uid animated:(BOOL)animated params:(NSDictionary *)params completion:(void (^)(BOOL))completion
{
FLBFlutterViewContainer *vc = (id)self.navigationController.presentedViewController;
if([vc isKindOfClass:FLBFlutterViewContainer.class] && [vc.uniqueIDString isEqual: uid]){
[vc dismissViewControllerAnimated:animated completion:^{}];
}else{
[self.navigationController popViewControllerAnimated:animated];
}
}
@end
```
在应用程序开头使用FLBPlatform初始化FlutterBoost。
```的ObjectiveC
[FlutterBoostPlugin.sharedInstance startFlutterWithPlatform:router
onStart:^(FlutterViewController * fvc){
}];
```
## Android代码集成。
在Application.onCreate()中初始化FlutterBoost
```java
public class MyApplication extends FlutterApplication {
@Override
public void onCreate() {
super.onCreate();
FlutterBoostPlugin.init(new IPlatform() {
@Override
public Application getApplication() {
return MyApplication.this;
}
/**
* get the main activity, this activity should always at the bottom of task stack.
*/
@Override
public Activity getMainActivity() {
return MainActivity.sRef.get();
}
@Override
public boolean isDebug() {
return false;
}
/**
* start a new activity from flutter page, you may need a activity router.
*/
@Override
public boolean startActivity(Context context, String url, int requestCode) {
return PageRouter.openPageByUrl(context,url,requestCode);
}
@Override
public Map getSettings() {
return null;
}
});
}
```
# 基本用法
## 概念
所有页面路由请求都将发送到Native路由器。Native路由器与Native Container Manager通信,Native Container Manager负责构建和销毁Native Containers。
## 使用Flutter Boost Native Container用Native代码打开Flutter页面。
```objc
FLBFlutterViewContainer *vc = FLBFlutterViewContainer.new;
[vc setName:name params:params];
[self.navigationController presentViewController:vc animated:animated completion:^{}];
```
Android
```java
public class FlutterPageActivity extends BoostFlutterActivity {
@Override
public void onRegisterPlugins(PluginRegistry registry) {
//register flutter plugins
GeneratedPluginRegistrant.registerWith(registry);
}
@Override
public String getContainerName() {
//specify the page name register in FlutterBoost
return "sample://firstPage";
}
@Override
public Map getContainerParams() {
//params of the page
Map<String,String> params = new HashMap<>();
params.put("key","value");
return params;
}
}
```
或者用Fragment
```java
public class FlutterFragment extends BoostFlutterFragment {
@Override
public void onRegisterPlugins(PluginRegistry registry) {
GeneratedPluginRegistrant.registerWith(registry);
}
@Override
public String getContainerName() {
return "sample://firstPage";
}
@Override
public Map getContainerParams() {
Map<String,String> params = new HashMap<>();
params.put("key","value");
return params;
}
}
```
## 使用Flutter Boost在dart代码打开页面。
Dart
```java
FlutterBoost.singleton.openPage("pagename", {}, true);
```
## 使用Flutter Boost在dart代码关闭页面。
```java
FlutterBoost.singleton.closePageForContext(context);
```
# Examples
更详细的使用例子请参考Demo
# 作者
阿里巴巴闲鱼终端团队
# 许可证
该项目根据MIT许可证授权 - 有关详细信息,请参阅[LICENSE.md](LICENSE.md)文件
<a name="Acknowledgments"> </a>
# 致谢
- Flutter
*.iml
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.idea
.DS_Store
/build
/captures
GitCommitRecord.txt
group 'com.taobao.idlefish.flutterboost'
version '1.0-SNAPSHOT'
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.1.2'
}
}
rootProject.allprojects {
repositories {
google()
jcenter()
}
}
apply plugin: 'com.android.library'
android {
compileSdkVersion 26
buildToolsVersion "26.0.2"
defaultConfig {
minSdkVersion 16
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
lintOptions {
disable 'InvalidPackage'
}
}
dependencies {
implementation 'com.alibaba:fastjson:1.2.41'
implementation 'com.android.support:support-v4:26.1.0'
implementation 'com.android.support:appcompat-v7:26.1.0'
provided rootProject.findProject(":xservice_kit")
}
ext {
groupId = 'com.taobao.fleamarket'
artifactId = "FlutterBoost"
}
org.gradle.jvmargs=-Xmx1536M
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
#!/usr/bin/env sh
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
rootProject.name = 'flutter_boost'
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.taobao.idlefish.flutterboost">
<application
android:allowBackup="false">
<activity
android:name="com.taobao.idlefish.flutterboost.BoostFlutterActivity"
android:launchMode="standard"
android:screenOrientation="portrait"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize"/>
</application>
</manifest>
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Alibaba Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.taobao.idlefish.flutterboost;
import android.content.Context;
import io.flutter.view.FlutterNativeView;
public class BoostFlutterNativeView extends FlutterNativeView {
public BoostFlutterNativeView(Context context) {
super(context);
}
@Override
public void detach() {
//do nothing...
}
@Override
public void destroy() {
//do nothing...
}
public void boostDestroy() {
super.destroy();
}
}
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Alibaba Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.taobao.idlefish.flutterboost;
import android.content.Context;
import android.graphics.Bitmap;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.SurfaceHolder;
import android.view.View;
import com.taobao.idlefish.flutterboost.NavigationService.NavigationService;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import io.flutter.view.FlutterNativeView;
import io.flutter.view.FlutterView;
public class BoostFlutterView extends FlutterView {
private boolean mFirstFrameCalled = false;
private boolean mResumed = false;
private BoostCallback mBoostCallback;
public BoostFlutterView(Context context, AttributeSet attrs, FlutterNativeView nativeView) {
super(context, attrs, nativeView);
super.addFirstFrameListener(new FirstFrameListener() {
@Override
public void onFirstFrame() {
mFirstFrameCalled = true;
}
});
try {
Field field = FlutterView.class.getDeclaredField("mSurfaceCallback");
field.setAccessible(true);
SurfaceHolder.Callback cb = (SurfaceHolder.Callback)field.get(this);
getHolder().removeCallback(cb);
mBoostCallback = new BoostCallback(cb);
getHolder().addCallback(mBoostCallback);
}catch (Throwable t){
Debuger.exception(t);
}
}
@Override
public void onStart() {
//do nothing...
}
@Override
public void onPostResume() {
//do nothing...
}
@Override
public void onPause() {
//do nothing...
}
@Override
public void onStop() {
//do nothing...
}
@Override
public FlutterNativeView detach() {
//do nothing...
return getFlutterNativeView();
}
@Override
public void destroy() {
//do nothing...
}
@Override
public Bitmap getBitmap() {
if(getFlutterNativeView() == null || !getFlutterNativeView().isAttached()) {
Debuger.exception("FlutterView not attached!");
return null;
}
return super.getBitmap();
}
public boolean firstFrameCalled() {
return mFirstFrameCalled;
}
public void boostResume() {
if (!mResumed) {
mResumed = true;
super.onPostResume();
Debuger.log("resume flutter view");
}
}
public void boostStop() {
if (mResumed) {
super.onStop();
Debuger.log("stop flutter view");
mResumed = false;
}
}
public boolean isResumed() {
return mResumed;
}
public void boostDestroy() {
super.destroy();
}
public void scheduleFrame(){
if (mResumed) {
Map<String,String> map = new HashMap<>();
map.put("type","scheduleFrame");
NavigationService.getService().emitEvent(map);
}
}
class BoostCallback implements SurfaceHolder.Callback {
final SurfaceHolder.Callback mCallback;
BoostCallback(SurfaceHolder.Callback cb){
this.mCallback = cb;
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
//Debuger.log("flutterView surfaceCreated");
try {
mCallback.surfaceCreated(holder);
}catch (Throwable t){
Debuger.exception(t);
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
//Debuger.log("flutterView surfaceChanged");
try {
mCallback.surfaceChanged(holder,format,width,height);
scheduleFrame();
}catch (Throwable t){
Debuger.exception(t);
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
//Debuger.log("flutterView surfaceDestroyed");
try {
mCallback.surfaceDestroyed(holder);
}catch (Throwable t){
Debuger.exception(t);
}
}
}
@Override
protected void onAttachedToWindow() {
//Debuger.log("flutterView onAttachedToWindow");
super.onAttachedToWindow();
}
}
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Alibaba Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.taobao.idlefish.flutterboost;
import com.taobao.idlefish.flutterboost.NavigationService.NavigationService;
import com.taobao.idlefish.flutterboost.interfaces.IContainerManager;
import com.taobao.idlefish.flutterboost.interfaces.IContainerRecord;
import com.taobao.idlefish.flutterboost.interfaces.IFlutterViewContainer;
import java.util.Map;
import fleamarket.taobao.com.xservicekit.handler.MessageResult;
public class ContainerRecord implements IContainerRecord {
private final IContainerManager mManager;
private final IFlutterViewContainer mContainer;
private final String mUniqueId;
private int mState = STATE_UNKNOW;
private MethodChannelProxy mProxy = new MethodChannelProxy();
public ContainerRecord(IContainerManager manager, IFlutterViewContainer container) {
mUniqueId = System.currentTimeMillis() + "-" + hashCode();
mManager = manager;
mContainer = container;
}
@Override
public String uniqueId() {
return mUniqueId;
}
@Override
public IFlutterViewContainer getContainer() {
return mContainer;
}
@Override
public int getState() {
return mState;
}
@Override
public void onCreate() {
mState = STATE_CREATED;
mContainer.getBoostFlutterView().boostResume();
mProxy.create();
}
@Override
public void onAppear() {
mState = STATE_APPEAR;
mContainer.getBoostFlutterView().boostResume();
mProxy.appear();
}
@Override
public void onDisappear() {
mProxy.disappear();
mState = STATE_DISAPPEAR;
}
@Override
public void onDestroy() {
mProxy.destroy();
mState = STATE_DESTROYED;
}
@Override
public void onResult(Map Result) {
NavigationService.onNativePageResult(
genResult("onNativePageResult"),
mUniqueId,
mUniqueId,
Result,
mContainer.getContainerParams()
);
}
private class MethodChannelProxy {
private int mState = STATE_UNKNOW;
private void create() {
if (mState == STATE_UNKNOW) {
NavigationService.didInitPageContainer(
genResult("didInitPageContainer"),
mContainer.getContainerName(),
mContainer.getContainerParams(),
mUniqueId
);
//Debuger.log("didInitPageContainer");
mState = STATE_CREATED;
}
}
private void appear() {
NavigationService.didShowPageContainer(
genResult("didShowPageContainer"),
mContainer.getContainerName(),
mContainer.getContainerParams(),
mUniqueId
);
//Debuger.log("didShowPageContainer");
mState = STATE_APPEAR;
}
private void disappear() {
if (mState < STATE_DISAPPEAR) {
NavigationService.didDisappearPageContainer(
genResult("didDisappearPageContainer"),
mContainer.getContainerName(),
mContainer.getContainerParams(),
mUniqueId
);
//Debuger.log("didDisappearPageContainer");
mState = STATE_DISAPPEAR;
}
}
private void destroy() {
if (mState < STATE_DESTROYED) {
NavigationService.willDeallocPageContainer(
genResult("willDeallocPageContainer"),
mContainer.getContainerName(),
mContainer.getContainerParams(),
mUniqueId
);
//Debuger.log("willDeallocPageContainer");
mState = STATE_DESTROYED;
}
}
}
private MessageResult<Boolean> genResult(final String name) {
return new MessageResult<Boolean>() {
@Override
public void success(Boolean var1) {
//Debuger.log(name + " call success");
}
@Override
public void error(String var1, String var2, Object var3) {
Debuger.log(name + " call error");
}
@Override
public void notImplemented() {
Debuger.log(name + " call not Impelemented");
}
};
}
}
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Alibaba Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.taobao.idlefish.flutterboost;
import android.util.Log;
public class Debuger {
private static final String TAG = "FlutterBoost#";
private static final Debuger DEBUG = new Debuger();
private Debuger(){ }
private void print(String info) {
if(isDebug()) {
Log.e(TAG, info);
}
}
public static void log(String info) {
DEBUG.print(info);
}
public static void exception(String message) {
if(isDebug()) {
throw new RuntimeException(message);
}else{
Log.e(TAG,"exception",new RuntimeException(message));
}
}
public static void exception(Throwable t) {
if(isDebug()) {
throw new RuntimeException(t);
}else{
Log.e(TAG,"exception",t);
}
}
public static boolean isDebug(){
try {
return FlutterBoostPlugin.platform().isDebug();
}catch (Throwable t){
return false;
}
}
}
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Alibaba Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.taobao.idlefish.flutterboost;
import android.app.Activity;
import com.taobao.idlefish.flutterboost.interfaces.IFlutterViewContainer;
import com.taobao.idlefish.flutterboost.interfaces.IFlutterViewProvider;
import com.taobao.idlefish.flutterboost.interfaces.IPlatform;
public class FlutterViewProvider implements IFlutterViewProvider {
private final IPlatform mPlatform;
private BoostFlutterNativeView mFlutterNativeView = null;
private BoostFlutterView mFlutterView = null;
FlutterViewProvider(IPlatform platform){
mPlatform = platform;
}
@Override
public BoostFlutterView createFlutterView(IFlutterViewContainer container) {
Activity activity = mPlatform.getMainActivity();
if(activity == null) {
Debuger.log("create Flutter View not with MainActivity");
activity = container.getActivity();
}
if (mFlutterView == null) {
mFlutterView = new BoostFlutterView(activity, null, createFlutterNativeView(container));
}
return mFlutterView;
}
@Override
public BoostFlutterNativeView createFlutterNativeView(IFlutterViewContainer container) {
if (mFlutterNativeView == null) {
mFlutterNativeView = new BoostFlutterNativeView(container.getActivity().getApplicationContext());
}
return mFlutterNativeView;
}
@Override
public BoostFlutterView tryGetFlutterView() {
return mFlutterView;
}
@Override
public void stopFlutterView() {
final BoostFlutterView view = mFlutterView;
if(view != null) {
view.boostStop();
}
}
@Override
public void reset() {
if(mFlutterNativeView != null) {
mFlutterNativeView.boostDestroy();
mFlutterNativeView = null;
}
if(mFlutterView != null) {
mFlutterView.boostDestroy();
mFlutterView = null;
}
}
}
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Alibaba Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.taobao.idlefish.flutterboost;
import com.taobao.idlefish.flutterboost.interfaces.IContainerRecord;
import com.taobao.idlefish.flutterboost.interfaces.IContainerManager;
public class Instrument {
private final IContainerManager mManager;
Instrument(IContainerManager manager) {
mManager = manager;
}
public void performCreate(IContainerRecord record) {
final int currentState = record.getState();
if (currentState != IContainerRecord.STATE_UNKNOW) {
Debuger.exception("performCreate state error, current state:" + currentState);
return;
}
record.onCreate();
}
public void performAppear(IContainerRecord record) {
final int currentState = record.getState();
if (currentState != IContainerRecord.STATE_CREATED
&& currentState != IContainerRecord.STATE_DISAPPEAR) {
Debuger.exception("performAppear state error, current state:" + currentState);
return;
}
record.onAppear();
}
public void performDisappear(IContainerRecord record) {
final int currentState = record.getState();
if (currentState != IContainerRecord.STATE_APPEAR) {
Debuger.exception("performDisappear state error , current state:" + currentState);
return;
}
record.onDisappear();
}
public void performDestroy(IContainerRecord record) {
final int currentState = record.getState();
if (currentState != IContainerRecord.STATE_DISAPPEAR) {
Debuger.exception("performDestroy state error, current state:" + currentState);
}
record.onDestroy();
}
}
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Alibaba Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.taobao.idlefish.flutterboost.NavigationService;
public class NavigationServiceRegister {
public static void register(){
NavigationService.register();
NavigationService_onShownContainerChanged.register();
NavigationService_onFlutterPageResult.register();
NavigationService_pageOnStart.register();
NavigationService_openPage.register();
NavigationService_closePage.register();
}
}
\ No newline at end of file
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Alibaba Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.taobao.idlefish.flutterboost.NavigationService;
import com.taobao.idlefish.flutterboost.FlutterBoostPlugin;
import com.taobao.idlefish.flutterboost.FlutterViewContainerManager;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import fleamarket.taobao.com.xservicekit.handler.MessageHandler;
import fleamarket.taobao.com.xservicekit.handler.MessageResult;
import fleamarket.taobao.com.xservicekit.service.ServiceGateway;
public class NavigationService_closePage implements MessageHandler<Boolean>{
private Object mContext = null;
private boolean onCall(MessageResult<Boolean> result,String uniqueId,String pageName,Map params,Boolean animated){
FlutterBoostPlugin.containerManager().destroyContainerRecord(pageName,uniqueId);
result.success(true);
return true;
}
//==================Do not edit code blow!==============
@Override
public boolean onMethodCall(String name, Map args, MessageResult<Boolean> result) {
this.onCall(result,(String)args.get("uniqueId"),(String)args.get("pageName"),(Map)args.get("params"),(Boolean)args.get("animated"));
return true;
}
@Override
public List<String> handleMessageNames() {
List<String> h = new ArrayList<>();
h.add("closePage");
return h;
}
@Override
public Object getContext() {
return mContext;
}
@Override
public void setContext(Object obj) {
mContext = obj;
}
@Override
public String service() {
return "NavigationService";
}
public static void register(){
ServiceGateway.sharedInstance().registerHandler(new NavigationService_closePage());
}
}
\ No newline at end of file
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Alibaba Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.taobao.idlefish.flutterboost.NavigationService;
import com.taobao.idlefish.flutterboost.FlutterBoostPlugin;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import fleamarket.taobao.com.xservicekit.handler.MessageHandler;
import fleamarket.taobao.com.xservicekit.handler.MessageResult;
import fleamarket.taobao.com.xservicekit.service.ServiceGateway;
public class NavigationService_onFlutterPageResult implements MessageHandler<Boolean>{
private Object mContext = null;
private boolean onCall(MessageResult<Boolean> result,String uniqueId,String key,Map resultData,Map params){
FlutterBoostPlugin.containerManager().setContainerResult(uniqueId,resultData);
result.success(true);
return true;
}
//==================Do not edit code blow!==============
@Override
public boolean onMethodCall(String name, Map args, MessageResult<Boolean> result) {
this.onCall(result,(String)args.get("uniqueId"),(String)args.get("key"),(Map)args.get("resultData"),(Map)args.get("params"));
return true;
}
@Override
public List<String> handleMessageNames() {
List<String> h = new ArrayList<>();
h.add("onFlutterPageResult");
return h;
}
@Override
public Object getContext() {
return mContext;
}
@Override
public void setContext(Object obj) {
mContext = obj;
}
@Override
public String service() {
return "NavigationService";
}
public static void register(){
ServiceGateway.sharedInstance().registerHandler(new NavigationService_onFlutterPageResult());
}
}
\ No newline at end of file
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Alibaba Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.taobao.idlefish.flutterboost.NavigationService;
import com.taobao.idlefish.flutterboost.Debuger;
import com.taobao.idlefish.flutterboost.FlutterBoostPlugin;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import fleamarket.taobao.com.xservicekit.handler.MessageHandler;
import fleamarket.taobao.com.xservicekit.handler.MessageResult;
import fleamarket.taobao.com.xservicekit.service.ServiceGateway;
public class NavigationService_onShownContainerChanged implements MessageHandler<Boolean>{
private Object mContext = null;
private boolean onCall(MessageResult<Boolean> result,String now,String old,Map params){
//Add your handler code here.
FlutterBoostPlugin.containerManager().onShownContainerChanged(old,now);
return true;
}
//==================Do not edit code blow!==============
@Override
public boolean onMethodCall(String name, Map args, MessageResult<Boolean> result) {
this.onCall(result,(String)args.get("newName"),(String)args.get("oldName"),(Map)args.get("params"));
return true;
}
@Override
public List<String> handleMessageNames() {
List<String> h = new ArrayList<>();
h.add("onShownContainerChanged");
return h;
}
@Override
public Object getContext() {
return mContext;
}
@Override
public void setContext(Object obj) {
mContext = obj;
}
@Override
public String service() {
return "NavigationService";
}
public static void register(){
ServiceGateway.sharedInstance().registerHandler(new NavigationService_onShownContainerChanged());
}
}
\ No newline at end of file
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Alibaba Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.taobao.idlefish.flutterboost.NavigationService;
import com.taobao.idlefish.flutterboost.FlutterBoostPlugin;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import fleamarket.taobao.com.xservicekit.handler.MessageHandler;
import fleamarket.taobao.com.xservicekit.handler.MessageResult;
import fleamarket.taobao.com.xservicekit.service.ServiceGateway;
public class NavigationService_openPage implements MessageHandler<Boolean>{
private Object mContext = null;
private boolean onCall(MessageResult<Boolean> result,String pageName,Map params,Boolean animated){
Map pageParams = null;
int requestCode = 0;
if(params != null && params.get("query") != null) {
pageParams = (Map)params.get("query");
}
if(params != null && params.get("requestCode") != null) {
requestCode = (int)params.get("requestCode");
}
FlutterBoostPlugin.openPage(null,pageName,pageParams,requestCode);
result.success(true);
return true;
}
//==================Do not edit code blow!==============
@Override
public boolean onMethodCall(String name, Map args, MessageResult<Boolean> result) {
this.onCall(result,(String)args.get("pageName"),(Map)args.get("params"),(Boolean)args.get("animated"));
return true;
}
@Override
public List<String> handleMessageNames() {
List<String> h = new ArrayList<>();
h.add("openPage");
return h;
}
@Override
public Object getContext() {
return mContext;
}
@Override
public void setContext(Object obj) {
mContext = obj;
}
@Override
public String service() {
return "NavigationService";
}
public static void register(){
ServiceGateway.sharedInstance().registerHandler(new NavigationService_openPage());
}
}
\ No newline at end of file
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Alibaba Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.taobao.idlefish.flutterboost.NavigationService;
import com.taobao.idlefish.flutterboost.FlutterBoostPlugin;
import com.taobao.idlefish.flutterboost.FlutterViewContainerManager;
import com.taobao.idlefish.flutterboost.interfaces.IContainerRecord;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import fleamarket.taobao.com.xservicekit.handler.MessageHandler;
import fleamarket.taobao.com.xservicekit.handler.MessageResult;
import fleamarket.taobao.com.xservicekit.service.ServiceGateway;
public class NavigationService_pageOnStart implements MessageHandler<Map>{
private Object mContext = null;
private boolean onCall(MessageResult<Map> result,Map params){
Map<String,Object> pageInfo = new HashMap<>();
try {
IContainerRecord record = FlutterBoostPlugin
.containerManager().getCurrentTopRecord();
if(record == null) {
record = FlutterBoostPlugin.containerManager().getLastRecord();
}
pageInfo.put("name",record.getContainer().getContainerName());
pageInfo.put("params",record.getContainer().getContainerParams());
pageInfo.put("uniqueId",record.uniqueId());
result.success(pageInfo);
}catch (Throwable t){
result.success(pageInfo);
}
return true;
}
//==================Do not edit code blow!==============
@Override
public boolean onMethodCall(String name, Map args, MessageResult<Map> result) {
this.onCall(result,(Map)args.get("params"));
return true;
}
@Override
public List<String> handleMessageNames() {
List<String> h = new ArrayList<>();
h.add("pageOnStart");
return h;
}
@Override
public Object getContext() {
return mContext;
}
@Override
public void setContext(Object obj) {
mContext = obj;
}
@Override
public String service() {
return "NavigationService";
}
public static void register(){
ServiceGateway.sharedInstance().registerHandler(new NavigationService_pageOnStart());
}
}
\ No newline at end of file
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Alibaba Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.taobao.idlefish.flutterboost;
import java.util.Map;
public interface PageResultHandler {
void onResult(String key , Map resultData);
}
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Alibaba Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.taobao.idlefish.flutterboost;
import java.util.HashMap;
import java.util.Map;
class PageResultMediator {
private Map<String,PageResultHandler> _handlers = new HashMap<>();
void onPageResult(String key , Map resultData){
if(key == null) return;
if(_handlers.containsKey(key)){
_handlers.get(key).onResult(key,resultData);
_handlers.remove(key);
}
}
void setHandler(String key, PageResultHandler handler){
if(key == null || handler == null) return;
_handlers.put(key,handler);
}
void removeHandler(String key){
if(key == null) return;;
_handlers.remove(key);
}
}
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Alibaba Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.taobao.idlefish.flutterboost;
import android.graphics.Bitmap;
import android.graphics.Color;
public class Utils {
public static boolean checkImageValid(final Bitmap bitmap) {
if (null == bitmap) {
return false;
}
int width = bitmap.getWidth();
int height = bitmap.getHeight();
int[] pixels = new int[width * height];
bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
int [] checkPixels = new int[18];
for (int i=0; i<5; i++) {
int colCount = 4 - i%2;
for (int j=0; j<colCount; j++) {
checkPixels[i*3 + j + (i+1)/2] = pixels[(i + 1)*(height/6)*width + (j + 1)*(width/(colCount + 1))];
}
}
float[][] checkHSV = new float[checkPixels.length][3];
for (int i=0; i<checkPixels.length; i++) {
int clr = checkPixels[i];
int red = (clr & 0x00ff0000) >> 16; // 取高两位
int green = (clr & 0x0000ff00) >> 8; // 取中两位
int blue = clr & 0x000000ff;
Color.RGBToHSV(red, green, blue, checkHSV[i]);
}
int diffCount = 0;
for (int i=0; i<checkPixels.length; i++) {
for (int j=i+1; j<checkPixels.length; j++) {
double d = Math.sqrt(Math.pow(checkHSV[i][0] - checkHSV[j][0], 2.0)
+ Math.pow(checkHSV[i][1] - checkHSV[j][1], 2.0)
+ Math.pow(checkHSV[i][2] - checkHSV[j][2], 2.0));
if (d >= 1) {
diffCount++;
}
}
}
if (diffCount <= 10) {
return false;
} else {
return true;
}
}
}
\ No newline at end of file
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Alibaba Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.taobao.idlefish.flutterboost.containers;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.FrameLayout;
import android.widget.ProgressBar;
import com.taobao.idlefish.flutterboost.BoostFlutterView;
import com.taobao.idlefish.flutterboost.FlutterBoostPlugin;
import com.taobao.idlefish.flutterboost.interfaces.IFlutterViewContainer;
import java.util.HashMap;
import java.util.Map;
import io.flutter.app.FlutterActivity;
import io.flutter.view.FlutterNativeView;
import io.flutter.view.FlutterView;
abstract public class BoostFlutterActivity extends FlutterActivity implements IFlutterViewContainer {
private FlutterContent mFlutterContent;
@Override
protected void onCreate(Bundle savedInstanceState) {
getWindow().requestFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
mFlutterContent = new FlutterContent(this);
setContentView(mFlutterContent);
FlutterBoostPlugin.containerManager().onContainerCreate(this);
onRegisterPlugins(this);
}
@Override
protected void onPostResume() {
super.onPostResume();
FlutterBoostPlugin.containerManager().onContainerAppear(BoostFlutterActivity.this);
mFlutterContent.attachFlutterView(getBoostFlutterView());
}
@Override
protected void onPause() {
mFlutterContent.detachFlutterView();
FlutterBoostPlugin.containerManager().onContainerDisappear(this);
super.onPause();
}
@Override
protected void onDestroy() {
FlutterBoostPlugin.containerManager().onContainerDestroy(this);
mFlutterContent.destroy();
super.onDestroy();
}
public FlutterView createFlutterView(Context context) {
return FlutterBoostPlugin.viewProvider().createFlutterView(this);
}
@Override
public FlutterNativeView createFlutterNativeView() {
return FlutterBoostPlugin.viewProvider().createFlutterNativeView(this);
}
@Override
public boolean retainFlutterNativeView() {
return true;
}
protected View createSplashScreenView() {
FrameLayout frameLayout = new FrameLayout(this);
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params.gravity = Gravity.CENTER;
frameLayout.addView(new ProgressBar(this), params);
return frameLayout;
}
protected View createFlutterInitCoverView() {
View initCover = new View(this);
initCover.setBackgroundColor(Color.WHITE);
return initCover;
}
@Override
public void onContainerShown() {
mFlutterContent.onContainerShown();
}
@Override
public void onContainerHidden() {
mFlutterContent.onContainerHidden();
}
@Override
public void onBackPressed() {
FlutterBoostPlugin.containerManager().onBackPressed(this);
}
@Override
public Activity getActivity() {
return this;
}
@Override
public BoostFlutterView getBoostFlutterView() {
return (BoostFlutterView) getFlutterView();
}
@Override
public void destroyContainer() {
finish();
}
@Override
public abstract String getContainerName();
@Override
public abstract Map getContainerParams();
@Override
public void setBoostResult(HashMap result) {
FlutterBoostPlugin.setBoostResult(this, result);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
FlutterBoostPlugin.onBoostResult(this,requestCode,resultCode,data);
}
class FlutterContent extends FlutterViewStub {
public FlutterContent(Context context) {
super(context);
}
@Override
public View createFlutterInitCoverView() {
return BoostFlutterActivity.this.createFlutterInitCoverView();
}
@Override
public BoostFlutterView getBoostFlutterView() {
return BoostFlutterActivity.this.getBoostFlutterView();
}
@Override
public View createSplashScreenView() {
return BoostFlutterActivity.this.createSplashScreenView();
}
}
}
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Alibaba Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.taobao.idlefish.flutterboost.containers;
import android.content.Context;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ProgressBar;
import com.taobao.idlefish.flutterboost.BoostFlutterView;
import com.taobao.idlefish.flutterboost.Debuger;
import com.taobao.idlefish.flutterboost.FlutterBoostPlugin;
import com.taobao.idlefish.flutterboost.interfaces.IFlutterViewContainer;
import java.util.HashMap;
import io.flutter.plugin.common.PluginRegistry;
abstract public class BoostFlutterFragment extends Fragment implements IFlutterViewContainer {
FlutterContent mContent;
PluginRegistry mRegistry;
boolean resumed = false;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mRegistry = FlutterBoostPlugin.containerManager().onContainerCreate(this);
onRegisterPlugins(mRegistry);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
mContent = new FlutterContent(getActivity());
return mContent;
}
@Override
public void onResume() {
super.onResume();
if (!resumed) {
resumed = true;
FlutterBoostPlugin.containerManager().onContainerAppear(this);
mContent.attachFlutterView(getBoostFlutterView());
Log.e("FlutterBoost", "FlutterMenuFragment resume");
}
}
@Override
public void onPause() {
super.onPause();
if (resumed) {
resumed = false;
mContent.snapshot();
FlutterBoostPlugin.containerManager().onContainerDisappear(this);
Log.e("FlutterBoost", "FlutterMenuFragment stop");
}
}
@Override
public void onDestroy() {
super.onDestroy();
if (mContent != null) {
mContent.destroy();
}
FlutterBoostPlugin.containerManager().onContainerDestroy(this);
}
@Override
public void onContainerShown() {
mContent.onContainerShown();
}
@Override
public void onContainerHidden() {
mContent.onContainerHidden();
}
@Override
public BoostFlutterView getBoostFlutterView() {
return FlutterBoostPlugin.viewProvider().createFlutterView(this);
}
@Override
public boolean isFinishing() {
return getActivity().isFinishing();
}
protected View createSplashScreenView() {
FrameLayout layout = new FrameLayout(getContext());
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params.gravity = Gravity.CENTER;
layout.addView(new ProgressBar(getContext()),params);
return layout;
}
protected View createFlutterInitCoverView() {
View initCover = new View(getActivity());
initCover.setBackgroundColor(Color.WHITE);
return initCover;
}
@Override
public void setBoostResult(HashMap result) {
}
class FlutterContent extends FlutterViewStub {
public FlutterContent(Context context) {
super(context);
}
@Override
public View createFlutterInitCoverView() {
return BoostFlutterFragment.this.createFlutterInitCoverView();
}
@Override
public BoostFlutterView getBoostFlutterView() {
return BoostFlutterFragment.this.getBoostFlutterView();
}
@Override
public View createSplashScreenView() {
return BoostFlutterFragment.this.createSplashScreenView();
}
}
}
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Alibaba Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.taobao.idlefish.flutterboost.containers;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ProgressBar;
import com.taobao.idlefish.flutterboost.BoostFlutterView;
import com.taobao.idlefish.flutterboost.Debuger;
abstract public class FlutterViewStub extends FrameLayout {
public static final Handler sHandler = new ProcessHandler(Looper.getMainLooper());
protected Bitmap mBitmap;
protected ImageView mSnapshot;
protected FrameLayout mStub;
protected View mCover;
protected View mSplashScreenView;
public FlutterViewStub(Context context) {
super(context);
mStub = new FrameLayout(context);
mStub.setBackgroundColor(Color.WHITE);
addView(mStub, new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
mSnapshot = new ImageView(context);
mSnapshot.setScaleType(ImageView.ScaleType.FIT_CENTER);
mSnapshot.setLayoutParams(new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
mCover = createFlutterInitCoverView();
addView(mCover, new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
final BoostFlutterView flutterView = getBoostFlutterView();
if (!flutterView.firstFrameCalled()) {
mSplashScreenView = createSplashScreenView();
addView(mSplashScreenView, new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
}
}
public void onContainerShown() {
Debuger.log("onContainerShown");
sHandler.postDelayed(new Runnable() {
@Override
public void run() {
if (mSplashScreenView != null) {
FlutterViewStub.this.removeView(mSplashScreenView);
mSplashScreenView = null;
}
if (mCover != null) {
FlutterViewStub.this.removeView(mCover);
}
if (mSnapshot.getParent() == FlutterViewStub.this) {
FlutterViewStub.this.removeView(mSnapshot);
mSnapshot.setImageBitmap(null);
if (mBitmap != null && !mBitmap.isRecycled()) {
mBitmap.recycle();
mBitmap = null;
}
}
getBoostFlutterView().scheduleFrame();
getBoostFlutterView().requestFocus();
getBoostFlutterView().invalidate();
}
}, 167);
}
public void onContainerHidden() {
//Debuger.log("onContainerHidden");
}
public void snapshot() {
if (mStub.getChildCount() <= 0) return;
if (mSnapshot.getParent() != null) return;
BoostFlutterView flutterView = (BoostFlutterView) mStub.getChildAt(0);
mBitmap = flutterView.getBitmap();
if (mBitmap != null && !mBitmap.isRecycled()) {
mSnapshot.setImageBitmap(mBitmap);
addView(mSnapshot);
}
}
public void attachFlutterView(final BoostFlutterView flutterView) {
if (flutterView.getParent() != mStub) {
sHandler.removeMessages(ProcessHandler.MSG_DETACH);
Debuger.log("attachFlutterView");
if (flutterView.getParent() != null) {
((ViewGroup) flutterView.getParent()).removeView(flutterView);
}
mStub.addView(flutterView, new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
}
}
public void detachFlutterView() {
if (mStub.getChildCount() <= 0) return;
final BoostFlutterView flutterView = (BoostFlutterView) mStub.getChildAt(0);
if (flutterView == null) return;
Debuger.log("detachFlutterView");
if (mSnapshot.getParent() == null) {
mBitmap = flutterView.getBitmap();
if (mBitmap != null && !mBitmap.isRecycled()) {
mSnapshot.setImageBitmap(mBitmap);
addView(mSnapshot);
}
}
Message msg = new Message();
msg.what = ProcessHandler.MSG_DETACH;
msg.obj = new Runnable() {
@Override
public void run() {
if (flutterView.getParent() != null && flutterView.getParent() == mStub) {
mStub.removeView(flutterView);
}
}
};
sHandler.sendMessage(msg);
}
public void destroy() {
removeAllViews();
mSnapshot.setImageBitmap(null);
if (mBitmap != null && !mBitmap.isRecycled()) {
mBitmap.recycle();
mBitmap = null;
}
}
protected View createFlutterInitCoverView() {
View initCover = new View(getContext());
initCover.setBackgroundColor(Color.WHITE);
return initCover;
}
protected View createSplashScreenView() {
FrameLayout layout = new FrameLayout(getContext());
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params.gravity = Gravity.CENTER;
layout.addView(new ProgressBar(getContext()),params);
return layout;
}
abstract protected BoostFlutterView getBoostFlutterView();
public static class ProcessHandler extends Handler {
static final int MSG_DETACH = 175101;
ProcessHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.obj instanceof Runnable) {
Runnable run = (Runnable) msg.obj;
run.run();
}
}
}
}
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Alibaba Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.taobao.idlefish.flutterboost.interfaces;
import android.app.Activity;
import java.util.Map;
import io.flutter.plugin.common.PluginRegistry;
public interface IContainerManager {
/**
* call by native side when container create
* @param container
* @return
*/
PluginRegistry onContainerCreate(IFlutterViewContainer container);
/**
* call by native side when container appear
* @param container
* @return
*/
void onContainerAppear(IFlutterViewContainer container);
/**
* call by native side when container disappear
* @param container
* @return
*/
void onContainerDisappear(IFlutterViewContainer container);
/**
* call by native side when container destroy
* @param container
* @return
*/
void onContainerDestroy(IFlutterViewContainer container);
/**
* call by native side when back key pressed
* @param container
* @return
*/
void onBackPressed(IFlutterViewContainer container);
/**
* call by flutter side when need destroy container
* @param name
* @param uq
*/
void destroyContainerRecord(String name,String uq);
/**
* call by native side when container handle a result (onActivityResult)
* @param container
* @param result
*/
void onContainerResult(IFlutterViewContainer container,Map result);
/**
* call by flutter side when flutter want set a result for request (setResult)
* @param uniqueId
* @param result
*/
void setContainerResult(String uniqueId,Map result);
/**
* get current interactive container
* @return
*/
IContainerRecord getCurrentTopRecord();
/**
* get last created container
* @return
*/
IContainerRecord getLastRecord();
/**
* find a container
* @param uniqueId
* @return
*/
IFlutterViewContainer findContainerById(String uniqueId);
/**
* call by flutter side when a container shown or hidden
* @param old
* @param now
*/
void onShownContainerChanged(String old,String now);
/**
* is any container appear now
* @return
*/
boolean hasContainerAppear();
/**
* no use
*/
void reset();
}
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Alibaba Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.taobao.idlefish.flutterboost.interfaces;
import java.util.Map;
/**
* a container record, which use map a flutter page
*/
public interface IContainerRecord {
int STATE_UNKNOW = 0;
int STATE_CREATED = 1;
int STATE_APPEAR = 2;
int STATE_DISAPPEAR = 3;
int STATE_DESTROYED = 4;
String uniqueId();
IFlutterViewContainer getContainer();
int getState();
void onCreate();
void onAppear();
void onDisappear();
void onDestroy();
void onResult(Map Result);
}
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Alibaba Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.taobao.idlefish.flutterboost.interfaces;
import android.app.Activity;
import com.taobao.idlefish.flutterboost.BoostFlutterView;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import io.flutter.plugin.common.PluginRegistry;
/**
* a container which contains the flutter view
*/
public interface IFlutterViewContainer {
String RESULT_KEY = "_flutter_result_";
Activity getActivity();
/**
* provide a flutter view
* @return
*/
BoostFlutterView getBoostFlutterView();
/**
* call to destroy the container
*/
void destroyContainer();
/**
* container name
* @return
*/
String getContainerName();
/**
* container params
* @return
*/
Map getContainerParams();
/**
* callback when container shown
*/
void onContainerShown();
/**
* callback when container hidden
*/
void onContainerHidden();
/**
* is container finishing
* @return
*/
boolean isFinishing();
/**
* call by flutter side to set result
* @param result
*/
void setBoostResult(HashMap result);
/**
* register flutter plugins
* @param registry
*/
void onRegisterPlugins(PluginRegistry registry);
}
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Alibaba Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.taobao.idlefish.flutterboost.interfaces;
import com.taobao.idlefish.flutterboost.BoostFlutterNativeView;
import com.taobao.idlefish.flutterboost.BoostFlutterView;
/**
* a flutter view provider
*/
public interface IFlutterViewProvider {
/**
* create flutter view, we just hold a single instance now
* @param container
* @return
*/
BoostFlutterView createFlutterView(IFlutterViewContainer container);
/**
* single instance also
* @param container
* @return
*/
BoostFlutterNativeView createFlutterNativeView(IFlutterViewContainer container);
/**
* may return null
* @return
*/
BoostFlutterView tryGetFlutterView();
/**
* release flutter view
*/
void stopFlutterView();
/**
* reset all refrence
*/
void reset();
}
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Alibaba Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.taobao.idlefish.flutterboost.interfaces;
import android.app.Activity;
import android.app.Application;
import android.content.Context;
import java.util.Map;
/**
* APIs that platform(Android App) must provide
*/
public interface IPlatform {
/**
* get current application
* @return
*/
Application getApplication();
/**
* get main activity, which must always exist at the bottom of task stack.
* @return
*/
Activity getMainActivity();
/**
* debug or not
* @return
*/
boolean isDebug();
/**
* start a new activity from flutter page, you may need a page router with url
* @param context
* @param url
* @param requestCode
* @return
*/
boolean startActivity(Context context,String url,int requestCode);
/**
* settings, no use
* @return
*/
Map getSettings();
}
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Alibaba Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.taobao.idlefish.flutterboost.loader;
public class ServiceLoader {
public static void load(){
com.taobao.idlefish.flutterboost.NavigationService.NavigationServiceRegister.register();
}
}
\ No newline at end of file
.DS_Store
.dart_tool/
.packages
.pub/
.idea
build/
.flutter-plugins
# 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: 2a5023ac70c4566dd56d7d00b1b7bd47a0e3cf80
channel: xy_beta_v0.8.2
# flutter_boost_example
Demonstrates how to use the flutter_boost plugin.
## Getting Started
For help getting started with Flutter, view our online
[documentation](https://flutter.io/).
*.iml
*.class
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures
GeneratedPluginRegistrant.java
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
apply plugin: 'com.android.application'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
compileSdkVersion 27
lintOptions {
disable 'InvalidPackage'
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.taobao.idlefish.flutterboostexample"
minSdkVersion 16
targetSdkVersion 27
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig signingConfigs.debug
}
}
}
flutter {
source '../..'
}
dependencies {
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation 'com.android.support:support-v4:27.1.1'
implementation 'com.android.support:appcompat-v7:27.1.1'
}
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.taobao.idlefish.flutterboostexample">
<!-- The INTERNET permission is required for development. Specifically,
flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
calls FlutterMain.startInitialization(this); in its onCreate method.
In most cases you can leave this as-is, but you if you want to provide
additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. -->
<application
android:name=".MyApplication"
android:label="flutter_boost_example"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="@style/Theme.AppCompat"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name=".FlutterPageActivity"
android:theme="@style/Theme.AppCompat"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize"/>
<activity
android:name=".FlutterFragmentPageActivity"
android:theme="@style/Theme.AppCompat"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize"/>
<activity
android:name=".NativePageActivity"
android:theme="@style/Theme.AppCompat"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density"
android:windowSoftInputMode="adjustResize"/>
</application>
</manifest>
package com.taobao.idlefish.flutterboostexample;
import android.os.Bundle;
import android.support.annotation.Nullable;
import com.taobao.idlefish.flutterboost.containers.BoostFlutterFragment;
import java.util.HashMap;
import java.util.Map;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugins.GeneratedPluginRegistrant;
public class FlutterFragment extends BoostFlutterFragment {
@Override
public void setArguments(@Nullable Bundle args) {
if(args == null) {
args = new Bundle();
args.putString("tag","");
}
super.setArguments(args);
}
public void setTabTag(String tag) {
Bundle args = new Bundle();
args.putString("tag",tag);
super.setArguments(args);
}
@Override
public void onRegisterPlugins(PluginRegistry registry) {
GeneratedPluginRegistrant.registerWith(registry);
}
@Override
public String getContainerName() {
return "flutterFragment";
}
@Override
public Map getContainerParams() {
Map<String,String> params = new HashMap<>();
params.put("tag",getArguments().getString("tag"));
return params;
}
@Override
public void destroyContainer() {
}
public static FlutterFragment instance(String tag){
FlutterFragment fragment = new FlutterFragment();
fragment.setTabTag(tag);
return fragment;
}
}
package com.taobao.idlefish.flutterboostexample;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.view.Window;
import android.view.WindowManager;
import io.flutter.plugin.platform.PlatformPlugin;
public class FlutterFragmentPageActivity extends AppCompatActivity {
private FlutterFragment mFragment;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(0x40000000);
window.getDecorView().setSystemUiVisibility(PlatformPlugin.DEFAULT_SYSTEM_UI);
}
super.onCreate(savedInstanceState);
final ActionBar actionBar = getSupportActionBar();
if(actionBar != null) {
actionBar.hide();
}
setContentView(R.layout.flutter_fragment_page);
mFragment = FlutterFragment.instance("hello");
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.fragment_stub,mFragment)
.commit();
}
}
package com.taobao.idlefish.flutterboostexample;
import com.taobao.idlefish.flutterboost.containers.BoostFlutterActivity;
import java.util.Map;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugins.GeneratedPluginRegistrant;
public class FlutterPageActivity extends BoostFlutterActivity {
@Override
public void onRegisterPlugins(PluginRegistry registry) {
GeneratedPluginRegistrant.registerWith(registry);
}
@Override
public String getContainerName() {
return "flutterPage";
}
@Override
public Map getContainerParams() {
return null;
}
}
package com.taobao.idlefish.flutterboostexample;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;
import java.lang.ref.WeakReference;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
public static WeakReference<MainActivity> sRef;
private TextView mOpenNative;
private TextView mOpenFlutter;
private TextView mOpenFlutterFragment;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
sRef = new WeakReference<>(this);
setContentView(R.layout.native_page);
mOpenNative = findViewById(R.id.open_native);
mOpenFlutter = findViewById(R.id.open_flutter);
mOpenFlutterFragment = findViewById(R.id.open_flutter_fragment);
mOpenNative.setOnClickListener(this);
mOpenFlutter.setOnClickListener(this);
mOpenFlutterFragment.setOnClickListener(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
sRef.clear();
sRef = null;
}
@Override
public void onClick(View v) {
if (v == mOpenNative) {
PageRouter.openPageByUrl(this, PageRouter.NATIVE_PAGE_URL);
} else if (v == mOpenFlutter) {
PageRouter.openPageByUrl(this, PageRouter.FLUTTER_PAGE_URL);
} else if (v == mOpenFlutterFragment) {
PageRouter.openPageByUrl(this, PageRouter.FLUTTER_FRAGMENT_PAGE_URL);
}
}
}
package com.taobao.idlefish.flutterboostexample;
import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.text.TextUtils;
import com.taobao.idlefish.flutterboost.FlutterBoostPlugin;
import com.taobao.idlefish.flutterboost.interfaces.IPlatform;
import java.util.Map;
import io.flutter.app.FlutterApplication;
public class MyApplication extends FlutterApplication {
@Override
public void onCreate() {
super.onCreate();
FlutterBoostPlugin.init(new IPlatform() {
@Override
public Application getApplication() {
return MyApplication.this;
}
/**
* 获取应用入口的Activity,这个Activity在应用交互期间应该是一直在栈底的
* @return
*/
@Override
public Activity getMainActivity() {
return MainActivity.sRef.get();
}
@Override
public boolean isDebug() {
return true;
}
@Override
public boolean startActivity(Context context, String url, int requestCode) {
return PageRouter.openPageByUrl(context,url,requestCode);
}
@Override
public Map getSettings() {
return null;
}
});
}
}
package com.taobao.idlefish.flutterboostexample;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;
public class NativePageActivity extends AppCompatActivity implements View.OnClickListener {
private TextView mOpenNative;
private TextView mOpenFlutter;
private TextView mOpenFlutterFragment;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.native_page);
mOpenNative = findViewById(R.id.open_native);
mOpenFlutter = findViewById(R.id.open_flutter);
mOpenFlutterFragment = findViewById(R.id.open_flutter_fragment);
mOpenNative.setOnClickListener(this);
mOpenFlutter.setOnClickListener(this);
mOpenFlutterFragment.setOnClickListener(this);
}
@Override
public void onClick(View v) {
if (v == mOpenNative) {
PageRouter.openPageByUrl(this, PageRouter.NATIVE_PAGE_URL);
} else if (v == mOpenFlutter) {
PageRouter.openPageByUrl(this, PageRouter.FLUTTER_PAGE_URL);
} else if (v == mOpenFlutterFragment) {
PageRouter.openPageByUrl(this, PageRouter.FLUTTER_FRAGMENT_PAGE_URL);
}
}
}
\ No newline at end of file
package com.taobao.idlefish.flutterboostexample;
import android.content.Context;
import android.content.Intent;
import android.text.TextUtils;
public class PageRouter {
public static final String NATIVE_PAGE_URL = "sample://nativePage";
public static final String FLUTTER_PAGE_URL = "sample://flutterPage";
public static final String FLUTTER_FRAGMENT_PAGE_URL = "sample://flutterFragmentPage";
public static boolean openPageByUrl(Context context, String url) {
return openPageByUrl(context, url, 0);
}
public static boolean openPageByUrl(Context context, String url, int requestCode) {
try {
if (TextUtils.equals(url, FLUTTER_PAGE_URL)) {
context.startActivity(new Intent(context, FlutterPageActivity.class));
return true;
} else if (TextUtils.equals(url, FLUTTER_FRAGMENT_PAGE_URL)) {
context.startActivity(new Intent(context, FlutterFragmentPageActivity.class));
return true;
} else if (TextUtils.equals(url, NATIVE_PAGE_URL)) {
context.startActivity(new Intent(context, NativePageActivity.class));
return true;
} else {
return false;
}
} catch (Throwable t) {
return false;
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@android:color/white">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:id="@+id/fragment_stub"/>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="left"
android:background="@android:color/white">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="80dp"
android:id="@+id/info"
android:text="@string/native_info"
android:textColor="@android:color/holo_blue_dark"
android:textSize="28sp"
android:layout_gravity="center_horizontal"/>
<View android:layout_width="1dp"
android:layout_height="0dp"
android:layout_weight="1"/>
<TextView
android:background="@android:color/holo_orange_dark"
android:layout_margin="8.0dp"
android:padding="8.0dp"
android:textColor="@android:color/black"
android:id="@+id/open_native"
android:textAllCaps="false"
android:textSize="16sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/open_native" />
<TextView
android:background="@android:color/holo_orange_dark"
android:layout_margin="8.0dp"
android:padding="8.0dp"
android:textColor="@android:color/black"
android:id="@+id/open_flutter"
android:textAllCaps="false"
android:textSize="16sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/open_flutter" />
<TextView
android:background="@android:color/holo_orange_dark"
android:layout_marginLeft="8.0dp"
android:layout_marginTop="8.0dp"
android:layout_marginRight="8.0dp"
android:layout_marginBottom="80.0dp"
android:padding="8.0dp"
android:textColor="@android:color/black"
android:id="@+id/open_flutter_fragment"
android:textAllCaps="false"
android:textSize="16sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/open_flutter_fragment" />
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="open_native">open native page</string>
<string name="open_flutter">open flutter page</string>
<string name="open_flutter_fragment">open flutter fragment page</string>
<string name="native_info">This is a native activity</string>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
Flutter draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
</resources>
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.1.2'
}
}
allprojects {
repositories {
google()
jcenter()
}
}
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(':app')
}
task clean(type: Delete) {
delete rootProject.buildDir
}
\ No newline at end of file
org.gradle.jvmargs=-Xmx1536M
#Fri Jun 23 08:50:38 CEST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
include ':app'
def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
def plugins = new Properties()
def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
if (pluginsFile.exists()) {
pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
}
plugins.each { name, path ->
def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
include ":$name"
project(":$name").projectDir = pluginDirectory
}
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/lib" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/.dart_tool" />
<excludeFolder url="file://$MODULE_DIR$/.idea" />
<excludeFolder url="file://$MODULE_DIR$/.pub" />
<excludeFolder url="file://$MODULE_DIR$/build" />
<excludeFolder url="file://$MODULE_DIR$/ios/.symlinks/plugins/xservice_kit/.dart_tool" />
<excludeFolder url="file://$MODULE_DIR$/ios/.symlinks/plugins/xservice_kit/.pub" />
<excludeFolder url="file://$MODULE_DIR$/ios/.symlinks/plugins/xservice_kit/build" />
<excludeFolder url="file://$MODULE_DIR$/ios/.symlinks/plugins/xservice_kit/example/.dart_tool" />
<excludeFolder url="file://$MODULE_DIR$/ios/.symlinks/plugins/xservice_kit/example/.pub" />
<excludeFolder url="file://$MODULE_DIR$/ios/.symlinks/plugins/xservice_kit/example/build" />
</content>
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Dart SDK" level="project" />
<orderEntry type="library" name="Flutter Plugins" level="project" />
</component>
</module>
\ No newline at end of file
This diff is collapsed.
/Users/jidong/Documents/FlutterBoost
\ No newline at end of file
/Users/jidong/.pub-cache/hosted/pub.dartlang.org/xservice_kit-0.0.26
\ No newline at end of file
App.framework
Flutter.framework
flutter_assets
Generated.xcconfig
This diff is collapsed.
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig"
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig"
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment