├── ios ├── Assets │ └── .gitkeep ├── Classes │ ├── FlutterjsbridgepluginPlugin.h │ └── FlutterjsbridgepluginPlugin.m ├── .gitignore └── flutter_jsbridge_plugin.podspec ├── .gradle ├── 5.2.1 │ ├── gc.properties │ ├── fileChanges │ │ └── last-build.bin │ └── fileHashes │ │ └── fileHashes.lock ├── vcs-1 │ └── gc.properties └── buildOutputCleanup │ ├── cache.properties │ └── buildOutputCleanup.lock ├── example ├── android │ ├── settings_aar.gradle │ ├── gradle.properties │ ├── app │ │ ├── src │ │ │ ├── main │ │ │ │ ├── res │ │ │ │ │ ├── mipmap-hdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-mdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-xhdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── drawable │ │ │ │ │ │ └── launch_background.xml │ │ │ │ │ └── values │ │ │ │ │ │ └── styles.xml │ │ │ │ ├── java │ │ │ │ │ └── dev │ │ │ │ │ │ └── epoll │ │ │ │ │ │ └── flutterjsbridgeplugin_example │ │ │ │ │ │ └── MainActivity.java │ │ │ │ └── AndroidManifest.xml │ │ │ ├── debug │ │ │ │ └── AndroidManifest.xml │ │ │ └── profile │ │ │ │ └── AndroidManifest.xml │ │ └── build.gradle │ ├── gradle │ │ └── wrapper │ │ │ └── gradle-wrapper.properties │ ├── .gitignore │ ├── build.gradle │ └── settings.gradle ├── web │ ├── favicon.png │ ├── icons │ │ ├── Icon-192.png │ │ └── Icon-512.png │ ├── manifest.json │ └── index.html ├── ios │ ├── Flutter │ │ ├── Debug.xcconfig │ │ ├── Release.xcconfig │ │ └── AppFrameworkInfo.plist │ ├── Runner │ │ ├── AppDelegate.h │ │ ├── Assets.xcassets │ │ │ ├── LaunchImage.imageset │ │ │ │ ├── LaunchImage.png │ │ │ │ ├── LaunchImage@2x.png │ │ │ │ ├── LaunchImage@3x.png │ │ │ │ ├── README.md │ │ │ │ └── Contents.json │ │ │ └── AppIcon.appiconset │ │ │ │ ├── Icon-App-20x20@1x.png │ │ │ │ ├── Icon-App-20x20@2x.png │ │ │ │ ├── Icon-App-20x20@3x.png │ │ │ │ ├── Icon-App-29x29@1x.png │ │ │ │ ├── Icon-App-29x29@2x.png │ │ │ │ ├── Icon-App-29x29@3x.png │ │ │ │ ├── Icon-App-40x40@1x.png │ │ │ │ ├── Icon-App-40x40@2x.png │ │ │ │ ├── Icon-App-40x40@3x.png │ │ │ │ ├── Icon-App-60x60@2x.png │ │ │ │ ├── Icon-App-60x60@3x.png │ │ │ │ ├── Icon-App-76x76@1x.png │ │ │ │ ├── Icon-App-76x76@2x.png │ │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ │ ├── Icon-App-83.5x83.5@2x.png │ │ │ │ └── Contents.json │ │ ├── main.m │ │ ├── AppDelegate.m │ │ ├── Base.lproj │ │ │ ├── Main.storyboard │ │ │ └── LaunchScreen.storyboard │ │ └── Info.plist │ ├── Runner.xcodeproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ ├── WorkspaceSettings.xcsettings │ │ │ │ └── IDEWorkspaceChecks.plist │ │ ├── xcshareddata │ │ │ └── xcschemes │ │ │ │ └── Runner.xcscheme │ │ └── project.pbxproj │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── WorkspaceSettings.xcsettings │ │ │ └── IDEWorkspaceChecks.plist │ ├── .gitignore │ ├── Podfile.lock │ └── Podfile ├── .metadata ├── README.md ├── .gitignore ├── test │ └── widget_test.dart ├── pubspec.yaml ├── lib │ └── main.dart └── pubspec.lock ├── android ├── settings.gradle ├── .gitignore ├── gradle.properties ├── src │ └── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── dev │ │ └── epoll │ │ └── flutterjsbridgeplugin │ │ └── FlutterjsbridgepluginPlugin.java ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties └── build.gradle ├── .gitignore ├── CHANGELOG.md ├── .idea ├── dictionaries │ └── jason.xml ├── misc.xml ├── vcs.xml ├── runConfigurations │ └── example_lib_main_dart.xml ├── libraries │ ├── Flutter_Plugins.xml │ └── Dart_SDK.xml ├── modules.xml ├── codeStyles │ └── Project.xml └── workspace.xml ├── .metadata ├── test └── flutterjsbridgeplugin_test.dart ├── lib ├── flutterjsbridgeplugin.dart ├── js_obj.dart ├── js_bridge.dart └── init_script.dart ├── flutterjsbridgeplugin.iml ├── LICENSE ├── README.md ├── JSBridge.js ├── pubspec.yaml └── pubspec.lock /ios/Assets/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gradle/5.2.1/gc.properties: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gradle/vcs-1/gc.properties: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gradle/5.2.1/fileChanges/last-build.bin: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/android/settings_aar.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'flutterjsbridgeplugin' 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .dart_tool/ 3 | 4 | .packages 5 | .pub/ 6 | 7 | build/ 8 | -------------------------------------------------------------------------------- /.gradle/buildOutputCleanup/cache.properties: -------------------------------------------------------------------------------- 1 | #Wed Jun 24 09:42:39 CST 2020 2 | gradle.version=5.2.1 3 | -------------------------------------------------------------------------------- /example/web/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epoll-j/flutter_jsbridge_plugin/HEAD/example/web/favicon.png -------------------------------------------------------------------------------- /example/web/icons/Icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epoll-j/flutter_jsbridge_plugin/HEAD/example/web/icons/Icon-192.png -------------------------------------------------------------------------------- /example/web/icons/Icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epoll-j/flutter_jsbridge_plugin/HEAD/example/web/icons/Icon-512.png -------------------------------------------------------------------------------- /.gradle/5.2.1/fileHashes/fileHashes.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epoll-j/flutter_jsbridge_plugin/HEAD/.gradle/5.2.1/fileHashes/fileHashes.lock -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.enableR8=true 3 | android.useAndroidX=true 4 | android.enableJetifier=true 5 | -------------------------------------------------------------------------------- /example/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.enableR8=true 3 | android.useAndroidX=true 4 | android.enableJetifier=true 5 | -------------------------------------------------------------------------------- /example/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /ios/Classes/FlutterjsbridgepluginPlugin.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface FlutterjsbridgepluginPlugin : NSObject 4 | @end 5 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface AppDelegate : FlutterAppDelegate 5 | 6 | @end 7 | -------------------------------------------------------------------------------- /.gradle/buildOutputCleanup/buildOutputCleanup.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epoll-j/flutter_jsbridge_plugin/HEAD/.gradle/buildOutputCleanup/buildOutputCleanup.lock -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epoll-j/flutter_jsbridge_plugin/HEAD/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epoll-j/flutter_jsbridge_plugin/HEAD/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 0.0.3 2 | fix example project bug 3 | 4 | ## 0.0.4 5 | upgrade flutter version 1.22、webview_flutter version 1.0.7 6 | 7 | ## 0.0.5 8 | upgrade webview_flutter version 2.1.0 -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epoll-j/flutter_jsbridge_plugin/HEAD/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epoll-j/flutter_jsbridge_plugin/HEAD/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epoll-j/flutter_jsbridge_plugin/HEAD/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /.idea/dictionaries/jason.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | flutterjsbridgeplugin 5 | 6 | 7 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epoll-j/flutter_jsbridge_plugin/HEAD/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epoll-j/flutter_jsbridge_plugin/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epoll-j/flutter_jsbridge_plugin/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epoll-j/flutter_jsbridge_plugin/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epoll-j/flutter_jsbridge_plugin/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epoll-j/flutter_jsbridge_plugin/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epoll-j/flutter_jsbridge_plugin/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epoll-j/flutter_jsbridge_plugin/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epoll-j/flutter_jsbridge_plugin/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epoll-j/flutter_jsbridge_plugin/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epoll-j/flutter_jsbridge_plugin/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epoll-j/flutter_jsbridge_plugin/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epoll-j/flutter_jsbridge_plugin/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epoll-j/flutter_jsbridge_plugin/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epoll-j/flutter_jsbridge_plugin/HEAD/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epoll-j/flutter_jsbridge_plugin/HEAD/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epoll-j/flutter_jsbridge_plugin/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epoll-j/flutter_jsbridge_plugin/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip 6 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/dev/epoll/flutterjsbridgeplugin_example/MainActivity.java: -------------------------------------------------------------------------------- 1 | package dev.epoll.flutterjsbridgeplugin_example; 2 | 3 | import io.flutter.embedding.android.FlutterActivity; 4 | 5 | public class MainActivity extends FlutterActivity { 6 | } 7 | -------------------------------------------------------------------------------- /example/ios/Runner/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char* argv[]) { 6 | @autoreleasepool { 7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Jun 24 09:50:29 CST 2020 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip 7 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 11 | key.properties 12 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations/example_lib_main_dart.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: f994b769743368b36b9c03fb359f62230b60ab92 8 | channel: beta 9 | 10 | project_type: plugin 11 | -------------------------------------------------------------------------------- /example/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: f994b769743368b36b9c03fb359f62230b60ab92 8 | channel: beta 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.m: -------------------------------------------------------------------------------- 1 | #import "AppDelegate.h" 2 | #import "GeneratedPluginRegistrant.h" 3 | 4 | @implementation AppDelegate 5 | 6 | - (BOOL)application:(UIApplication *)application 7 | didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 8 | [GeneratedPluginRegistrant registerWithRegistry:self]; 9 | // Override point for customization after application launch. 10 | return [super application:application didFinishLaunchingWithOptions:launchOptions]; 11 | } 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ios/.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .vagrant/ 3 | .sconsign.dblite 4 | .svn/ 5 | 6 | .DS_Store 7 | *.swp 8 | profile 9 | 10 | DerivedData/ 11 | build/ 12 | GeneratedPluginRegistrant.h 13 | GeneratedPluginRegistrant.m 14 | 15 | .generated/ 16 | 17 | *.pbxuser 18 | *.mode1v3 19 | *.mode2v3 20 | *.perspectivev3 21 | 22 | !default.pbxuser 23 | !default.mode1v3 24 | !default.mode2v3 25 | !default.perspectivev3 26 | 27 | xcuserdata 28 | 29 | *.moved-aside 30 | 31 | *.pyc 32 | *sync/ 33 | Icon? 34 | .tags* 35 | 36 | /Flutter/Generated.xcconfig 37 | /Flutter/flutter_export_environment.sh -------------------------------------------------------------------------------- /.idea/libraries/Flutter_Plugins.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # flutterjsbridgeplugin_example 2 | 3 | Demonstrates how to use the flutterjsbridgeplugin plugin. 4 | 5 | ## Getting Started 6 | 7 | This project is a starting point for a Flutter application. 8 | 9 | A few resources to get you started if this is your first Flutter project: 10 | 11 | - [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) 12 | - [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) 13 | 14 | For help getting started with Flutter, view our 15 | [online documentation](https://flutter.dev/docs), which offers tutorials, 16 | samples, guidance on mobile development, and a full API reference. 17 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | google() 4 | jcenter() 5 | } 6 | 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:4.0.0' 9 | } 10 | } 11 | 12 | allprojects { 13 | repositories { 14 | google() 15 | jcenter() 16 | } 17 | } 18 | 19 | rootProject.buildDir = '../build' 20 | subprojects { 21 | project.buildDir = "${rootProject.buildDir}/${project.name}" 22 | } 23 | subprojects { 24 | project.evaluationDependsOn(':app') 25 | } 26 | 27 | task clean(type: Delete) { 28 | delete rootProject.buildDir 29 | } 30 | 31 | tasks.withType(JavaCompile) { 32 | options.encoding = "UTF-8" 33 | } 34 | -------------------------------------------------------------------------------- /example/ios/.gitignore: -------------------------------------------------------------------------------- 1 | *.mode1v3 2 | *.mode2v3 3 | *.moved-aside 4 | *.pbxuser 5 | *.perspectivev3 6 | **/*sync/ 7 | .sconsign.dblite 8 | .tags* 9 | **/.vagrant/ 10 | **/DerivedData/ 11 | Icon? 12 | **/Pods/ 13 | **/.symlinks/ 14 | profile 15 | xcuserdata 16 | **/.generated/ 17 | Flutter/App.framework 18 | Flutter/Flutter.framework 19 | Flutter/Flutter.podspec 20 | Flutter/Generated.xcconfig 21 | Flutter/app.flx 22 | Flutter/app.zip 23 | Flutter/flutter_assets/ 24 | Flutter/flutter_export_environment.sh 25 | ServiceDefinitions.json 26 | Runner/GeneratedPluginRegistrant.* 27 | 28 | # Exceptions to above rules. 29 | !default.mode1v3 30 | !default.mode2v3 31 | !default.pbxuser 32 | !default.perspectivev3 33 | -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Flutter Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | include ':app' 6 | 7 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties") 8 | def properties = new Properties() 9 | 10 | assert localPropertiesFile.exists() 11 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } 12 | 13 | def flutterSdkPath = properties.getProperty("flutter.sdk") 14 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 15 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" 16 | -------------------------------------------------------------------------------- /test/flutterjsbridgeplugin_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/services.dart'; 2 | import 'package:flutter_test/flutter_test.dart'; 3 | //import 'package:flutterjsbridgeplugin/flutterjsbridgeplugin.dart'; 4 | 5 | void main() { 6 | const MethodChannel channel = MethodChannel('flutterjsbridgeplugin'); 7 | 8 | TestWidgetsFlutterBinding.ensureInitialized(); 9 | 10 | setUp(() { 11 | channel.setMockMethodCallHandler((MethodCall methodCall) async { 12 | return '42'; 13 | }); 14 | }); 15 | 16 | tearDown(() { 17 | channel.setMockMethodCallHandler(null); 18 | }); 19 | 20 | test('getPlatformVersion', () async { 21 | // expect(await Flutterjsbridgeplugin.platformVersion, '42'); 22 | }); 23 | } 24 | -------------------------------------------------------------------------------- /example/web/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "flutterjsbridgeplugin_example", 3 | "short_name": "flutterjsbridgeplugin_example", 4 | "start_url": ".", 5 | "display": "standalone", 6 | "background_color": "#0175C2", 7 | "theme_color": "#0175C2", 8 | "description": "Demonstrates how to use the flutterjsbridgeplugin plugin.", 9 | "orientation": "portrait-primary", 10 | "prefer_related_applications": false, 11 | "icons": [ 12 | { 13 | "src": "icons/Icon-192.png", 14 | "sizes": "192x192", 15 | "type": "image/png" 16 | }, 17 | { 18 | "src": "icons/Icon-512.png", 19 | "sizes": "512x512", 20 | "type": "image/png" 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | group 'dev.epoll.flutterjsbridgeplugin' 2 | version '1.0' 3 | 4 | buildscript { 5 | repositories { 6 | google() 7 | jcenter() 8 | } 9 | 10 | dependencies { 11 | classpath 'com.android.tools.build:gradle:3.5.0' 12 | } 13 | } 14 | 15 | rootProject.allprojects { 16 | repositories { 17 | google() 18 | jcenter() 19 | maven { url 'https://jitpack.io' } 20 | } 21 | } 22 | 23 | apply plugin: 'com.android.library' 24 | 25 | android { 26 | compileSdkVersion 28 27 | 28 | defaultConfig { 29 | minSdkVersion 19 30 | } 31 | lintOptions { 32 | disable 'InvalidPackage' 33 | } 34 | } 35 | 36 | dependencies { 37 | implementation 'androidx.webkit:webkit:1.2.0' 38 | } -------------------------------------------------------------------------------- /ios/Classes/FlutterjsbridgepluginPlugin.m: -------------------------------------------------------------------------------- 1 | #import "FlutterjsbridgepluginPlugin.h" 2 | 3 | @implementation FlutterjsbridgepluginPlugin 4 | + (void)registerWithRegistrar:(NSObject*)registrar { 5 | FlutterMethodChannel* channel = [FlutterMethodChannel 6 | methodChannelWithName:@"flutterjsbridgeplugin" 7 | binaryMessenger:[registrar messenger]]; 8 | FlutterjsbridgepluginPlugin* instance = [[FlutterjsbridgepluginPlugin alloc] init]; 9 | [registrar addMethodCallDelegate:instance channel:channel]; 10 | } 11 | 12 | - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { 13 | if ([@"getPlatformVersion" isEqualToString:call.method]) { 14 | result([@"iOS " stringByAppendingString:[[UIDevice currentDevice] systemVersion]]); 15 | } else { 16 | result(FlutterMethodNotImplemented); 17 | } 18 | } 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | **/ios/Flutter/.last_build_id 26 | .dart_tool/ 27 | .flutter-plugins 28 | .flutter-plugins-dependencies 29 | .packages 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | 34 | # Web related 35 | lib/generated_plugin_registrant.dart 36 | 37 | # Symbolication related 38 | app.*.symbols 39 | 40 | # Obfuscation related 41 | app.*.map.json 42 | 43 | # Exceptions to above rules. 44 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 45 | -------------------------------------------------------------------------------- /example/ios/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Flutter (1.0.0) 3 | - flutter_jsbridge_plugin (0.0.1): 4 | - Flutter 5 | - webview_flutter (0.0.1): 6 | - Flutter 7 | 8 | DEPENDENCIES: 9 | - Flutter (from `Flutter`) 10 | - flutter_jsbridge_plugin (from `.symlinks/plugins/flutter_jsbridge_plugin/ios`) 11 | - webview_flutter (from `.symlinks/plugins/webview_flutter/ios`) 12 | 13 | EXTERNAL SOURCES: 14 | Flutter: 15 | :path: Flutter 16 | flutter_jsbridge_plugin: 17 | :path: ".symlinks/plugins/flutter_jsbridge_plugin/ios" 18 | webview_flutter: 19 | :path: ".symlinks/plugins/webview_flutter/ios" 20 | 21 | SPEC CHECKSUMS: 22 | Flutter: 0e3d915762c693b495b44d77113d4970485de6ec 23 | flutter_jsbridge_plugin: d4797308930960f65e3536c8a645039b2083004e 24 | webview_flutter: d2b4d6c66968ad042ad94cbb791f5b72b4678a96 25 | 26 | PODFILE CHECKSUM: 8e679eca47255a8ca8067c4c67aab20e64cb974d 27 | 28 | COCOAPODS: 1.9.3 29 | -------------------------------------------------------------------------------- /example/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 8.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /lib/flutterjsbridgeplugin.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:flutter/services.dart'; 4 | 5 | class Flutterjsbridgeplugin { 6 | static const MethodChannel _channel = 7 | const MethodChannel('flutterjsbridgeplugin'); 8 | 9 | Flutterjsbridgeplugin() { 10 | _channel.setMethodCallHandler(_onMethodCall); 11 | } 12 | 13 | static Future get platformVersion async { 14 | final String version = await _channel.invokeMethod('getPlatformVersion'); 15 | return version; 16 | } 17 | 18 | static Future get scrpit async { 19 | final String initScript = await _channel.invokeMethod("getScript"); 20 | return "javascript:$initScript"; 21 | } 22 | 23 | Future isMainThread() async { 24 | return await _channel.invokeMethod("isMainThread"); 25 | } 26 | 27 | Future handlerReturnData(String url) async { 28 | return await _channel.invokeMethod("handlerReturnData", url); 29 | } 30 | 31 | Future _onMethodCall(MethodCall call) async {} 32 | } 33 | -------------------------------------------------------------------------------- /flutterjsbridgeplugin.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /example/test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility that Flutter provides. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | import 'package:flutter/material.dart'; 9 | import 'package:flutter_test/flutter_test.dart'; 10 | 11 | import 'package:flutterjsbridgeplugin_example/main.dart'; 12 | 13 | void main() { 14 | testWidgets('Verify Platform version', (WidgetTester tester) async { 15 | // Build our app and trigger a frame. 16 | await tester.pumpWidget(MyApp()); 17 | 18 | // Verify that platform version is retrieved. 19 | expect( 20 | find.byWidgetPredicate( 21 | (Widget widget) => widget is Text && 22 | widget.data.startsWith('Running on:'), 23 | ), 24 | findsOneWidget, 25 | ); 26 | }); 27 | } 28 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /ios/flutter_jsbridge_plugin.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. 3 | # Run `pod lib lint flutterjsbridgeplugin.podspec' to validate before publishing. 4 | # 5 | Pod::Spec.new do |s| 6 | s.name = 'flutter_jsbridge_plugin' 7 | s.version = '0.0.1' 8 | s.summary = 'A JsBridge Flutter plugin.' 9 | s.description = <<-DESC 10 | A JsBridge Flutter plugin. 11 | DESC 12 | s.homepage = 'http://example.com' 13 | s.license = { :file => '../LICENSE' } 14 | s.author = { 'Your Company' => 'email@example.com' } 15 | s.source = { :path => '.' } 16 | s.source_files = 'Classes/**/*' 17 | s.public_header_files = 'Classes/**/*.h' 18 | s.dependency 'Flutter' 19 | s.platform = :ios, '8.0' 20 | 21 | # Flutter.framework does not contain a i386 slice. Only x86_64 simulators are supported. 22 | s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'VALID_ARCHS[sdk=iphonesimulator*]' => 'x86_64' } 23 | end 24 | -------------------------------------------------------------------------------- /example/web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | flutterjsbridgeplugin_example 18 | 19 | 20 | 21 | 24 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /example/ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | # platform :ios, '9.0' 3 | 4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 6 | 7 | project 'Runner', { 8 | 'Debug' => :debug, 9 | 'Profile' => :release, 10 | 'Release' => :release, 11 | } 12 | 13 | def flutter_root 14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) 15 | unless File.exist?(generated_xcode_build_settings_path) 16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" 17 | end 18 | 19 | File.foreach(generated_xcode_build_settings_path) do |line| 20 | matches = line.match(/FLUTTER_ROOT\=(.*)/) 21 | return matches[1].strip if matches 22 | end 23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" 24 | end 25 | 26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) 27 | 28 | flutter_ios_podfile_setup 29 | 30 | target 'Runner' do 31 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) 32 | end 33 | 34 | post_install do |installer| 35 | installer.pods_project.targets.each do |target| 36 | flutter_additional_ios_build_settings(target) 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Chromium Authors. All rights reserved. 2 | // 3 | // Redistribution and use in source and binary forms, with or without 4 | // modification, are permitted provided that the following conditions are 5 | // met: 6 | // 7 | // * Redistributions of source code must retain the above copyright 8 | // notice, this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above 10 | // copyright notice, this list of conditions and the following disclaimer 11 | // in the documentation and/or other materials provided with the 12 | // distribution. 13 | // * Neither the name of Google Inc. nor the names of its 14 | // contributors may be used to endorse or promote products derived from 15 | // this software without specific prior written permission. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /.idea/libraries/Dart_SDK.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 26 | 27 | android { 28 | compileSdkVersion 28 29 | 30 | lintOptions { 31 | disable 'InvalidPackage' 32 | } 33 | 34 | defaultConfig { 35 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 36 | applicationId "dev.epoll.flutterjsbridgeplugin_example" 37 | minSdkVersion 19 38 | targetSdkVersion 28 39 | versionCode flutterVersionCode.toInteger() 40 | versionName flutterVersionName 41 | } 42 | 43 | buildTypes { 44 | release { 45 | // TODO: Add your own signing config for the release build. 46 | // Signing with the debug keys for now, so `flutter run --release` works. 47 | signingConfig signingConfigs.debug 48 | } 49 | } 50 | } 51 | 52 | flutter { 53 | source '../..' 54 | } 55 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Add JsBridge Plugin to the WebView 2 | 3 | [A Flutter plugin that provides a JsBridge on WebView widget.](https://pub.dev/packages/bridge_webview_flutter) 4 | 5 | This plugin must introduce [webview_flutter](https://pub.dev/packages/webview_flutter) 6 | 7 | 8 | ## Usage 9 | Add `flutter_jsbridge_plugin` as a [dependency in your pubspec.yaml file](https://pub.dev/packages/flutter_jsbridge_plugin). 10 | ``` 11 | dependencies: 12 | flutter_jsbridge_plugin: ^0.0.5 13 | ``` 14 | ### Init JsBridge and register handler 15 | 16 | ``` 17 | ... 18 | final JsBridge _jsBridge = JsBridge(); 19 | ... 20 | WebView( 21 | initialUrl: "https://www.baidu.com?timeStamp=${new DateTime.now().millisecondsSinceEpoch}", 22 | javascriptMode: JavascriptMode.unrestricted, 23 | onWebViewCreated: (WebViewController webViewController) async { 24 | _jsBridge.loadJs(webViewController); 25 | _controller.complete(webViewController); 26 | _jsBridge.registerHandler("getToken", onCallBack: (data, func) { 27 | // return token to js 28 | func({"token": "token"}); 29 | }); 30 | _jsBridge.registerHandler("IAPpayment", onCallBack: (data, func) { 31 | print("js call flutter iap"); 32 | }); 33 | _jsBridge.registerHandler("back", onCallBack: (data, func) { 34 | print("js call flutter back"); 35 | }); 36 | }, 37 | navigationDelegate: (NavigationRequest request) { 38 | if (_jsBridge.handlerUrl(request.url)) { 39 | return NavigationDecision.navigate; 40 | } 41 | return NavigationDecision.prevent; 42 | }, 43 | onPageStarted: (url) { 44 | _jsBridge.init(); 45 | }, 46 | )) 47 | 48 | ``` 49 | 50 | ## JS Usage 51 | [js file](https://github.com/epoll-j/flutter_jsbridge_plugin/blob/master/JSBridge.js) 52 | -------------------------------------------------------------------------------- /lib/js_obj.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert' as convert; 2 | 3 | class JsRequest { 4 | String callbackId; 5 | String data; 6 | String handlerName; 7 | 8 | String toJson() { 9 | return convert.jsonEncode({ 10 | "callbackId": callbackId == null ? "" : callbackId, 11 | "data": data == null ? "" : data, 12 | "handlerName": handlerName == null ? "" : handlerName 13 | }); 14 | } 15 | } 16 | 17 | class JsMsg { 18 | String callbackId; //callbackId 19 | String responseId; //responseId 20 | String responseData; //responseData 21 | String data; //data of message 22 | String handlerName; 23 | 24 | JsMsg(); 25 | 26 | static List fromList(List list) { 27 | List msgList = []; 28 | for (Map json in list) { 29 | JsMsg msg = JsMsg(); 30 | msg.callbackId = json["callbackId"]; 31 | msg.responseId = json["responseId"]; 32 | msg.responseData = convert.jsonEncode(json["responseData"]); 33 | msg.data = convert.jsonEncode(json["data"]); 34 | msg.handlerName = json["handlerName"]; 35 | msgList.add(msg); 36 | } 37 | return msgList; 38 | } 39 | 40 | factory JsMsg.formJson(Map json) { 41 | JsMsg msg = JsMsg(); 42 | msg.callbackId = json["callbackId"]; 43 | msg.responseId = json["responseId"]; 44 | msg.responseData = convert.jsonEncode(json["responseData"]); 45 | msg.data = convert.jsonEncode(json["data"]); 46 | msg.handlerName = json["handlerName"]; 47 | return msg; 48 | } 49 | 50 | String toJson() { 51 | return convert.jsonEncode({ 52 | "callbackId": callbackId == null ? "" : callbackId, 53 | "responseId": responseId == null ? "" : responseId, 54 | "responseData": responseData == null ? "" : responseData, 55 | "data": data == null ? "" : data, 56 | "handlerName": handlerName == null ? "" : handlerName 57 | }); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /example/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSAppTransportSecurity 6 | 7 | NSAllowsArbitraryLoads 8 | 9 | 10 | CFBundleDevelopmentRegion 11 | $(DEVELOPMENT_LANGUAGE) 12 | CFBundleExecutable 13 | $(EXECUTABLE_NAME) 14 | CFBundleIdentifier 15 | $(PRODUCT_BUNDLE_IDENTIFIER) 16 | CFBundleInfoDictionaryVersion 17 | 6.0 18 | CFBundleName 19 | flutterjsbridgeplugin_example 20 | CFBundlePackageType 21 | APPL 22 | CFBundleShortVersionString 23 | $(FLUTTER_BUILD_NAME) 24 | CFBundleSignature 25 | ???? 26 | CFBundleVersion 27 | $(FLUTTER_BUILD_NUMBER) 28 | LSRequiresIPhoneOS 29 | 30 | UILaunchStoryboardName 31 | LaunchScreen 32 | UIMainStoryboardFile 33 | Main 34 | UISupportedInterfaceOrientations 35 | 36 | UIInterfaceOrientationPortrait 37 | UIInterfaceOrientationLandscapeLeft 38 | UIInterfaceOrientationLandscapeRight 39 | 40 | UISupportedInterfaceOrientations~ipad 41 | 42 | UIInterfaceOrientationPortrait 43 | UIInterfaceOrientationPortraitUpsideDown 44 | UIInterfaceOrientationLandscapeLeft 45 | UIInterfaceOrientationLandscapeRight 46 | 47 | UIViewControllerBasedStatusBarAppearance 48 | 49 | io.flutter.embedded_views_preview 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /JSBridge.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | let isAndroid = navigator.userAgent.indexOf('Android') > -1 || navigator.userAgent.indexOf('Adr') > -1 3 | let isiOS = !!navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/) 4 | 5 | // 这是必须要写的,用来创建一些设置 6 | function setupWebViewJavascriptBridge (callback) { 7 | // Android使用 8 | if (isAndroid) { 9 | if (window.WebViewJavascriptBridge) { 10 | callback(WebViewJavascriptBridge) 11 | } else { 12 | document.addEventListener( 13 | 'WebViewJavascriptBridgeReady', 14 | function () { 15 | callback(WebViewJavascriptBridge) 16 | }, 17 | false 18 | ) 19 | } 20 | console.log('tag', '安卓') 21 | sessionStorage.phoneType = 'android' 22 | } 23 | 24 | // iOS使用 25 | if (isiOS) { 26 | if (window.WebViewJavascriptBridge) { 27 | return callback(WebViewJavascriptBridge) 28 | } 29 | if (window.WVJBCallbacks) { 30 | return window.WVJBCallbacks.push(callback) 31 | } 32 | window.WVJBCallbacks = [callback] 33 | var WVJBIframe = document.createElement('iframe') 34 | WVJBIframe.style.display = 'none' 35 | WVJBIframe.src = 'wvjbscheme://__BRIDGE_LOADED__' 36 | document.documentElement.appendChild(WVJBIframe) 37 | setTimeout(function () { 38 | document.documentElement.removeChild(WVJBIframe) 39 | }, 0) 40 | console.log('tag', 'ios') 41 | sessionStorage.phoneType = 'ios' 42 | } 43 | } 44 | // 注册回调函数,第一次连接时调用 初始化函数(android需要初始化,ios不用) 45 | setupWebViewJavascriptBridge(function (bridge) { 46 | if (isAndroid) { 47 | // 初始化 48 | bridge.init(function (message, responseCallback) { 49 | var data = { 50 | 'Javascript Responds': 'Wee!' 51 | } 52 | responseCallback(data) 53 | }) 54 | } 55 | }) 56 | 57 | export default { 58 | // js调APP方法 (参数分别为:app提供的方法名 传给app的数据 回调) 59 | callHandler (name, data, callback) { 60 | setupWebViewJavascriptBridge(function (bridge) { 61 | bridge.callHandler(name, data, callback) 62 | }) 63 | }, 64 | // APP调js方法 (参数分别为:js提供的方法名 回调) 65 | registerHandler (name, callback) { 66 | setupWebViewJavascriptBridge(function (bridge) { 67 | bridge.registerHandler(name, function (data, responseCallback) { 68 | callback(data, responseCallback) 69 | }) 70 | }) 71 | } 72 | } 73 | 74 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flutter_jsbridge_plugin 2 | description: use jsbridge to webview in flutter 3 | version: 0.0.5 4 | homepage: https://github.com/epoll-j/flutter_jsbridge_plugin 5 | 6 | environment: 7 | sdk: ">=2.7.0 <3.0.0" 8 | flutter: ">=1.22.0" 9 | 10 | dependencies: 11 | flutter: 12 | sdk: flutter 13 | webview_flutter: ^2.1.0 14 | sprintf: ^4.0.2 15 | 16 | dev_dependencies: 17 | flutter_test: 18 | sdk: flutter 19 | 20 | # For information on the generic Dart part of this file, see the 21 | # following page: https://dart.dev/tools/pub/pubspec 22 | 23 | # The following section is specific to Flutter. 24 | flutter: 25 | # This section identifies this Flutter project as a plugin project. 26 | # The 'pluginClass' and Android 'package' identifiers should not ordinarily 27 | # be modified. They are used by the tooling to maintain consistency when 28 | # adding or updating assets for this project. 29 | plugin: 30 | platforms: 31 | android: 32 | package: dev.epoll.flutterjsbridgeplugin 33 | pluginClass: FlutterjsbridgepluginPlugin 34 | ios: 35 | pluginClass: FlutterjsbridgepluginPlugin 36 | 37 | # To add assets to your plugin package, add an assets section, like this: 38 | # assets: 39 | # - images/a_dot_burr.jpeg 40 | # - images/a_dot_ham.jpeg 41 | # 42 | # For details regarding assets in packages, see 43 | # https://flutter.dev/assets-and-images/#from-packages 44 | # 45 | # An image asset can refer to one or more resolution-specific "variants", see 46 | # https://flutter.dev/assets-and-images/#resolution-aware. 47 | 48 | # To add custom fonts to your plugin package, add a fonts section here, 49 | # in this "flutter" section. Each entry in this list should have a 50 | # "family" key with the font family name, and a "fonts" key with a 51 | # list giving the asset and other descriptors for the font. For 52 | # example: 53 | # fonts: 54 | # - family: Schyler 55 | # fonts: 56 | # - asset: fonts/Schyler-Regular.ttf 57 | # - asset: fonts/Schyler-Italic.ttf 58 | # style: italic 59 | # - family: Trajan Pro 60 | # fonts: 61 | # - asset: fonts/TrajanPro.ttf 62 | # - asset: fonts/TrajanPro_Bold.ttf 63 | # weight: 700 64 | # 65 | # For details regarding fonts in packages, see 66 | # https://flutter.dev/custom-fonts/#from-packages 67 | -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flutterjsbridgeplugin_example 2 | description: Demonstrates how to use the flutterjsbridgeplugin plugin. 3 | 4 | # The following line prevents the package from being accidentally published to 5 | # pub.dev using `pub publish`. This is preferred for private packages. 6 | publish_to: 'none' # Remove this line if you wish to publish to pub.dev 7 | 8 | environment: 9 | sdk: ">=2.7.0 <3.0.0" 10 | 11 | dependencies: 12 | flutter: 13 | sdk: flutter 14 | 15 | flutter_jsbridge_plugin: 16 | # When depending on this package from a real application you should use: 17 | # flutterjsbridgeplugin: ^x.y.z 18 | # See https://dart.dev/tools/pub/dependencies#version-constraints 19 | # The example app is bundled with the plugin so we use a path dependency on 20 | # the parent directory to use the current plugin's version. 21 | path: ../ 22 | 23 | # The following adds the Cupertino Icons font to your application. 24 | # Use with the CupertinoIcons class for iOS style icons. 25 | cupertino_icons: ^0.1.3 26 | webview_flutter: ^2.1.0 27 | 28 | dev_dependencies: 29 | flutter_test: 30 | sdk: flutter 31 | 32 | # For information on the generic Dart part of this file, see the 33 | # following page: https://dart.dev/tools/pub/pubspec 34 | 35 | # The following section is specific to Flutter. 36 | flutter: 37 | 38 | # The following line ensures that the Material Icons font is 39 | # included with your application, so that you can use the icons in 40 | # the material Icons class. 41 | uses-material-design: true 42 | 43 | # To add assets to your application, add an assets section, like this: 44 | # assets: 45 | # - images/a_dot_burr.jpeg 46 | # - images/a_dot_ham.jpeg 47 | 48 | # An image asset can refer to one or more resolution-specific "variants", see 49 | # https://flutter.dev/assets-and-images/#resolution-aware. 50 | 51 | # For details regarding adding assets from package dependencies, see 52 | # https://flutter.dev/assets-and-images/#from-packages 53 | 54 | # To add custom fonts to your application, add a fonts section here, 55 | # in this "flutter" section. Each entry in this list should have a 56 | # "family" key with the font family name, and a "fonts" key with a 57 | # list giving the asset and other descriptors for the font. For 58 | # example: 59 | # fonts: 60 | # - family: Schyler 61 | # fonts: 62 | # - asset: fonts/Schyler-Regular.ttf 63 | # - asset: fonts/Schyler-Italic.ttf 64 | # style: italic 65 | # - family: Trajan Pro 66 | # fonts: 67 | # - asset: fonts/TrajanPro.ttf 68 | # - asset: fonts/TrajanPro_Bold.ttf 69 | # weight: 700 70 | # 71 | # For details regarding fonts from package dependencies, 72 | # see https://flutter.dev/custom-fonts/#from-packages 73 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 4 | 9 | 15 | 22 | 26 | 30 | 35 | 39 | 40 | 41 | 42 | 43 | 44 | 46 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'dart:async'; 3 | 4 | import 'package:flutter/services.dart'; 5 | import 'package:flutter_jsbridge_plugin/flutterjsbridgeplugin.dart'; 6 | import 'package:flutter_jsbridge_plugin/js_bridge.dart'; 7 | import 'package:webview_flutter/webview_flutter.dart'; 8 | 9 | void main() { 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyApp extends StatefulWidget { 14 | @override 15 | _MyAppState createState() => _MyAppState(); 16 | } 17 | 18 | class _MyAppState extends State { 19 | String _platformVersion = 'Unknown'; 20 | 21 | final Completer _controller = 22 | Completer(); 23 | final JsBridge _jsBridge = JsBridge(); 24 | 25 | @override 26 | void initState() { 27 | super.initState(); 28 | initPlatformState(); 29 | } 30 | 31 | // Platform messages are asynchronous, so we initialize in an async method. 32 | Future initPlatformState() async { 33 | String platformVersion; 34 | // Platform messages may fail, so we use a try/catch PlatformException. 35 | try { 36 | platformVersion = await Flutterjsbridgeplugin.platformVersion; 37 | } on PlatformException { 38 | platformVersion = 'Failed to get platform version.'; 39 | } 40 | 41 | // If the widget was removed from the tree while the asynchronous platform 42 | // message was in flight, we want to discard the reply rather than calling 43 | // setState to update our non-existent appearance. 44 | if (!mounted) return; 45 | 46 | setState(() { 47 | _platformVersion = platformVersion; 48 | }); 49 | } 50 | 51 | @override 52 | Widget build(BuildContext context) { 53 | return MaterialApp( 54 | home: Scaffold( 55 | appBar: AppBar( 56 | title: const Text('Plugin example app'), 57 | ), 58 | body: WebView( 59 | initialUrl: "https://juejin.cn?timeStamp=${new DateTime.now().millisecondsSinceEpoch}", 60 | javascriptMode: JavascriptMode.unrestricted, 61 | onWebViewCreated: (WebViewController webViewController) async { 62 | _jsBridge.loadJs(webViewController); 63 | _controller.complete(webViewController); 64 | _jsBridge.registerHandler("getToken", onCallBack: (data, func) { 65 | // return token to js 66 | func({"token": "token"}); 67 | }); 68 | _jsBridge.registerHandler("IAPpayment", onCallBack: (data, func) { 69 | print("js call flutter iap"); 70 | }); 71 | _jsBridge.registerHandler("back", onCallBack: (data, func) { 72 | print("js call flutter back"); 73 | }); 74 | 75 | }, 76 | navigationDelegate: (NavigationRequest request) { 77 | if (_jsBridge.handlerUrl(request.url)) { 78 | return NavigationDecision.navigate; 79 | } 80 | return NavigationDecision.prevent; 81 | }, 82 | onPageStarted: (url) { 83 | _jsBridge.init(); 84 | }, 85 | )), 86 | ); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /android/src/main/java/dev/epoll/flutterjsbridgeplugin/FlutterjsbridgepluginPlugin.java: -------------------------------------------------------------------------------- 1 | package dev.epoll.flutterjsbridgeplugin; 2 | 3 | import android.app.Activity; 4 | import android.os.Looper; 5 | 6 | import androidx.annotation.NonNull; 7 | 8 | import io.flutter.embedding.engine.plugins.FlutterPlugin; 9 | import io.flutter.embedding.engine.plugins.activity.ActivityAware; 10 | import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding; 11 | import io.flutter.plugin.common.MethodCall; 12 | import io.flutter.plugin.common.MethodChannel; 13 | import io.flutter.plugin.common.MethodChannel.MethodCallHandler; 14 | import io.flutter.plugin.common.MethodChannel.Result; 15 | import io.flutter.plugin.common.PluginRegistry.Registrar; 16 | 17 | /** 18 | * FlutterjsbridgepluginPlugin 19 | */ 20 | public class FlutterjsbridgepluginPlugin implements FlutterPlugin, MethodCallHandler, ActivityAware { 21 | /// The MethodChannel that will the communication between Flutter and native Android 22 | /// 23 | /// This local reference serves to register the plugin with the Flutter Engine and unregister it 24 | /// when the Flutter Engine is detached from the Activity 25 | private MethodChannel channel; 26 | private Activity activity; 27 | private boolean hook = false; 28 | 29 | private void setActivity(Activity activity) { 30 | this.activity = activity; 31 | } 32 | 33 | @Override 34 | public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) { 35 | channel = new MethodChannel(flutterPluginBinding.getFlutterEngine().getDartExecutor(), "flutterjsbridgeplugin"); 36 | channel.setMethodCallHandler(this); 37 | } 38 | 39 | @Override 40 | public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) { 41 | activity = binding.getActivity(); 42 | } 43 | 44 | @Override 45 | public void onDetachedFromActivityForConfigChanges() { 46 | 47 | } 48 | 49 | @Override 50 | public void onReattachedToActivityForConfigChanges(ActivityPluginBinding binding) { 51 | activity = binding.getActivity(); 52 | } 53 | 54 | @Override 55 | public void onDetachedFromActivity() { 56 | 57 | } 58 | 59 | // This static function is optional and equivalent to onAttachedToEngine. It supports the old 60 | // pre-Flutter-1.12 Android projects. You are encouraged to continue supporting 61 | // plugin registration via this function while apps migrate to use the new Android APIs 62 | // post-flutter-1.12 via https://flutter.dev/go/android-project-migration. 63 | // 64 | // It is encouraged to share logic between onAttachedToEngine and registerWith to keep 65 | // them functionally equivalent. Only one of onAttachedToEngine or registerWith will be called 66 | // depending on the user's project. onAttachedToEngine or registerWith must both be defined 67 | // in the same class. 68 | public static void registerWith(Registrar registrar) { 69 | final MethodChannel channel = new MethodChannel(registrar.messenger(), "flutterjsbridgeplugin"); 70 | FlutterjsbridgepluginPlugin plugin = new FlutterjsbridgepluginPlugin(); 71 | plugin.setActivity(registrar.activity()); 72 | channel.setMethodCallHandler(plugin); 73 | } 74 | 75 | // diankechengjin.cn/b/index 76 | @Override 77 | public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) { 78 | if (call.method.equals("getPlatformVersion")) { 79 | result.success("Android" + android.os.Build.VERSION.RELEASE); 80 | } else { 81 | result.notImplemented(); 82 | } 83 | } 84 | 85 | @Override 86 | public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { 87 | channel.setMethodCallHandler(null); 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | xmlns:android 14 | 15 | ^$ 16 | 17 | 18 | 19 |
20 |
21 | 22 | 23 | 24 | xmlns:.* 25 | 26 | ^$ 27 | 28 | 29 | BY_NAME 30 | 31 |
32 |
33 | 34 | 35 | 36 | .*:id 37 | 38 | http://schemas.android.com/apk/res/android 39 | 40 | 41 | 42 |
43 |
44 | 45 | 46 | 47 | .*:name 48 | 49 | http://schemas.android.com/apk/res/android 50 | 51 | 52 | 53 |
54 |
55 | 56 | 57 | 58 | name 59 | 60 | ^$ 61 | 62 | 63 | 64 |
65 |
66 | 67 | 68 | 69 | style 70 | 71 | ^$ 72 | 73 | 74 | 75 |
76 |
77 | 78 | 79 | 80 | .* 81 | 82 | ^$ 83 | 84 | 85 | BY_NAME 86 | 87 |
88 |
89 | 90 | 91 | 92 | .* 93 | 94 | http://schemas.android.com/apk/res/android 95 | 96 | 97 | ANDROID_ATTRIBUTE_ORDER 98 | 99 |
100 |
101 | 102 | 103 | 104 | .* 105 | 106 | .* 107 | 108 | 109 | BY_NAME 110 | 111 |
112 |
113 |
114 |
115 |
116 |
-------------------------------------------------------------------------------- /lib/js_bridge.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | import 'package:webview_flutter/webview_flutter.dart'; 4 | import 'dart:convert' as convert; 5 | import 'package:sprintf/sprintf.dart'; 6 | 7 | import 'init_script.dart'; 8 | import 'js_obj.dart'; 9 | 10 | typedef CallBackFunction = void Function(dynamic data); 11 | typedef BridgeHandler = void Function(dynamic data, CallBackFunction function); 12 | 13 | class JsBridge { 14 | WebViewController _webViewController; 15 | Map _callbacks = Map(); 16 | Map _handlers = Map(); 17 | int _uniqueId = 0; 18 | static final String _protocolScheme = "jsbridge://"; 19 | final String _fetchData = "${_protocolScheme}return/fetch"; 20 | final String _returnData = "${_protocolScheme}return/sendMsg/"; 21 | String _dartToJs = 22 | "javascript:WebViewJavascriptBridge._handleMessageFromNative('%s');"; 23 | 24 | void loadJs(WebViewController controller) { 25 | _webViewController = controller; 26 | init(); 27 | } 28 | 29 | void init() { 30 | if (_webViewController == null) { 31 | throw "WebViewController must not null"; 32 | } 33 | if (Platform.isIOS) { 34 | _loadJs(init_script_ios); 35 | } else { 36 | _loadJs(init_script_android); 37 | } 38 | // test(); 39 | } 40 | 41 | bool handlerUrl(String url) { 42 | return _handlerReturnData(url); 43 | } 44 | 45 | bool _handlerReturnData(String url) { 46 | if (url.startsWith(_protocolScheme)) { 47 | if (url == _fetchData) { 48 | _fetchQueue(); 49 | } else { 50 | List list = JsMsg.fromList(convert 51 | .jsonDecode(Uri.decodeComponent(url).replaceAll(_returnData, ""))); 52 | print(list); 53 | for (JsMsg msg in list) { 54 | print(msg); 55 | if (msg.responseId != null) { 56 | 57 | } else { 58 | CallBackFunction function; 59 | if (msg.callbackId != null) { 60 | if (msg.callbackId != null) { 61 | function = (dynamic data) { 62 | JsMsg callbackMsg = JsMsg(); 63 | callbackMsg.responseId = msg.callbackId; 64 | callbackMsg.responseData = convert.jsonEncode(data); 65 | // 发送 66 | _loadJs(sprintf(_dartToJs, [_replaceJson(callbackMsg.toJson())])); 67 | }; 68 | } 69 | } else { 70 | function = (dynamic data) {}; 71 | } 72 | BridgeHandler handler; 73 | if (msg.handlerName != null) { 74 | handler = _handlers[msg.handlerName]; 75 | } 76 | if (handler != null) { 77 | handler.call(msg.data, function); 78 | } 79 | } 80 | } 81 | } 82 | return false; 83 | } 84 | return true; 85 | } 86 | 87 | void _fetchQueue() { 88 | _loadJs("WebViewJavascriptBridge._fetchQueue()"); 89 | } 90 | 91 | void callHandler(String handlerName, 92 | {dynamic data, CallBackFunction onCallBack}) { 93 | JsRequest request = JsRequest(); 94 | request.handlerName = handlerName; 95 | if (data != null) { 96 | if (data is String) { 97 | request.data = data; 98 | } else { 99 | request.data = convert.jsonEncode(data); 100 | } 101 | } 102 | request.callbackId = _generateId(); 103 | if (onCallBack != null) { 104 | _callbacks[request.callbackId] = onCallBack; 105 | } 106 | _loadJs(sprintf(_dartToJs, [_replaceJson(request.toJson())])); 107 | } 108 | 109 | void registerHandler(String handlerName, 110 | {dynamic data, BridgeHandler onCallBack}) { 111 | if (onCallBack != null) { 112 | _handlers[handlerName] = onCallBack; 113 | } 114 | } 115 | 116 | String _generateId() { 117 | return "flutter_cb_${_uniqueId++}"; 118 | } 119 | 120 | String _replaceJson(String json) { 121 | json = json.replaceAll("\\", "\\\\"); 122 | return json; 123 | } 124 | 125 | void _loadJs(String script) { 126 | _webViewController.evaluateJavascript(script); 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | async: 5 | dependency: transitive 6 | description: 7 | name: async 8 | url: "https://pub.dartlang.org" 9 | source: hosted 10 | version: "2.8.1" 11 | boolean_selector: 12 | dependency: transitive 13 | description: 14 | name: boolean_selector 15 | url: "https://pub.dartlang.org" 16 | source: hosted 17 | version: "2.1.0" 18 | characters: 19 | dependency: transitive 20 | description: 21 | name: characters 22 | url: "https://pub.dartlang.org" 23 | source: hosted 24 | version: "1.1.0" 25 | charcode: 26 | dependency: transitive 27 | description: 28 | name: charcode 29 | url: "https://pub.dartlang.org" 30 | source: hosted 31 | version: "1.3.1" 32 | clock: 33 | dependency: transitive 34 | description: 35 | name: clock 36 | url: "https://pub.dartlang.org" 37 | source: hosted 38 | version: "1.1.0" 39 | collection: 40 | dependency: transitive 41 | description: 42 | name: collection 43 | url: "https://pub.dartlang.org" 44 | source: hosted 45 | version: "1.15.0" 46 | fake_async: 47 | dependency: transitive 48 | description: 49 | name: fake_async 50 | url: "https://pub.dartlang.org" 51 | source: hosted 52 | version: "1.2.0" 53 | flutter: 54 | dependency: "direct main" 55 | description: flutter 56 | source: sdk 57 | version: "0.0.0" 58 | flutter_test: 59 | dependency: "direct dev" 60 | description: flutter 61 | source: sdk 62 | version: "0.0.0" 63 | matcher: 64 | dependency: transitive 65 | description: 66 | name: matcher 67 | url: "https://pub.dartlang.org" 68 | source: hosted 69 | version: "0.12.10" 70 | meta: 71 | dependency: transitive 72 | description: 73 | name: meta 74 | url: "https://pub.dartlang.org" 75 | source: hosted 76 | version: "1.7.0" 77 | path: 78 | dependency: transitive 79 | description: 80 | name: path 81 | url: "https://pub.dartlang.org" 82 | source: hosted 83 | version: "1.8.0" 84 | plugin_platform_interface: 85 | dependency: transitive 86 | description: 87 | name: plugin_platform_interface 88 | url: "https://pub.dartlang.org" 89 | source: hosted 90 | version: "2.0.2" 91 | sky_engine: 92 | dependency: transitive 93 | description: flutter 94 | source: sdk 95 | version: "0.0.99" 96 | source_span: 97 | dependency: transitive 98 | description: 99 | name: source_span 100 | url: "https://pub.dartlang.org" 101 | source: hosted 102 | version: "1.8.1" 103 | sprintf: 104 | dependency: "direct main" 105 | description: 106 | name: sprintf 107 | url: "https://pub.dartlang.org" 108 | source: hosted 109 | version: "4.1.0" 110 | stack_trace: 111 | dependency: transitive 112 | description: 113 | name: stack_trace 114 | url: "https://pub.dartlang.org" 115 | source: hosted 116 | version: "1.10.0" 117 | stream_channel: 118 | dependency: transitive 119 | description: 120 | name: stream_channel 121 | url: "https://pub.dartlang.org" 122 | source: hosted 123 | version: "2.1.0" 124 | string_scanner: 125 | dependency: transitive 126 | description: 127 | name: string_scanner 128 | url: "https://pub.dartlang.org" 129 | source: hosted 130 | version: "1.1.0" 131 | term_glyph: 132 | dependency: transitive 133 | description: 134 | name: term_glyph 135 | url: "https://pub.dartlang.org" 136 | source: hosted 137 | version: "1.2.0" 138 | test_api: 139 | dependency: transitive 140 | description: 141 | name: test_api 142 | url: "https://pub.dartlang.org" 143 | source: hosted 144 | version: "0.4.2" 145 | typed_data: 146 | dependency: transitive 147 | description: 148 | name: typed_data 149 | url: "https://pub.dartlang.org" 150 | source: hosted 151 | version: "1.3.0" 152 | vector_math: 153 | dependency: transitive 154 | description: 155 | name: vector_math 156 | url: "https://pub.dartlang.org" 157 | source: hosted 158 | version: "2.1.0" 159 | webview_flutter: 160 | dependency: "direct main" 161 | description: 162 | name: webview_flutter 163 | url: "https://pub.dartlang.org" 164 | source: hosted 165 | version: "2.3.0" 166 | webview_flutter_android: 167 | dependency: transitive 168 | description: 169 | name: webview_flutter_android 170 | url: "https://pub.dartlang.org" 171 | source: hosted 172 | version: "2.2.1" 173 | webview_flutter_platform_interface: 174 | dependency: transitive 175 | description: 176 | name: webview_flutter_platform_interface 177 | url: "https://pub.dartlang.org" 178 | source: hosted 179 | version: "1.4.0" 180 | webview_flutter_wkwebview: 181 | dependency: transitive 182 | description: 183 | name: webview_flutter_wkwebview 184 | url: "https://pub.dartlang.org" 185 | source: hosted 186 | version: "2.2.0" 187 | sdks: 188 | dart: ">=2.14.0 <3.0.0" 189 | flutter: ">=2.5.0" 190 | -------------------------------------------------------------------------------- /example/pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | async: 5 | dependency: transitive 6 | description: 7 | name: async 8 | url: "https://pub.dartlang.org" 9 | source: hosted 10 | version: "2.8.1" 11 | boolean_selector: 12 | dependency: transitive 13 | description: 14 | name: boolean_selector 15 | url: "https://pub.dartlang.org" 16 | source: hosted 17 | version: "2.1.0" 18 | characters: 19 | dependency: transitive 20 | description: 21 | name: characters 22 | url: "https://pub.dartlang.org" 23 | source: hosted 24 | version: "1.1.0" 25 | charcode: 26 | dependency: transitive 27 | description: 28 | name: charcode 29 | url: "https://pub.dartlang.org" 30 | source: hosted 31 | version: "1.3.1" 32 | clock: 33 | dependency: transitive 34 | description: 35 | name: clock 36 | url: "https://pub.dartlang.org" 37 | source: hosted 38 | version: "1.1.0" 39 | collection: 40 | dependency: transitive 41 | description: 42 | name: collection 43 | url: "https://pub.dartlang.org" 44 | source: hosted 45 | version: "1.15.0" 46 | cupertino_icons: 47 | dependency: "direct main" 48 | description: 49 | name: cupertino_icons 50 | url: "https://pub.dartlang.org" 51 | source: hosted 52 | version: "0.1.3" 53 | fake_async: 54 | dependency: transitive 55 | description: 56 | name: fake_async 57 | url: "https://pub.dartlang.org" 58 | source: hosted 59 | version: "1.2.0" 60 | flutter: 61 | dependency: "direct main" 62 | description: flutter 63 | source: sdk 64 | version: "0.0.0" 65 | flutter_jsbridge_plugin: 66 | dependency: "direct main" 67 | description: 68 | path: ".." 69 | relative: true 70 | source: path 71 | version: "0.0.5" 72 | flutter_test: 73 | dependency: "direct dev" 74 | description: flutter 75 | source: sdk 76 | version: "0.0.0" 77 | matcher: 78 | dependency: transitive 79 | description: 80 | name: matcher 81 | url: "https://pub.dartlang.org" 82 | source: hosted 83 | version: "0.12.10" 84 | meta: 85 | dependency: transitive 86 | description: 87 | name: meta 88 | url: "https://pub.dartlang.org" 89 | source: hosted 90 | version: "1.7.0" 91 | path: 92 | dependency: transitive 93 | description: 94 | name: path 95 | url: "https://pub.dartlang.org" 96 | source: hosted 97 | version: "1.8.0" 98 | plugin_platform_interface: 99 | dependency: transitive 100 | description: 101 | name: plugin_platform_interface 102 | url: "https://pub.dartlang.org" 103 | source: hosted 104 | version: "2.0.2" 105 | sky_engine: 106 | dependency: transitive 107 | description: flutter 108 | source: sdk 109 | version: "0.0.99" 110 | source_span: 111 | dependency: transitive 112 | description: 113 | name: source_span 114 | url: "https://pub.dartlang.org" 115 | source: hosted 116 | version: "1.8.1" 117 | sprintf: 118 | dependency: transitive 119 | description: 120 | name: sprintf 121 | url: "https://pub.dartlang.org" 122 | source: hosted 123 | version: "4.1.0" 124 | stack_trace: 125 | dependency: transitive 126 | description: 127 | name: stack_trace 128 | url: "https://pub.dartlang.org" 129 | source: hosted 130 | version: "1.10.0" 131 | stream_channel: 132 | dependency: transitive 133 | description: 134 | name: stream_channel 135 | url: "https://pub.dartlang.org" 136 | source: hosted 137 | version: "2.1.0" 138 | string_scanner: 139 | dependency: transitive 140 | description: 141 | name: string_scanner 142 | url: "https://pub.dartlang.org" 143 | source: hosted 144 | version: "1.1.0" 145 | term_glyph: 146 | dependency: transitive 147 | description: 148 | name: term_glyph 149 | url: "https://pub.dartlang.org" 150 | source: hosted 151 | version: "1.2.0" 152 | test_api: 153 | dependency: transitive 154 | description: 155 | name: test_api 156 | url: "https://pub.dartlang.org" 157 | source: hosted 158 | version: "0.4.2" 159 | typed_data: 160 | dependency: transitive 161 | description: 162 | name: typed_data 163 | url: "https://pub.dartlang.org" 164 | source: hosted 165 | version: "1.3.0" 166 | vector_math: 167 | dependency: transitive 168 | description: 169 | name: vector_math 170 | url: "https://pub.dartlang.org" 171 | source: hosted 172 | version: "2.1.0" 173 | webview_flutter: 174 | dependency: "direct main" 175 | description: 176 | name: webview_flutter 177 | url: "https://pub.dartlang.org" 178 | source: hosted 179 | version: "2.3.0" 180 | webview_flutter_android: 181 | dependency: transitive 182 | description: 183 | name: webview_flutter_android 184 | url: "https://pub.dartlang.org" 185 | source: hosted 186 | version: "2.2.1" 187 | webview_flutter_platform_interface: 188 | dependency: transitive 189 | description: 190 | name: webview_flutter_platform_interface 191 | url: "https://pub.dartlang.org" 192 | source: hosted 193 | version: "1.4.0" 194 | webview_flutter_wkwebview: 195 | dependency: transitive 196 | description: 197 | name: webview_flutter_wkwebview 198 | url: "https://pub.dartlang.org" 199 | source: hosted 200 | version: "2.2.0" 201 | sdks: 202 | dart: ">=2.14.0 <3.0.0" 203 | flutter: ">=2.5.0" 204 | -------------------------------------------------------------------------------- /.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 27 | 28 | 29 | 34 | 35 | 36 | 39 | 40 | 41 | 42 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 1592962334458 69 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /lib/init_script.dart: -------------------------------------------------------------------------------- 1 | // ignore: non_constant_identifier_names 2 | String init_script_android = ''' 3 | (function() { 4 | if (window.WebViewJavascriptBridge) { 5 | return; 6 | } 7 | 8 | var lastCallTime = 0; 9 | var stoId = null; 10 | var FETCH_QUEUE = 50; 11 | 12 | var messagingIframe; 13 | var sendMessageQueue = []; 14 | var receiveMessageQueue = []; 15 | var messageHandlers = {}; 16 | var timer = null; 17 | 18 | var CUSTOM_PROTOCOL_SCHEME = 'jsbridge'; 19 | var QUEUE_HAS_MESSAGE = '__QUEUE_MESSAGE__/'; 20 | 21 | var responseCallbacks = {}; 22 | var uniqueId = 1; 23 | 24 | var base64encodechars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 25 | function base64encode(str) { 26 | if (str === undefined) { 27 | return str; 28 | } 29 | 30 | var out, i, len; 31 | var c1, c2, c3; 32 | len = str.length; 33 | i = 0; 34 | out = ""; 35 | while (i < len) { 36 | c1 = str.charCodeAt(i++) & 0xff; 37 | if (i == len) { 38 | out += base64encodechars.charAt(c1 >> 2); 39 | out += base64encodechars.charAt((c1 & 0x3) << 4); 40 | out += "=="; 41 | break; 42 | } 43 | c2 = str.charCodeAt(i++); 44 | if (i == len) { 45 | out += base64encodechars.charAt(c1 >> 2); 46 | out += base64encodechars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xf0) >> 4)); 47 | out += base64encodechars.charAt((c2 & 0xf) << 2); 48 | out += "="; 49 | break; 50 | } 51 | c3 = str.charCodeAt(i++); 52 | out += base64encodechars.charAt(c1 >> 2); 53 | out += base64encodechars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xf0) >> 4)); 54 | out += base64encodechars.charAt(((c2 & 0xf) << 2) | ((c3 & 0xc0) >> 6)); 55 | out += base64encodechars.charAt(c3 & 0x3f); 56 | } 57 | return out; 58 | } 59 | 60 | 61 | function _createQueueReadyIframe(doc) { 62 | // messagingIframe = doc.createElement('iframe'); 63 | // messagingIframe.style.display = 'none'; 64 | // doc.documentElement.appendChild(messagingIframe); 65 | } 66 | 67 | function isAndroid() { 68 | var ua = navigator.userAgent.toLowerCase(); 69 | var isA = ua.indexOf("android") > -1; 70 | if (isA) { 71 | return true; 72 | } 73 | return false; 74 | } 75 | 76 | function isIphone() { 77 | var ua = navigator.userAgent.toLowerCase(); 78 | var isIph = ua.indexOf("iphone") > -1; 79 | if (isIph) { 80 | return true; 81 | } 82 | return false; 83 | } 84 | 85 | //set default messageHandler 86 | function init(messageHandler) { 87 | if (WebViewJavascriptBridge._messageHandler) { 88 | throw new Error('WebViewJavascriptBridge.init called twice'); 89 | } 90 | WebViewJavascriptBridge._messageHandler = messageHandler; 91 | var receivedMessages = receiveMessageQueue; 92 | receiveMessageQueue = null; 93 | for (var i = 0; i < receivedMessages.length; i++) { 94 | _dispatchMessageFromNative(receivedMessages[i]); 95 | } 96 | } 97 | 98 | function send(data, responseCallback) { 99 | _doSend({ 100 | data: data 101 | }, responseCallback); 102 | } 103 | 104 | function registerHandler(handlerName, handler) { 105 | messageHandlers[handlerName] = handler; 106 | } 107 | 108 | function callHandler(handlerName, data, responseCallback) { 109 | console.log(handlerName); 110 | _doSend({ 111 | handlerName: handlerName, 112 | data: data 113 | }, responseCallback); 114 | } 115 | 116 | //sendMessage add message, 触发native处理 sendMessage 117 | function _doSend(message, responseCallback) { 118 | console.log('send'); 119 | if (responseCallback) { 120 | var callbackId = 'cb_' + (uniqueId++) + '_' + new Date().getTime(); 121 | responseCallbacks[callbackId] = responseCallback; 122 | message.callbackId = callbackId; 123 | } 124 | sendMessageQueue.push(message); 125 | if (!timer) { 126 | timer = setTimeout(function() { 127 | _getIframe().src = CUSTOM_PROTOCOL_SCHEME + '://return/sendMsg/' + encodeURIComponent(JSON.stringify(sendMessageQueue)); 128 | sendMessageQueue = []; 129 | timer = null; 130 | }, 30); 131 | } 132 | } 133 | 134 | // 提供给native调用,该函数作用:获取sendMessageQueue返回给native,由于android不能直接获取返回的内容,所以使用url shouldOverrideUrlLoading 的方式返回内容 135 | function _fetchQueue() { 136 | if (sendMessageQueue.length === 0) { 137 | return; 138 | } 139 | 140 | if (new Date().getTime() - lastCallTime < FETCH_QUEUE) { 141 | if (!stoId) { 142 | stoId = setTimeout(_fetchQueue, FETCH_QUEUE); 143 | } 144 | return; 145 | } 146 | 147 | lastCallTime = new Date().getTime(); 148 | stoId = null; 149 | 150 | var messageQueueString = JSON.stringify(sendMessageQueue); 151 | sendMessageQueue = []; 152 | if (messageQueueString === '[]') { 153 | return; 154 | } 155 | 156 | _getIframe().src = CUSTOM_PROTOCOL_SCHEME + '://return/sendMsg/' + encodeURIComponent(messageQueueString); 157 | 158 | // var messageQueueString = JSON.stringify(sendMessageQueue); 159 | // sendMessageQueue = []; 160 | // //add by hq 161 | // if (isIphone()) { 162 | // return messageQueueString; 163 | // //android can't read directly the return data, so we can reload iframe src to communicate with java 164 | // } else if (isAndroid()) { 165 | // messagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://return/sendMsg/' + encodeURIComponent(messageQueueString); 166 | // } 167 | } 168 | 169 | //提供给native使用, 170 | function _dispatchMessageFromNative(messageJSON) { 171 | setTimeout(function() { 172 | var message = JSON.parse(messageJSON); 173 | var responseCallback; 174 | //java call finished, now need to call js callback function 175 | if (message.responseId) { 176 | responseCallback = responseCallbacks[message.responseId]; 177 | if (!responseCallback) { 178 | return; 179 | } 180 | responseCallback(message.responseData); 181 | delete responseCallbacks[message.responseId]; 182 | } else { 183 | //直接发送 184 | if (message.callbackId) { 185 | var callbackResponseId = message.callbackId; 186 | responseCallback = function(responseData) { 187 | _doSend({ 188 | responseId: callbackResponseId, 189 | responseData: responseData 190 | }); 191 | }; 192 | } 193 | var handler = WebViewJavascriptBridge._messageHandler; 194 | if (message.handlerName) { 195 | handler = messageHandlers[message.handlerName]; 196 | } 197 | //查找指定handler 198 | try { 199 | handler(message.data, responseCallback); 200 | } catch (exception) { 201 | if (typeof console != 'undefined') { 202 | console.log("WebViewJavascriptBridge: WARNING: javascript handler threw.", message, exception); 203 | } 204 | } 205 | } 206 | }); 207 | } 208 | 209 | //提供给native调用,receiveMessageQueue 在会在页面加载完后赋值为null,所以 210 | function _handleMessageFromNative(messageJSON) { 211 | // if (receiveMessageQueue) { 212 | // receiveMessageQueue.push(messageJSON); 213 | // } else { 214 | _dispatchMessageFromNative(messageJSON); 215 | // } 216 | } 217 | 218 | function _getIframe() { 219 | if (typeof(messagingIframe) == 'undefined') { 220 | messagingIframe = document.createElement('iframe'); 221 | messagingIframe.style.display = 'none'; 222 | document.documentElement.appendChild(messagingIframe); 223 | } 224 | return messagingIframe; 225 | } 226 | 227 | var WebViewJavascriptBridge = window.WebViewJavascriptBridge = { 228 | init: init, 229 | send: send, 230 | registerHandler: registerHandler, 231 | callHandler: callHandler, 232 | _handleMessageFromNative: _handleMessageFromNative, 233 | _fetchQueue: _fetchQueue 234 | }; 235 | 236 | var doc = document; 237 | // _createQueueReadyIframe(doc); 238 | var readyEvent = doc.createEvent('Events'); 239 | readyEvent.initEvent('WebViewJavascriptBridgeReady'); 240 | readyEvent.bridge = WebViewJavascriptBridge; 241 | doc.dispatchEvent(readyEvent); 242 | })();'''; 243 | 244 | String init_script_ios = ''' 245 | (function() { 246 | if (window.WebViewJavascriptBridge) { 247 | return; 248 | } 249 | 250 | if (!window.onerror) { 251 | window.onerror = function(msg, url, line) { 252 | console.log("WebViewJavascriptBridge: ERROR:" + msg + "@" + url + ":" + line); 253 | } 254 | } 255 | var WebViewJavascriptBridge = window.WebViewJavascriptBridge = { 256 | registerHandler: registerHandler, 257 | callHandler: callHandler, 258 | disableJavscriptAlertBoxSafetyTimeout: disableJavscriptAlertBoxSafetyTimeout, 259 | _handleMessageFromNative: _handleMessageFromNative, 260 | _fetchQueue: _fetchQueue 261 | }; 262 | 263 | var messagingIframe; 264 | var sendMessageQueue = []; 265 | var messageHandlers = {}; 266 | 267 | var CUSTOM_PROTOCOL_SCHEME = 'jsbridge'; 268 | 269 | var responseCallbacks = {}; 270 | var uniqueId = 1; 271 | var dispatchMessagesWithTimeoutSafety = true; 272 | 273 | function registerHandler(handlerName, handler) { 274 | messageHandlers[handlerName] = handler; 275 | } 276 | 277 | function callHandler(handlerName, data, responseCallback) { 278 | if (arguments.length == 2 && typeof data == 'function') { 279 | responseCallback = data; 280 | data = null; 281 | } 282 | _doSend({ handlerName:handlerName, data:data }, responseCallback); 283 | } 284 | 285 | function disableJavscriptAlertBoxSafetyTimeout() { 286 | dispatchMessagesWithTimeoutSafety = false; 287 | } 288 | 289 | function _doSend(message, responseCallback) { 290 | if (responseCallback) { 291 | var callbackId = 'cb_'+(uniqueId++)+'_'+new Date().getTime(); 292 | responseCallbacks[callbackId] = responseCallback; 293 | message['callbackId'] = callbackId; 294 | } 295 | sendMessageQueue.push(message); 296 | _getIframe().src = 'jsbridge://return/fetch' 297 | } 298 | 299 | function _dispatchMessageFromNative(messageJSON) { 300 | if (dispatchMessagesWithTimeoutSafety) { 301 | setTimeout(_doDispatchMessageFromNative, 0); 302 | } else { 303 | _doDispatchMessageFromNative(); 304 | } 305 | 306 | function _doDispatchMessageFromNative() { 307 | var message = JSON.parse(messageJSON); 308 | var messageHandler; 309 | var responseCallback; 310 | 311 | if (message.responseId) { 312 | responseCallback = responseCallbacks[message.responseId]; 313 | if (!responseCallback) { 314 | return; 315 | } 316 | responseCallback(message.responseData); 317 | delete responseCallbacks[message.responseId]; 318 | } else { 319 | if (message.callbackId) { 320 | var callbackResponseId = message.callbackId; 321 | responseCallback = function(responseData) { 322 | _doSend({ handlerName:message.handlerName, responseId:callbackResponseId, responseData:responseData }); 323 | }; 324 | } 325 | 326 | var handler = messageHandlers[message.handlerName]; 327 | if (!handler) { 328 | console.log("WebViewJavascriptBridge: WARNING: no handler for message from ObjC:", message); 329 | } else { 330 | handler(message.data, responseCallback); 331 | } 332 | } 333 | } 334 | } 335 | 336 | function _fetchQueue() { 337 | if (Array.isArray(sendMessageQueue) && sendMessageQueue.length === 0) { 338 | return; 339 | } 340 | var messageQueueString = JSON.stringify(sendMessageQueue); 341 | sendMessageQueue = []; 342 | if (messageQueueString === '[]') { 343 | return; 344 | } 345 | _getIframe().src = CUSTOM_PROTOCOL_SCHEME + '://return/sendMsg/' + encodeURIComponent(messageQueueString); 346 | } 347 | 348 | function _handleMessageFromNative(messageJSON) { 349 | _dispatchMessageFromNative(messageJSON); 350 | } 351 | 352 | function _getIframe() { 353 | if (typeof(messagingIframe) == 'undefined') { 354 | messagingIframe = document.createElement('iframe'); 355 | messagingIframe.style.display = 'none'; 356 | messagingIframe.src = 'jsbridge://return/fetch' 357 | document.documentElement.appendChild(messagingIframe); 358 | } 359 | return messagingIframe; 360 | } 361 | 362 | registerHandler("_disableJavascriptAlertBoxSafetyTimeout", disableJavscriptAlertBoxSafetyTimeout); 363 | setTimeout(_callWVJBCallbacks, 0); 364 | 365 | function _callWVJBCallbacks() { 366 | var callbacks = window.WVJBCallbacks; 367 | delete window.WVJBCallbacks; 368 | for (var i=0; i /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 245 | showEnvVarsInLog = 0; 246 | }; 247 | 9740EEB61CF901F6004384FC /* Run Script */ = { 248 | isa = PBXShellScriptBuildPhase; 249 | buildActionMask = 2147483647; 250 | files = ( 251 | ); 252 | inputPaths = ( 253 | ); 254 | name = "Run Script"; 255 | outputPaths = ( 256 | ); 257 | runOnlyForDeploymentPostprocessing = 0; 258 | shellPath = /bin/sh; 259 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; 260 | }; 261 | 99394E2E751D396918E99B46 /* [CP] Embed Pods Frameworks */ = { 262 | isa = PBXShellScriptBuildPhase; 263 | buildActionMask = 2147483647; 264 | files = ( 265 | ); 266 | inputPaths = ( 267 | "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", 268 | "${PODS_ROOT}/../Flutter/Flutter.framework", 269 | ); 270 | name = "[CP] Embed Pods Frameworks"; 271 | outputPaths = ( 272 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework", 273 | ); 274 | runOnlyForDeploymentPostprocessing = 0; 275 | shellPath = /bin/sh; 276 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; 277 | showEnvVarsInLog = 0; 278 | }; 279 | /* End PBXShellScriptBuildPhase section */ 280 | 281 | /* Begin PBXSourcesBuildPhase section */ 282 | 97C146EA1CF9000F007C117D /* Sources */ = { 283 | isa = PBXSourcesBuildPhase; 284 | buildActionMask = 2147483647; 285 | files = ( 286 | 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */, 287 | 97C146F31CF9000F007C117D /* main.m in Sources */, 288 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, 289 | ); 290 | runOnlyForDeploymentPostprocessing = 0; 291 | }; 292 | /* End PBXSourcesBuildPhase section */ 293 | 294 | /* Begin PBXVariantGroup section */ 295 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = { 296 | isa = PBXVariantGroup; 297 | children = ( 298 | 97C146FB1CF9000F007C117D /* Base */, 299 | ); 300 | name = Main.storyboard; 301 | sourceTree = ""; 302 | }; 303 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { 304 | isa = PBXVariantGroup; 305 | children = ( 306 | 97C147001CF9000F007C117D /* Base */, 307 | ); 308 | name = LaunchScreen.storyboard; 309 | sourceTree = ""; 310 | }; 311 | /* End PBXVariantGroup section */ 312 | 313 | /* Begin XCBuildConfiguration section */ 314 | 249021D3217E4FDB00AE95B9 /* Profile */ = { 315 | isa = XCBuildConfiguration; 316 | buildSettings = { 317 | ALWAYS_SEARCH_USER_PATHS = NO; 318 | CLANG_ANALYZER_NONNULL = YES; 319 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 320 | CLANG_CXX_LIBRARY = "libc++"; 321 | CLANG_ENABLE_MODULES = YES; 322 | CLANG_ENABLE_OBJC_ARC = YES; 323 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 324 | CLANG_WARN_BOOL_CONVERSION = YES; 325 | CLANG_WARN_COMMA = YES; 326 | CLANG_WARN_CONSTANT_CONVERSION = YES; 327 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 328 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 329 | CLANG_WARN_EMPTY_BODY = YES; 330 | CLANG_WARN_ENUM_CONVERSION = YES; 331 | CLANG_WARN_INFINITE_RECURSION = YES; 332 | CLANG_WARN_INT_CONVERSION = YES; 333 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 334 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 335 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 336 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 337 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 338 | CLANG_WARN_STRICT_PROTOTYPES = YES; 339 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 340 | CLANG_WARN_UNREACHABLE_CODE = YES; 341 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 342 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 343 | COPY_PHASE_STRIP = NO; 344 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 345 | ENABLE_NS_ASSERTIONS = NO; 346 | ENABLE_STRICT_OBJC_MSGSEND = YES; 347 | GCC_C_LANGUAGE_STANDARD = gnu99; 348 | GCC_NO_COMMON_BLOCKS = YES; 349 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 350 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 351 | GCC_WARN_UNDECLARED_SELECTOR = YES; 352 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 353 | GCC_WARN_UNUSED_FUNCTION = YES; 354 | GCC_WARN_UNUSED_VARIABLE = YES; 355 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 356 | MTL_ENABLE_DEBUG_INFO = NO; 357 | SDKROOT = iphoneos; 358 | SUPPORTED_PLATFORMS = iphoneos; 359 | TARGETED_DEVICE_FAMILY = "1,2"; 360 | VALIDATE_PRODUCT = YES; 361 | }; 362 | name = Profile; 363 | }; 364 | 249021D4217E4FDB00AE95B9 /* Profile */ = { 365 | isa = XCBuildConfiguration; 366 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 367 | buildSettings = { 368 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 369 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 370 | ENABLE_BITCODE = NO; 371 | FRAMEWORK_SEARCH_PATHS = ( 372 | "$(inherited)", 373 | "$(PROJECT_DIR)/Flutter", 374 | ); 375 | INFOPLIST_FILE = Runner/Info.plist; 376 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 377 | LIBRARY_SEARCH_PATHS = ( 378 | "$(inherited)", 379 | "$(PROJECT_DIR)/Flutter", 380 | ); 381 | PRODUCT_BUNDLE_IDENTIFIER = dev.epoll.flutterjsbridgepluginExample; 382 | PRODUCT_NAME = "$(TARGET_NAME)"; 383 | VERSIONING_SYSTEM = "apple-generic"; 384 | }; 385 | name = Profile; 386 | }; 387 | 97C147031CF9000F007C117D /* Debug */ = { 388 | isa = XCBuildConfiguration; 389 | buildSettings = { 390 | ALWAYS_SEARCH_USER_PATHS = NO; 391 | CLANG_ANALYZER_NONNULL = YES; 392 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 393 | CLANG_CXX_LIBRARY = "libc++"; 394 | CLANG_ENABLE_MODULES = YES; 395 | CLANG_ENABLE_OBJC_ARC = YES; 396 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 397 | CLANG_WARN_BOOL_CONVERSION = YES; 398 | CLANG_WARN_COMMA = YES; 399 | CLANG_WARN_CONSTANT_CONVERSION = YES; 400 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 401 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 402 | CLANG_WARN_EMPTY_BODY = YES; 403 | CLANG_WARN_ENUM_CONVERSION = YES; 404 | CLANG_WARN_INFINITE_RECURSION = YES; 405 | CLANG_WARN_INT_CONVERSION = YES; 406 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 407 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 408 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 409 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 410 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 411 | CLANG_WARN_STRICT_PROTOTYPES = YES; 412 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 413 | CLANG_WARN_UNREACHABLE_CODE = YES; 414 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 415 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 416 | COPY_PHASE_STRIP = NO; 417 | DEBUG_INFORMATION_FORMAT = dwarf; 418 | ENABLE_STRICT_OBJC_MSGSEND = YES; 419 | ENABLE_TESTABILITY = YES; 420 | GCC_C_LANGUAGE_STANDARD = gnu99; 421 | GCC_DYNAMIC_NO_PIC = NO; 422 | GCC_NO_COMMON_BLOCKS = YES; 423 | GCC_OPTIMIZATION_LEVEL = 0; 424 | GCC_PREPROCESSOR_DEFINITIONS = ( 425 | "DEBUG=1", 426 | "$(inherited)", 427 | ); 428 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 429 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 430 | GCC_WARN_UNDECLARED_SELECTOR = YES; 431 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 432 | GCC_WARN_UNUSED_FUNCTION = YES; 433 | GCC_WARN_UNUSED_VARIABLE = YES; 434 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 435 | MTL_ENABLE_DEBUG_INFO = YES; 436 | ONLY_ACTIVE_ARCH = YES; 437 | SDKROOT = iphoneos; 438 | TARGETED_DEVICE_FAMILY = "1,2"; 439 | }; 440 | name = Debug; 441 | }; 442 | 97C147041CF9000F007C117D /* Release */ = { 443 | isa = XCBuildConfiguration; 444 | buildSettings = { 445 | ALWAYS_SEARCH_USER_PATHS = NO; 446 | CLANG_ANALYZER_NONNULL = YES; 447 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 448 | CLANG_CXX_LIBRARY = "libc++"; 449 | CLANG_ENABLE_MODULES = YES; 450 | CLANG_ENABLE_OBJC_ARC = YES; 451 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 452 | CLANG_WARN_BOOL_CONVERSION = YES; 453 | CLANG_WARN_COMMA = YES; 454 | CLANG_WARN_CONSTANT_CONVERSION = YES; 455 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 456 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 457 | CLANG_WARN_EMPTY_BODY = YES; 458 | CLANG_WARN_ENUM_CONVERSION = YES; 459 | CLANG_WARN_INFINITE_RECURSION = YES; 460 | CLANG_WARN_INT_CONVERSION = YES; 461 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 462 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 463 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 464 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 465 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 466 | CLANG_WARN_STRICT_PROTOTYPES = YES; 467 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 468 | CLANG_WARN_UNREACHABLE_CODE = YES; 469 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 470 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 471 | COPY_PHASE_STRIP = NO; 472 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 473 | ENABLE_NS_ASSERTIONS = NO; 474 | ENABLE_STRICT_OBJC_MSGSEND = YES; 475 | GCC_C_LANGUAGE_STANDARD = gnu99; 476 | GCC_NO_COMMON_BLOCKS = YES; 477 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 478 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 479 | GCC_WARN_UNDECLARED_SELECTOR = YES; 480 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 481 | GCC_WARN_UNUSED_FUNCTION = YES; 482 | GCC_WARN_UNUSED_VARIABLE = YES; 483 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 484 | MTL_ENABLE_DEBUG_INFO = NO; 485 | SDKROOT = iphoneos; 486 | SUPPORTED_PLATFORMS = iphoneos; 487 | TARGETED_DEVICE_FAMILY = "1,2"; 488 | VALIDATE_PRODUCT = YES; 489 | }; 490 | name = Release; 491 | }; 492 | 97C147061CF9000F007C117D /* Debug */ = { 493 | isa = XCBuildConfiguration; 494 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 495 | buildSettings = { 496 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 497 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 498 | ENABLE_BITCODE = NO; 499 | FRAMEWORK_SEARCH_PATHS = ( 500 | "$(inherited)", 501 | "$(PROJECT_DIR)/Flutter", 502 | ); 503 | INFOPLIST_FILE = Runner/Info.plist; 504 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 505 | LIBRARY_SEARCH_PATHS = ( 506 | "$(inherited)", 507 | "$(PROJECT_DIR)/Flutter", 508 | ); 509 | PRODUCT_BUNDLE_IDENTIFIER = dev.epoll.flutterjsbridgepluginExample; 510 | PRODUCT_NAME = "$(TARGET_NAME)"; 511 | VERSIONING_SYSTEM = "apple-generic"; 512 | }; 513 | name = Debug; 514 | }; 515 | 97C147071CF9000F007C117D /* Release */ = { 516 | isa = XCBuildConfiguration; 517 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 518 | buildSettings = { 519 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 520 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 521 | ENABLE_BITCODE = NO; 522 | FRAMEWORK_SEARCH_PATHS = ( 523 | "$(inherited)", 524 | "$(PROJECT_DIR)/Flutter", 525 | ); 526 | INFOPLIST_FILE = Runner/Info.plist; 527 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 528 | LIBRARY_SEARCH_PATHS = ( 529 | "$(inherited)", 530 | "$(PROJECT_DIR)/Flutter", 531 | ); 532 | PRODUCT_BUNDLE_IDENTIFIER = dev.epoll.flutterjsbridgepluginExample; 533 | PRODUCT_NAME = "$(TARGET_NAME)"; 534 | VERSIONING_SYSTEM = "apple-generic"; 535 | }; 536 | name = Release; 537 | }; 538 | /* End XCBuildConfiguration section */ 539 | 540 | /* Begin XCConfigurationList section */ 541 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { 542 | isa = XCConfigurationList; 543 | buildConfigurations = ( 544 | 97C147031CF9000F007C117D /* Debug */, 545 | 97C147041CF9000F007C117D /* Release */, 546 | 249021D3217E4FDB00AE95B9 /* Profile */, 547 | ); 548 | defaultConfigurationIsVisible = 0; 549 | defaultConfigurationName = Release; 550 | }; 551 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { 552 | isa = XCConfigurationList; 553 | buildConfigurations = ( 554 | 97C147061CF9000F007C117D /* Debug */, 555 | 97C147071CF9000F007C117D /* Release */, 556 | 249021D4217E4FDB00AE95B9 /* Profile */, 557 | ); 558 | defaultConfigurationIsVisible = 0; 559 | defaultConfigurationName = Release; 560 | }; 561 | /* End XCConfigurationList section */ 562 | }; 563 | rootObject = 97C146E61CF9000F007C117D /* Project object */; 564 | } 565 | --------------------------------------------------------------------------------