Parcourir la source

完成android端开发

hwh97 il y a 5 ans
Parent
commit
d5aa507441

+ 1 - 1
.gitignore

@@ -1,6 +1,6 @@
 .DS_Store
 .dart_tool/
-
+.idea
 .packages
 .pub/
 

+ 221 - 174
.idea/workspace.xml

@@ -2,108 +2,21 @@
 <project version="4">
   <component name="ChangeListManager">
     <list default="true" id="e3e301fb-9bf2-45ae-a867-af8d9f406797" name="Default Changelist" comment="add: first commit">
-      <change afterPath="$PROJECT_DIR$/.gitignore" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/.idea/codeStyles/Project.xml" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/.idea/libraries/Dart_SDK.xml" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/.idea/libraries/Flutter_Plugins.xml" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/.idea/libraries/Flutter_for_Android.xml" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/.idea/misc.xml" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/.idea/modules.xml" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/.idea/runConfigurations/example_lib_main_dart.xml" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/.metadata" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/CHANGELOG.md" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/LICENSE" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/README.md" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/android/.gitignore" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/android/.idea/codeStyles/Project.xml" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/android/.idea/gradle.xml" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/android/.idea/misc.xml" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/android/.idea/modules.xml" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/android/.idea/runConfigurations.xml" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/android/build.gradle" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/android/gradle.properties" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/android/gradle/wrapper/gradle-wrapper.properties" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/android/settings.gradle" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/android/src/main/AndroidManifest.xml" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/android/src/main/kotlin/com/i2edu/flutter_ali_camera/AliCameraView.kt" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/android/src/main/kotlin/com/i2edu/flutter_ali_camera/CameraMethodHandler.kt" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/android/src/main/kotlin/com/i2edu/flutter_ali_camera/FlutterAliCameraPlugin.kt" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/android/src/main/kotlin/com/i2edu/flutter_ali_camera/FlutterState.kt" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/android/src/main/kotlin/com/i2edu/flutter_ali_camera/QueuingEventSink.java" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/.gitignore" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/.metadata" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/README.md" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/android/.gitignore" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/android/app/build.gradle" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/android/app/src/debug/AndroidManifest.xml" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/android/app/src/main/AndroidManifest.xml" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/android/app/src/main/kotlin/com/i2edu/flutter_ali_camera_example/MainActivity.kt" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/android/app/src/main/res/drawable/launch_background.xml" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/android/app/src/main/res/values/styles.xml" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/android/app/src/profile/AndroidManifest.xml" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/android/build.gradle" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/android/gradle.properties" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/android/gradle/wrapper/gradle-wrapper.properties" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/android/settings.gradle" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/ios/.gitignore" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/ios/Flutter/AppFrameworkInfo.plist" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/ios/Flutter/Debug.xcconfig" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/ios/Flutter/Release.xcconfig" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/ios/Runner.xcodeproj/project.pbxproj" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/ios/Runner.xcworkspace/contents.xcworkspacedata" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/ios/Runner/AppDelegate.h" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/ios/Runner/AppDelegate.m" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/ios/Runner/AppDelegate.swift" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/ios/Runner/Base.lproj/LaunchScreen.storyboard" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/ios/Runner/Base.lproj/Main.storyboard" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/ios/Runner/Info.plist" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/ios/Runner/Runner-Bridging-Header.h" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/ios/Runner/main.m" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/lib/main.dart" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/pubspec.lock" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/pubspec.yaml" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/example/test/widget_test.dart" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/flutter_ali_camera.iml" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/ios/.gitignore" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/ios/Assets/.gitkeep" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/ios/Classes/FlutterAliCameraPlugin.h" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/ios/Classes/FlutterAliCameraPlugin.m" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/ios/Classes/SwiftFlutterAliCameraPlugin.swift" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/ios/flutter_ali_camera.podspec" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/lib/camera_option.dart" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/lib/flutter_ali_camera.dart" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/pubspec.lock" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/pubspec.yaml" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/test/flutter_ali_camera_test.dart" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/lib/ali_camera.dart" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/.gitignore" beforeDir="false" afterPath="$PROJECT_DIR$/.gitignore" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/.idea/libraries/Flutter_Plugins.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/libraries/Flutter_Plugins.xml" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/android/src/main/kotlin/com/i2edu/flutter_ali_camera/AliCameraView.kt" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/kotlin/com/i2edu/flutter_ali_camera/AliCameraView.kt" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/android/src/main/kotlin/com/i2edu/flutter_ali_camera/CameraMethodHandler.kt" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/kotlin/com/i2edu/flutter_ali_camera/CameraMethodHandler.kt" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/android/src/main/kotlin/com/i2edu/flutter_ali_camera/FlutterAliCameraPlugin.kt" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/kotlin/com/i2edu/flutter_ali_camera/FlutterAliCameraPlugin.kt" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/android/src/main/kotlin/com/i2edu/flutter_ali_camera/FlutterState.kt" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/kotlin/com/i2edu/flutter_ali_camera/FlutterState.kt" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/android/src/main/kotlin/com/i2edu/flutter_ali_camera/QueuingEventSink.java" beforeDir="false" />
+      <change beforePath="$PROJECT_DIR$/example/lib/main.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/lib/main.dart" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/example/pubspec.lock" beforeDir="false" afterPath="$PROJECT_DIR$/example/pubspec.lock" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/example/pubspec.yaml" beforeDir="false" afterPath="$PROJECT_DIR$/example/pubspec.yaml" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/lib/camera_option.dart" beforeDir="false" afterPath="$PROJECT_DIR$/lib/camera_option.dart" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/lib/flutter_ali_camera.dart" beforeDir="false" afterPath="$PROJECT_DIR$/lib/ali_camera_controller.dart" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/test/flutter_ali_camera_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/test/flutter_ali_camera_test.dart" afterDir="false" />
     </list>
     <ignored path="$PROJECT_DIR$/.dart_tool/" />
     <ignored path="$PROJECT_DIR$/.idea/" />
@@ -118,62 +31,114 @@
     <option name="LAST_RESOLUTION" value="IGNORE" />
   </component>
   <component name="DefaultGradleProjectSettings">
-    <option name="testRunner" value="GRADLE" />
-    <option name="delegatedBuild" value="true" />
+    <option name="isMigrated" value="true" />
   </component>
   <component name="ExecutionTargetManager" SELECTED_TARGET="792QAESFTC6MD" />
   <component name="FileEditorManager">
     <leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
       <file pinned="false" current-in-tab="false">
+        <entry file="file://C:/flutter/flutter/packages/flutter/lib/src/material/icon_button.dart">
+          <provider selected="true" editor-type-id="text-editor">
+            <state relative-caret-position="39">
+              <caret line="137" column="8" selection-start-line="137" selection-start-column="8" selection-end-line="137" selection-end-column="8" />
+            </state>
+          </provider>
+        </entry>
+      </file>
+      <file pinned="false" current-in-tab="true">
         <entry file="file://$PROJECT_DIR$/example/lib/main.dart">
           <provider selected="true" editor-type-id="text-editor">
-            <state relative-caret-position="620">
-              <caret line="68" selection-start-line="68" selection-end-line="68" />
+            <state relative-caret-position="44">
+              <caret line="2" selection-start-line="2" selection-end-line="2" />
               <folding>
-                <element signature="e#1046#1195#0" />
-                <element signature="e#1212#1636#0" />
-                <element signature="e#1690#1750#0" />
+                <element signature="e#518#546#0" />
+                <element signature="e#799#809#0" />
+                <element signature="e#971#1336#0" />
+                <element signature="e#1370#1395#0" />
+                <element signature="e#1522#1699#0" />
+                <element signature="e#969#1235#0" />
+                <element signature="e#1751#2357#0" />
+                <element signature="e#2228#2446#0" />
+                <element signature="e#2408#5021#0" />
+                <element signature="e#2297#2337#0" />
+                <element signature="e#3140#3223#0" />
+                <element signature="e#3233#3544#0" />
               </folding>
             </state>
           </provider>
         </entry>
       </file>
+      <file pinned="false" current-in-tab="false">
+        <entry file="file://$PROJECT_DIR$/lib/ali_camera_controller.dart">
+          <provider selected="true" editor-type-id="text-editor">
+            <state relative-caret-position="111">
+              <caret line="66" column="46" selection-start-line="66" selection-start-column="46" selection-end-line="66" selection-end-column="46" />
+            </state>
+          </provider>
+        </entry>
+      </file>
+      <file pinned="false" current-in-tab="false">
+        <entry file="file://C:/flutter/flutter/.pub-cache/hosted/pub.flutter-io.cn/path_provider-0.4.1/lib/path_provider.dart">
+          <provider selected="true" editor-type-id="text-editor">
+            <state relative-caret-position="159">
+              <caret line="37" column="50" selection-start-line="37" selection-start-column="18" selection-end-line="37" selection-end-column="50" />
+            </state>
+          </provider>
+        </entry>
+      </file>
       <file pinned="false" current-in-tab="false">
         <entry file="file://$PROJECT_DIR$/lib/camera_option.dart">
           <provider selected="true" editor-type-id="text-editor">
-            <state relative-caret-position="264">
-              <caret line="12" column="15" selection-start-line="12" selection-start-column="5" selection-end-line="12" selection-end-column="15" />
+            <state relative-caret-position="171">
+              <caret line="41" column="6" selection-start-line="41" selection-start-column="6" selection-end-line="41" selection-end-column="6" />
             </state>
           </provider>
         </entry>
       </file>
-      <file pinned="false" current-in-tab="true">
-        <entry file="file://$PROJECT_DIR$/lib/flutter_ali_camera.dart">
+      <file pinned="false" current-in-tab="false">
+        <entry file="file://C:/flutter/flutter/packages/flutter/lib/src/services/text_input.dart">
           <provider selected="true" editor-type-id="text-editor">
-            <state relative-caret-position="418">
-              <caret line="48" column="3" lean-forward="true" selection-start-line="48" selection-start-column="3" selection-end-line="48" selection-end-column="3" />
+            <state relative-caret-position="171">
+              <caret line="584" column="9" selection-start-line="584" selection-start-column="9" selection-end-line="584" selection-end-column="9" />
+            </state>
+          </provider>
+        </entry>
+      </file>
+      <file pinned="false" current-in-tab="false">
+        <entry file="file://$PROJECT_DIR$/example/pubspec.yaml">
+          <provider selected="true" editor-type-id="text-editor">
+            <state relative-caret-position="-751">
+              <caret line="15" selection-start-line="15" selection-end-line="15" />
+            </state>
+          </provider>
+        </entry>
+      </file>
+      <file pinned="false" current-in-tab="false">
+        <entry file="file://$PROJECT_DIR$/pubspec.yaml">
+          <provider selected="true" editor-type-id="text-editor">
+            <state relative-caret-position="-135">
+              <caret line="12" selection-start-line="12" selection-end-line="12" />
+            </state>
+          </provider>
+        </entry>
+      </file>
+      <file pinned="false" current-in-tab="false">
+        <entry file="file://$PROJECT_DIR$/lib/ali_camera.dart">
+          <provider selected="true" editor-type-id="text-editor">
+            <state relative-caret-position="22">
+              <caret line="1" column="28" selection-start-line="1" selection-start-column="28" selection-end-line="1" selection-end-column="28" />
               <folding>
-                <element signature="e#425#534#0" />
-                <element signature="e#559#659#0" />
-                <element signature="e#716#1223#0" />
-                <element signature="e#769#977#0" />
-                <element signature="e#997#1218#0" />
-                <element signature="e#1307#1362#0" />
-                <element signature="e#1393#1448#0" />
-                <element signature="e#1489#1548#0" />
-                <element signature="e#1562#1572#0" />
-                <element signature="e#1680#1690#0" />
-                <element signature="e#733#789#0" />
+                <element signature="e#0#36#0" expanded="true" />
               </folding>
             </state>
           </provider>
         </entry>
       </file>
       <file pinned="false" current-in-tab="false">
-        <entry file="file://$PROJECT_DIR$/pubspec.yaml">
+        <entry file="file://C:/flutter/flutter/bin/cache/pkg/sky_engine/lib/core/map.dart">
           <provider selected="true" editor-type-id="text-editor">
-            <state relative-caret-position="286">
-              <caret line="13" column="17" lean-forward="true" selection-start-line="13" selection-start-column="17" selection-end-line="13" selection-end-column="17" />
+            <state relative-caret-position="5566">
+              <caret line="271" column="61" selection-start-line="271" selection-start-column="61" selection-end-line="271" selection-end-column="61" />
             </state>
           </provider>
         </entry>
@@ -187,24 +152,40 @@
       </list>
     </option>
   </component>
+  <component name="FindInProjectRecents">
+    <findStrings>
+      <find>path</find>
+      <find>path</find>
+      <find>{</find>
+      <find>record update</find>
+      <find>record updat</find>
+      <find>progress</find>
+      <find>recordPath</find>
+    </findStrings>
+  </component>
   <component name="Git.Settings">
     <option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
   </component>
   <component name="IdeDocumentHistory">
     <option name="CHANGED_PATHS">
       <list>
-        <option value="$PROJECT_DIR$/test/flutter_ali_camera_test.dart" />
         <option value="$PROJECT_DIR$/lib/output_option.dart" />
-        <option value="$PROJECT_DIR$/lib/camera_option.dart" />
+        <option value="$PROJECT_DIR$/.gitignore" />
         <option value="$PROJECT_DIR$/lib/flutter_ali_camera.dart" />
+        <option value="$PROJECT_DIR$/lib/ali_camera.dart" />
+        <option value="$PROJECT_DIR$/test/flutter_ali_camera_test.dart" />
+        <option value="$PROJECT_DIR$/lib/camera_option.dart" />
+        <option value="$PROJECT_DIR$/pubspec.yaml" />
+        <option value="$PROJECT_DIR$/example/pubspec.yaml" />
+        <option value="$PROJECT_DIR$/lib/ali_camera_controller.dart" />
         <option value="$PROJECT_DIR$/example/lib/main.dart" />
       </list>
     </option>
   </component>
   <component name="ProjectFrameBounds" extendedState="6">
-    <option name="x" value="400" />
-    <option name="y" value="23" />
-    <option name="width" value="1346" />
+    <option name="x" value="-53" />
+    <option name="y" value="14" />
+    <option name="width" value="1068" />
     <option name="height" value="955" />
   </component>
   <component name="ProjectLevelVcsManager" settingsEditedManually="true" />
@@ -213,8 +194,6 @@
       <foldersAlwaysOnTop value="true" />
     </navigator>
     <panes>
-      <pane id="PackagesPane" />
-      <pane id="Scope" />
       <pane id="ProjectPane">
         <subPane>
           <expand>
@@ -222,6 +201,11 @@
               <item name="flutter_ali_camera" type="b2602c69:ProjectViewProjectNode" />
               <item name="flutter_ali_camera" type="462c0819:PsiDirectoryNode" />
             </path>
+            <path>
+              <item name="flutter_ali_camera" type="b2602c69:ProjectViewProjectNode" />
+              <item name="flutter_ali_camera" type="462c0819:PsiDirectoryNode" />
+              <item name="example" type="462c0819:PsiDirectoryNode" />
+            </path>
             <path>
               <item name="flutter_ali_camera" type="b2602c69:ProjectViewProjectNode" />
               <item name="flutter_ali_camera" type="462c0819:PsiDirectoryNode" />
@@ -241,6 +225,8 @@
           <select />
         </subPane>
       </pane>
+      <pane id="PackagesPane" />
+      <pane id="Scope" />
       <pane id="AndroidView" />
     </panes>
   </component>
@@ -278,6 +264,7 @@
   </component>
   <component name="ToolWindowManager">
     <frame x="-8" y="-8" width="1936" height="1096" extended-state="6" />
+    <editor active="true" />
     <layout>
       <window_info content_ui="combo" id="Project" order="0" visible="true" weight="0.25" />
       <window_info id="Captures" order="1" side_tool="true" />
@@ -288,13 +275,14 @@
       <window_info id="Resources Explorer" order="6" />
       <window_info id="Capture Tool" order="7" />
       <window_info id="Favorites" order="8" side_tool="true" />
+      <window_info anchor="bottom" id="Messages" weight="0.32976446" />
       <window_info anchor="bottom" id="Dart Analysis" order="0" weight="0.32905984" />
-      <window_info anchor="bottom" id="Run" order="1" weight="0.42200854" />
+      <window_info anchor="bottom" id="Run" order="1" weight="0.42184153" />
       <window_info anchor="bottom" id="TODO" order="2" />
       <window_info anchor="bottom" id="Android Profiler" order="3" show_stripe_button="false" />
       <window_info anchor="bottom" id="Logcat" order="4" />
-      <window_info anchor="bottom" id="Debug" order="5" />
-      <window_info active="true" anchor="bottom" id="Terminal" order="6" visible="true" weight="0.32976446" />
+      <window_info active="true" anchor="bottom" id="Debug" order="5" visible="true" weight="0.32976446" />
+      <window_info anchor="bottom" id="Terminal" order="6" weight="0.32976446" />
       <window_info anchor="bottom" id="Event Log" order="7" side_tool="true" />
       <window_info anchor="bottom" id="Version Control" order="8" />
       <window_info anchor="right" id="Device File Explorer" order="0" side_tool="true" />
@@ -315,16 +303,6 @@
         </state>
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/test/flutter_ali_camera_test.dart">
-      <provider selected="true" editor-type-id="text-editor">
-        <state relative-caret-position="308">
-          <caret line="16" column="43" selection-start-line="16" selection-start-column="43" selection-end-line="16" selection-end-column="43" />
-          <folding>
-            <element signature="e#0#39#0" expanded="true" />
-          </folding>
-        </state>
-      </provider>
-    </entry>
     <entry file="file://C:/flutter/flutter/packages/flutter/lib/src/services/binary_messenger.dart">
       <provider selected="true" editor-type-id="text-editor">
         <state relative-caret-position="265">
@@ -349,48 +327,117 @@
     <entry file="file://$PROJECT_DIR$/ios/Classes/SwiftFlutterAliCameraPlugin.swift">
       <provider selected="true" editor-type-id="text-editor" />
     </entry>
-    <entry file="file://$PROJECT_DIR$/example/lib/main.dart">
+    <entry file="file://$PROJECT_DIR$/.gitignore">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="44">
+          <caret line="2" column="5" selection-start-line="2" selection-start-column="5" selection-end-line="2" selection-end-column="5" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/test/flutter_ali_camera_test.dart">
       <provider selected="true" editor-type-id="text-editor">
-        <state relative-caret-position="620">
-          <caret line="68" selection-start-line="68" selection-end-line="68" />
+        <state relative-caret-position="44">
+          <caret line="2" column="50" selection-start-line="2" selection-start-column="50" selection-end-line="2" selection-end-column="50" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://C:/flutter/flutter/bin/cache/pkg/sky_engine/lib/core/map.dart">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="5566">
+          <caret line="271" column="61" selection-start-line="271" selection-start-column="61" selection-end-line="271" selection-end-column="61" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://C:/flutter/flutter/packages/flutter/lib/src/material/input_decorator.dart">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="259">
+          <caret line="2352" column="19" selection-start-line="2352" selection-start-column="9" selection-end-line="2352" selection-end-column="19" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/lib/ali_camera.dart">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="22">
+          <caret line="1" column="28" selection-start-line="1" selection-start-column="28" selection-end-line="1" selection-end-column="28" />
           <folding>
-            <element signature="e#1046#1195#0" />
-            <element signature="e#1212#1636#0" />
-            <element signature="e#1690#1750#0" />
+            <element signature="e#0#36#0" expanded="true" />
           </folding>
         </state>
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/lib/camera_option.dart">
+    <entry file="file://C:/flutter/flutter/packages/flutter/lib/src/services/platform_channel.dart">
       <provider selected="true" editor-type-id="text-editor">
-        <state relative-caret-position="264">
-          <caret line="12" column="15" selection-start-line="12" selection-start-column="5" selection-end-line="12" selection-end-column="15" />
+        <state relative-caret-position="171">
+          <caret line="320" column="32" selection-start-line="320" selection-start-column="32" selection-end-line="320" selection-end-column="32" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/example/pubspec.yaml">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="-751">
+          <caret line="15" selection-start-line="15" selection-end-line="15" />
         </state>
       </provider>
     </entry>
     <entry file="file://$PROJECT_DIR$/pubspec.yaml">
       <provider selected="true" editor-type-id="text-editor">
-        <state relative-caret-position="286">
-          <caret line="13" column="17" lean-forward="true" selection-start-line="13" selection-start-column="17" selection-end-line="13" selection-end-column="17" />
+        <state relative-caret-position="-135">
+          <caret line="12" selection-start-line="12" selection-end-line="12" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://C:/flutter/flutter/packages/flutter/lib/src/services/text_input.dart">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="171">
+          <caret line="584" column="9" selection-start-line="584" selection-start-column="9" selection-end-line="584" selection-end-column="9" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/lib/camera_option.dart">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="171">
+          <caret line="41" column="6" selection-start-line="41" selection-start-column="6" selection-end-line="41" selection-end-column="6" />
         </state>
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/lib/flutter_ali_camera.dart">
+    <entry file="file://C:/flutter/flutter/packages/flutter/lib/src/material/icon_button.dart">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="39">
+          <caret line="137" column="8" selection-start-line="137" selection-start-column="8" selection-end-line="137" selection-end-column="8" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://C:/flutter/flutter/.pub-cache/hosted/pub.flutter-io.cn/path_provider-0.4.1/lib/path_provider.dart">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="159">
+          <caret line="37" column="50" selection-start-line="37" selection-start-column="18" selection-end-line="37" selection-end-column="50" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/lib/ali_camera_controller.dart">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="111">
+          <caret line="66" column="46" selection-start-line="66" selection-start-column="46" selection-end-line="66" selection-end-column="46" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/example/lib/main.dart">
       <provider selected="true" editor-type-id="text-editor">
-        <state relative-caret-position="418">
-          <caret line="48" column="3" lean-forward="true" selection-start-line="48" selection-start-column="3" selection-end-line="48" selection-end-column="3" />
+        <state relative-caret-position="44">
+          <caret line="2" selection-start-line="2" selection-end-line="2" />
           <folding>
-            <element signature="e#425#534#0" />
-            <element signature="e#559#659#0" />
-            <element signature="e#716#1223#0" />
-            <element signature="e#769#977#0" />
-            <element signature="e#997#1218#0" />
-            <element signature="e#1307#1362#0" />
-            <element signature="e#1393#1448#0" />
-            <element signature="e#1489#1548#0" />
-            <element signature="e#1562#1572#0" />
-            <element signature="e#1680#1690#0" />
-            <element signature="e#733#789#0" />
+            <element signature="e#518#546#0" />
+            <element signature="e#799#809#0" />
+            <element signature="e#971#1336#0" />
+            <element signature="e#1370#1395#0" />
+            <element signature="e#1522#1699#0" />
+            <element signature="e#969#1235#0" />
+            <element signature="e#1751#2357#0" />
+            <element signature="e#2228#2446#0" />
+            <element signature="e#2408#5021#0" />
+            <element signature="e#2297#2337#0" />
+            <element signature="e#3140#3223#0" />
+            <element signature="e#3233#3544#0" />
           </folding>
         </state>
       </provider>

+ 160 - 29
android/src/main/kotlin/com/i2edu/flutter_ali_camera/AliCameraView.kt

@@ -1,65 +1,111 @@
 package com.i2edu.flutter_ali_camera
 
 import android.content.Context
-import android.hardware.Camera
+import android.graphics.Bitmap
+import android.net.Uri
+import android.os.Handler
+import android.os.Looper
 import android.util.Log
 import android.view.*
 import android.widget.FrameLayout
+import com.aliyun.editor.EditorCallBack
+import com.aliyun.qupai.editor.AliyunIComposeCallBack
+import com.aliyun.qupai.editor.impl.AliyunEditorFactory
+import com.aliyun.qupai.import_core.AliyunImportCreator
 import com.aliyun.recorder.AliyunRecorderCreator
 import com.aliyun.recorder.supply.AliyunIRecorder
+import com.aliyun.recorder.supply.RecordCallback
+import com.aliyun.svideo.sdk.external.struct.common.AliyunVideoClip
+import com.aliyun.svideo.sdk.external.struct.common.AliyunVideoParam
+import com.aliyun.svideo.sdk.external.struct.common.VideoDisplayMode
 import com.aliyun.svideo.sdk.external.struct.common.VideoQuality
+import com.aliyun.svideo.sdk.external.struct.effect.EffectBean
 import com.aliyun.svideo.sdk.external.struct.effect.EffectFilter
 import com.aliyun.svideo.sdk.external.struct.encoder.VideoCodecs
 import com.aliyun.svideo.sdk.external.struct.recorder.CameraParam
 import com.aliyun.svideo.sdk.external.struct.recorder.CameraType
 import com.aliyun.svideo.sdk.external.struct.recorder.MediaInfo
-import com.qu.preview.callback.OnFrameCallBack
-import com.qu.preview.callback.OnTextureIdCallBack
-import io.flutter.plugin.common.BinaryMessenger
+import io.flutter.plugin.common.MethodChannel
 import io.flutter.plugin.platform.PlatformView
+import java.io.File
 import java.lang.Exception
 
-class AliCameraView(context: Context, messenger: BinaryMessenger, id: Long) : PlatformView {
+class AliCameraView(private val context: Context, private val channel: MethodChannel) : PlatformView {
     private val TAG = "AliCameraView"
     var surfaceView: SurfaceView? = null
     var frameLayout: FrameLayout? = null
 
     private var recorder: AliyunIRecorder? = null
+    private val mainHandler: Handler = Handler(Looper.getMainLooper())
 
     init {
-        setUpCameraView(context, id)
+        setUpView(context)
     }
 
-    private fun setUpCameraView(context: Context, id: Long) {
-        try {
+    private fun setUpView(context: Context) {
+        if (frameLayout == null) {
             frameLayout = FrameLayout(context)
             frameLayout?.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
             surfaceView = SurfaceView(context)
             surfaceView?.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
             frameLayout?.addView(surfaceView)
+        }
+    }
+
+    fun setUpCameraView(context: Context, recordOption: Map<String, Any>) {
+        try {
             recorder = AliyunRecorderCreator.getRecorderInstance(context)
 
             val mediaInfo = MediaInfo()
-            mediaInfo.videoWidth = 720
-            mediaInfo.videoHeight = 1280
-            mediaInfo.videoCodec = VideoCodecs.H264_HARDWARE
+            if (recordOption.containsKey("videoWidth")) mediaInfo.videoWidth = recordOption["videoWidth"] as Int
+            if (recordOption.containsKey("videoHeight")) mediaInfo.videoHeight = recordOption["videoHeight"] as Int
+            if (recordOption.containsKey("videoCodecs")) mediaInfo.videoCodec = VideoCodecs.getInstanceByValue(recordOption["videoCodecs"] as Int)
+            if (recordOption.containsKey("fps")) mediaInfo.fps = recordOption["fps"] as Int
+            if (recordOption.containsKey("crf")) mediaInfo.crf = recordOption["crf"] as Int
+            if (recordOption.containsKey("encoderFps")) mediaInfo.encoderFps = recordOption["encoderFps"] as Int
             recorder?.setMediaInfo(mediaInfo)
-            recorder?.setVideoQuality(VideoQuality.SD)
+            if (recordOption.containsKey("quality")) recorder?.setVideoQuality(VideoQuality.values()[recordOption["quality"] as Int])
+            if (recordOption.containsKey("videoBitrate")) recorder?.setVideoBitrate(recordOption["videoBitrate"] as Int)
+            if (recordOption.containsKey("gop")) recorder?.setGop(recordOption["gop"] as Int)
+
             recorder?.setFocusMode(CameraParam.FOCUS_MODE_CONTINUE)
             recorder?.setCamera(CameraType.FRONT)
             recorder?.setBeautyStatus(false)
             recorder?.beautyLevel = 0
-            recorder?.setOnTextureIdCallback(object : OnTextureIdCallBack {
-                override fun onTextureIdBack(textureId: Int, textureWidth: Int, textureHeight: Int, matrix: FloatArray?): Int {
-                    return textureId
+
+            recorder?.setRecordCallBack(object : RecordCallback {
+                override fun onFinish(p0: String?) {
                 }
 
-                override fun onScaledIdBack(scaledId: Int, textureWidth: Int, textureHeight: Int, matrix: FloatArray?): Int {
-                    return scaledId
+                override fun onInitReady() {
                 }
 
-                override fun onTextureDestroyed() {
+                override fun onPictureBack(p0: Bitmap?) {
+                }
+
+                override fun onPictureDataBack(p0: ByteArray?) {
+                }
+
+                override fun onComplete(p0: Boolean, p1: Long) {
+                    mainHandler.post {
+                        channel.invokeMethod("recordUpdate",
+                                mapOf("progress" to recorder?.clipManager?.maxDuration, "path" to recorder?.clipManager?.videoPathList?.last()))
+                    }
+                }
+
+                override fun onMaxDuration() {
+                }
 
+                override fun onDrawReady() {
+                }
+
+                override fun onProgress(p0: Long) {
+                    mainHandler.post {
+                        channel.invokeMethod("recordUpdate", mapOf("progress" to p0))
+                    }
+                }
+
+                override fun onError(p0: Int) {
                 }
             })
             recorder?.setDisplayView(surfaceView)
@@ -93,20 +139,100 @@ class AliCameraView(context: Context, messenger: BinaryMessenger, id: Long) : Pl
         recorder?.applyFilter(EffectFilter(path))
     }
 
-    fun startRecord(max: Int, recordPath: String) {
-        recorder?.setOutputPath(recordPath)
-        //  补充时间段上去
-        val currentDuration = if (recorder?.clipManager?.maxDuration!! >= Int.MAX_VALUE) 0 else recorder?.clipManager?.maxDuration!!
-        recorder?.clipManager?.maxDuration = max + currentDuration
-        recorder?.startRecording()
+    fun startRecord(max: Int, recordPath: String, result: MethodChannel.Result) {
+        try {
+            recorder?.setOutputPath(recordPath)
+            //  补充时间段上去
+            val currentDuration = if (recorder?.clipManager?.maxDuration!! >= Int.MAX_VALUE) 0 else recorder?.clipManager?.maxDuration!!
+            recorder?.clipManager?.maxDuration = max + currentDuration
+            recorder?.startRecording()
+            result.success(true)
+        } catch (e: Exception) {
+            result.error("1001", e.message, null)
+        }
     }
 
-    fun onDestroy() {
-        if (frameLayout == null) return
-        frameLayout?.removeView(surfaceView)
-        if (surfaceView != null) {
-            surfaceView = null
+    fun startCompose(outputPath: String, bgmPath: String?, paths: List<String>, durations: List<Int>, outputOption: Map<String, Any>, result: MethodChannel.Result) {
+        try {
+            // 配置输出参数
+            val mImport = AliyunImportCreator.getImportInstance(context)
+            for ((index, path) in paths.withIndex()) {
+                mImport.addMediaClip(AliyunVideoClip.Builder()
+                        .source(path)
+                        .startTime(0)
+                        .endTime(durations[index].toLong())
+                        .build())
+            }
+            val param = AliyunVideoParam()
+            if (outputOption.containsKey("outputWidth")) param.outputWidth = outputOption["outputWidth"] as Int
+            if (outputOption.containsKey("outputHeight")) param.outputHeight = outputOption["outputHeight"] as Int
+            if (outputOption.containsKey("frameRate")) param.frameRate = outputOption["frameRate"] as Int
+            if (outputOption.containsKey("crf")) param.crf = outputOption["crf"] as Int
+            if (outputOption.containsKey("gop")) param.gop = outputOption["gop"] as Int
+            if (outputOption.containsKey("bitrate")) param.bitrate = outputOption["bitrate"] as Int
+            if (outputOption.containsKey("scaleRate")) param.scaleRate = outputOption["scaleRate"] as Float
+            if (outputOption.containsKey("videoCodecs")) param.videoCodec = VideoCodecs.getInstanceByValue(outputOption["videoCodecs"] as Int)
+            if (outputOption.containsKey("quality")) param.videoQuality = VideoQuality.values()[outputOption["quality"] as Int]
+            if (outputOption.containsKey("scaleMode")) param.scaleMode = VideoDisplayMode.values()[outputOption["scaleMode"] as Int]
+            mImport.setVideoParam(param)
+            val configStringPath = mImport.generateProjectConfigure()
+            mImport.release()
+            val uri = Uri.fromFile(File(configStringPath))
+            // 添加bgm背景音乐
+            val editor = AliyunEditorFactory.creatAliyunEditor(uri, object : EditorCallBack() {
+                override fun onTextureRender(srcTextureID: Int, width: Int, height: Int): Int {
+                    return srcTextureID
+                }
+
+                override fun onPlayProgress(p0: Long, p1: Long) {
+                }
+
+                override fun onCustomRender(srcTextureID: Int, width: Int, height: Int): Int {
+                    return srcTextureID
+                }
+
+                override fun onDataReady() {
+                }
+
+                override fun onEnd(state: Int) {
+                }
+
+                override fun onError(errorCode: Int) {
+                }
+            })
+            editor.init(null, frameLayout?.context)
+            if (bgmPath != null) {
+                val bean = EffectBean()
+                bean.path = bgmPath
+                editor.applyMusic(bean)
+            }
+            // 合并输出视频
+            editor.compose(param, outputPath, object : AliyunIComposeCallBack {
+                override fun onComposeProgress(p0: Int) {
+                    Log.d(TAG, "onComposeProgress: $p0")
+                }
+
+                override fun onComposeCompleted() {
+                    Log.d(TAG, "onComposeCompleted")
+                    mainHandler.post {
+                        result.success(true)
+                    }
+                }
+
+                override fun onComposeError(p0: Int) {
+                    Log.d(TAG, "onComposeError: $p0")
+                    mainHandler.post {
+                        result.success(false)
+                    }
+                }
+            })
+        } catch (e: Exception) {
+            e.printStackTrace()
+            result.error("1002", e.message, null)
         }
+    }
+
+    fun onDestroy() {
         recorder?.stopPreview()
         recorder?.stopRecording()
         recorder?.destroy()
@@ -118,6 +244,11 @@ class AliCameraView(context: Context, messenger: BinaryMessenger, id: Long) : Pl
     }
 
     override fun dispose() {
+        if (frameLayout == null) return
+        frameLayout?.removeView(surfaceView)
+        if (surfaceView != null) {
+            surfaceView = null
+        }
         onDestroy()
     }
 }

+ 18 - 9
android/src/main/kotlin/com/i2edu/flutter_ali_camera/CameraMethodHandler.kt

@@ -8,7 +8,7 @@ import io.flutter.plugin.platform.PlatformViewFactory
 
 class CameraMethodHandler(
         private val flutterState: FlutterState) : MethodChannel.MethodCallHandler {
-    private var camera: AliCameraView? = null;
+    var camera: AliCameraView ?= null
 
     override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
         when (call.method) {
@@ -16,17 +16,19 @@ class CameraMethodHandler(
                 result.success("Android ${android.os.Build.VERSION.RELEASE}")
             }
             "initializeSdk" -> {
+                camera = AliCameraView(flutterState.context, flutterState.methodChannel)
+                flutterState.platformViewRegistry.registerViewFactory("com.i2edu.cameraLib", object : PlatformViewFactory(StandardMessageCodec.INSTANCE) {
+                    override fun create(context: Context, viewId: Int, args: Any?): PlatformView {
+                        return camera!!
+                    }
+                })
                 AlivcSdkCore.register(flutterState.context)
                 AlivcSdkCore.setLogLevel(AlivcSdkCore.AlivcLogLevel.AlivcLogDebug)
                 result.success(true)
             }
             "create" -> {
-                flutterState.platformViewRegistry.registerViewFactory("com.i2edu.cameraLib", object : PlatformViewFactory(StandardMessageCodec.INSTANCE) {
-                    override fun create(context: Context?, viewId: Int, args: Any?): PlatformView {
-                        camera = AliCameraView(context!!, flutterState.binaryMessenger, viewId.toLong())
-                        return camera!!
-                    }
-                })
+                val recordOption: Map<String, Any> = call.argument<Map<String, Any>>("recordOption")!!
+                camera?.setUpCameraView(context = flutterState.context, recordOption = recordOption)
                 result.success(true)
             }
             "startPreview" -> {
@@ -51,8 +53,15 @@ class CameraMethodHandler(
             }
             "startRecord" -> {
                 camera?.startRecord(
-                        max=call.argument<Int>("max")!!, recordPath = call.argument<String>("recordPath")!!)
-                result.success(true)
+                        max = call.argument<Int>("max")!!, recordPath = call.argument<String>("recordPath")!!, result = result)
+            }
+            "startCompose" -> {
+                val outputPath = call.argument<String>("outputPath")!!
+                val bgmPath = call.argument<String>("bgmPath")
+                val paths = call.argument<List<String>>("paths")!!
+                val durations = call.argument<List<Int>>("durations")!!
+                val outputOption = call.argument<Map<String, Any>>("composeOption")!!
+                camera?.startCompose(outputPath = outputPath, bgmPath = bgmPath, paths = paths, durations = durations, outputOption = outputOption, result = result)
             }
             "onDestroy" -> {
                 camera?.onDestroy()

+ 4 - 8
android/src/main/kotlin/com/i2edu/flutter_ali_camera/FlutterAliCameraPlugin.kt

@@ -1,14 +1,10 @@
 package com.i2edu.flutter_ali_camera
 
-import android.content.Context
-import androidx.annotation.NonNull;
+import androidx.annotation.NonNull
+import io.flutter.app.FlutterActivity
 import io.flutter.embedding.engine.plugins.FlutterPlugin
-import io.flutter.plugin.common.MethodChannel
 import io.flutter.plugin.common.PluginRegistry.Registrar
-import io.flutter.view.TextureRegistry
-import io.flutter.plugin.common.BinaryMessenger
-
-
+import io.flutter.plugin.common.PluginRegistry
 
 /** FlutterAliCameraPlugin */
 public class FlutterAliCameraPlugin : FlutterPlugin {
@@ -36,6 +32,6 @@ public class FlutterAliCameraPlugin : FlutterPlugin {
 
     override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
         flutterState?.stopListening()
-        flutterState = null;
+        flutterState = null
     }
 }

+ 2 - 9
android/src/main/kotlin/com/i2edu/flutter_ali_camera/FlutterState.kt

@@ -3,21 +3,14 @@ package com.i2edu.flutter_ali_camera
 import android.content.Context
 import io.flutter.plugin.common.MethodChannel
 import io.flutter.plugin.common.BinaryMessenger
-import io.flutter.plugin.common.StandardMessageCodec
-import io.flutter.plugin.platform.PlatformView
-import io.flutter.plugin.platform.PlatformViewFactory
 import io.flutter.plugin.platform.PlatformViewRegistry
 
 class FlutterState(
         val context: Context,
-        val binaryMessenger: BinaryMessenger,
+        binaryMessenger: BinaryMessenger,
         val platformViewRegistry: PlatformViewRegistry) {
     
-    private val methodChannel: MethodChannel
-
-    init {
-        methodChannel = MethodChannel(binaryMessenger, "flutter_ali_camera")
-    }
+    val methodChannel: MethodChannel = MethodChannel(binaryMessenger, "flutter_ali_camera")
 
     fun startListening(methodCallHandler: CameraMethodHandler) {
         methodChannel.setMethodCallHandler(methodCallHandler)

+ 0 - 85
android/src/main/kotlin/com/i2edu/flutter_ali_camera/QueuingEventSink.java

@@ -1,85 +0,0 @@
-package com.i2edu.flutter_ali_camera;
-
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import io.flutter.plugin.common.EventChannel;
-import java.util.ArrayList;
-
-/**
- * And implementation of {@link EventChannel.EventSink} which can wrap an underlying sink.
- *
- * <p>It delivers messages immediately when downstream is available, but it queues messages before
- * the delegate event sink is set with setDelegate.
- *
- * <p>This class is not thread-safe. All calls must be done on the same thread or synchronized
- * externally.
- */
-final class QueuingEventSink implements EventChannel.EventSink {
-    private EventChannel.EventSink delegate;
-    private ArrayList<Object> eventQueue = new ArrayList<>();
-    private boolean done = false;
-
-    public void setDelegate(EventChannel.EventSink delegate) {
-        this.delegate = delegate;
-        maybeFlush();
-    }
-
-    @Override
-    public void endOfStream() {
-        enqueue(new EndOfStreamEvent());
-        maybeFlush();
-        done = true;
-    }
-
-    @Override
-    public void error(String code, String message, Object details) {
-        enqueue(new ErrorEvent(code, message, details));
-        maybeFlush();
-    }
-
-    @Override
-    public void success(Object event) {
-        enqueue(event);
-        maybeFlush();
-    }
-
-    private void enqueue(Object event) {
-        if (done) {
-            return;
-        }
-        eventQueue.add(event);
-    }
-
-    private void maybeFlush() {
-        if (delegate == null) {
-            return;
-        }
-        for (Object event : eventQueue) {
-            if (event instanceof EndOfStreamEvent) {
-                delegate.endOfStream();
-            } else if (event instanceof ErrorEvent) {
-                ErrorEvent errorEvent = (ErrorEvent) event;
-                delegate.error(errorEvent.code, errorEvent.message, errorEvent.details);
-            } else {
-                delegate.success(event);
-            }
-        }
-        eventQueue.clear();
-    }
-
-    private static class EndOfStreamEvent {}
-
-    private static class ErrorEvent {
-        String code;
-        String message;
-        Object details;
-
-        ErrorEvent(String code, String message, Object details) {
-            this.code = code;
-            this.message = message;
-            this.details = details;
-        }
-    }
-}

+ 125 - 20
example/lib/main.dart

@@ -1,8 +1,10 @@
-import 'package:flutter/material.dart';
+import 'dart:io';
 import 'dart:async';
 
-import 'package:flutter/services.dart';
-import 'package:flutter_ali_camera/flutter_ali_camera.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_ali_camera/ali_camera.dart';
+import 'package:path_provider/path_provider.dart';
+import 'package:path/path.dart' as path;
 
 void main() async {
   WidgetsFlutterBinding.ensureInitialized();
@@ -17,20 +19,77 @@ class MyApp extends StatefulWidget {
 
 class _MyAppState extends State<MyApp> {
   FlutterAliCameraController _controller = FlutterAliCameraController();
+  StreamSubscription _durationSubscription; // 播放进度订阅
+  final int duration = 5000;
   double value = 0;
+  bool recording = false;
+  List<String> recordPath = List();
 
   @override
   void initState() {
     super.initState();
-    initPlatform();
+  }
+
+  @override
+  void dispose() {
+    _durationSubscription.cancel();
+    _controller.dispose();
+    super.dispose();
   }
 
   Future<void> initPlatform() async {
-    await _controller.create();
+    await _controller.create(
+        recordOption: CameraRecordOption(
+            videoWidth: 720, videoHeight: 1280, quality: VideoQuality.SD));
+    _durationSubscription = _controller.recordUpdate.listen((result) {
+      print("record update" + result.toString());
+      if (result.containsKey("path")) {
+        print("录制完成");
+        setState(() {
+          recording = false;
+          recordPath.add(result['path']);
+        });
+      }
+    });
     setState(() {});
   }
 
   void _onPlatformViewCreated() {
+    initPlatform();
+  }
+
+  static Future<String> _findLocalPath() async {
+    final directory = Platform.isAndroid
+        ? await getExternalStorageDirectory()
+        : await getApplicationDocumentsDirectory();
+    return directory.path;
+  }
+
+  Future<void> _record() async {
+    setState(() {
+      recording = true;
+    });
+    String mp4Path = path.join(await _findLocalPath(), "1.mp4");
+    _controller.startRecord(duration, mp4Path);
+  }
+
+  void _compose() async {
+    if (recordPath.length == 0) return;
+    String resultPath = path.join(await _findLocalPath(), "result.mp4");
+    bool success = await _controller.startCompose(
+      resultPath,
+      null,
+      recordPath,
+      recordPath.map((f) => duration).toList(),
+      CameraComposeOption(
+          outputWidth: 480,
+          outputHeight: 480 * 16 ~/ 9,
+          videoCodecs: VideoCodecs.H264_HARDWARE,
+          quality: VideoQuality.SD,
+          frameRate: 20,
+          bitrate: 500000),
+    );
+    print("compose result: ${success ? "successful" : "failed"}");
   }
 
   @override
@@ -41,7 +100,8 @@ class _MyAppState extends State<MyApp> {
         appBar: AppBar(
           title: const Text('Plugin example app'),
         ),
-        body: Column(
+        body: ListView(
+          padding: EdgeInsets.symmetric(horizontal: 10),
           children: <Widget>[
             SizedBox(
               width: double.maxFinite,
@@ -51,22 +111,67 @@ class _MyAppState extends State<MyApp> {
             Row(
               mainAxisAlignment: MainAxisAlignment.spaceEvenly,
               children: <Widget>[
-                IconButton(icon: Icon(Icons.play_arrow, size: 26,), onPressed: () {
-                  _controller.startPreview();
-                }),
-                IconButton(icon: Icon(Icons.pause, size: 26,), onPressed: () {
-                  _controller.stopPreview();
-                }),
+                IconButton(
+                    icon: Icon(
+                      Icons.play_arrow,
+                      size: 26,
+                    ),
+                    onPressed: () {
+                      if (!recording) _controller.startPreview();
+                    }),
+                IconButton(
+                    icon: Icon(
+                      Icons.pause,
+                      size: 26,
+                    ),
+                    onPressed: () {
+                      if (!recording) _controller.stopPreview();
+                    }),
+                IconButton(
+                    icon: Icon(
+                      Icons.switch_camera,
+                      size: 26,
+                    ),
+                    onPressed: () {
+                      if (!recording) _controller.switchCamera();
+                    }),
+                IconButton(
+                    icon: Icon(
+                      recording ? Icons.stop : Icons.fiber_manual_record,
+                      size: 26,
+                    ),
+                    onPressed: () {
+                      if (!recording) _record();
+                    }),
+                IconButton(
+                    icon: Icon(
+                      Icons.settings,
+                      size: 26,
+                    ),
+                    onPressed: () {
+                      if (!recording) _compose();
+                    }),
+              ],
+            ),
+            SizedBox(
+              height: 5,
+            ),
+            Row(
+              children: <Widget>[
+                Text("美颜0-100"),
+                Expanded(
+                  child: Slider(
+                      value: value,
+                      max: 100,
+                      onChanged: (value) {
+                        _controller.setBeauty(value.toInt());
+                        setState(() {
+                          this.value = value;
+                        });
+                      }),
+                ),
               ],
             ),
-            SizedBox(height: 5,),
-            Slider(value: value, max: 100, onChanged: (value) {
-              _controller.setBeauty(value.toInt());
-              setState(() {
-                this.value = value;
-              });
-            }),
-
           ],
         ),
       ),

+ 8 - 0
example/pubspec.lock

@@ -109,6 +109,13 @@ packages:
       url: "https://pub.flutter-io.cn"
     source: hosted
     version: "1.6.4"
+  path_provider:
+    dependency: "direct main"
+    description:
+      name: path_provider
+      url: "https://pub.flutter-io.cn"
+    source: hosted
+    version: "0.4.1"
   pedantic:
     dependency: transitive
     description:
@@ -200,3 +207,4 @@ packages:
     version: "3.5.0"
 sdks:
   dart: ">=2.4.0 <3.0.0"
+  flutter: ">=0.1.4 <2.0.0"

+ 1 - 0
example/pubspec.yaml

@@ -12,6 +12,7 @@ dependencies:
   # The following adds the Cupertino Icons font to your application.
   # Use with the CupertinoIcons class for iOS style icons.
   cupertino_icons: ^0.1.2
+  path_provider: '^0.4.1'
 
 dev_dependencies:
   flutter_test:

+ 2 - 0
lib/ali_camera.dart

@@ -0,0 +1,2 @@
+export 'ali_camera_controller.dart';
+export 'camera_option.dart';

+ 36 - 3
lib/flutter_ali_camera.dart → lib/ali_camera_controller.dart

@@ -7,9 +7,12 @@ import 'package:flutter/services.dart';
 import 'package:flutter_ali_camera/camera_option.dart';
 
 class FlutterAliCameraController {
+
   static const MethodChannel _channel =
       const MethodChannel('flutter_ali_camera');
   static const String viewType = "com.i2edu.cameraLib";
+  final StreamController<Map> _recordController = StreamController.broadcast();
+  Stream<Map> get recordUpdate => _recordController.stream;
 
   static Future<String> get platformVersion async {
     final String version = await _channel.invokeMethod('getPlatformVersion');
@@ -20,8 +23,9 @@ class FlutterAliCameraController {
     return _channel.invokeMethod("initializeSdk");
   }
 
-  Future<void> create() async {
-    return await _channel.invokeMethod("create", {});
+  Future<void> create({@required CameraRecordOption recordOption}) async {
+    _channel.setMethodCallHandler(_onMethodCallHandler);
+    return await _channel.invokeMethod("create", {"recordOption": recordOption.toMap()});
   }
 
   Widget buildView(VoidCallback onPlatformViewCreated) {
@@ -60,7 +64,36 @@ class FlutterAliCameraController {
     return _channel.invokeMethod("setFilter", {"path": path});
   }
 
-  Future<void> onDestroy() {
+  Future<void> startRecord(int max, String recordPath) {
+    return _channel.invokeMethod("startRecord", {"max": max, "recordPath": recordPath});
+  }
+
+  Future<bool> startCompose(String outputPath, String bgmPath,
+      List<String> paths, List<int> durations, CameraComposeOption option) {
+    if (paths.length != durations.length) {
+      print("error: length error");
+      return null;
+    }
+    return _channel.invokeMethod("startCompose", {
+      "outputPath": outputPath,
+      "bgmPath": bgmPath,
+      "paths": paths,
+      "durations": durations,
+      "composeOption": option.toMap()
+    });
+  }
+
+  Future _onMethodCallHandler(MethodCall call) {
+    print(call.arguments);
+    switch (call.method) {
+      case "recordUpdate":
+        _recordController.add(call.arguments);
+        break;
+    }
+    return null;
+  }
+
+  Future<void> dispose() async {
     return _channel.invokeMethod("onDestroy");
   }
 }

+ 81 - 8
lib/camera_option.dart

@@ -1,13 +1,86 @@
-import 'dart:collection';
+class CameraRecordOption {
+  int videoWidth;
+  int videoHeight;
+  int fps;
+  VideoCodecs videoCodecs;
+  int crf;
+  int encoderFps;
+  VideoQuality quality;
+  int videoBitrate;
+  int gop;
 
-class CameraOption {
-  final Map<String, dynamic> outPutMap = HashMap();
+  CameraRecordOption(
+      {this.videoWidth,
+      this.videoHeight,
+      this.fps,
+      this.videoCodecs,
+      this.crf,
+      this.encoderFps,
+      this.quality,
+      this.videoBitrate,
+      this.gop});
+
+  Map toMap() {
+    Map data = {
+      "videoWidth": videoWidth,
+      "videoHeight": videoHeight,
+      "fps": fps,
+      "videoCodecs": videoCodecs?.index,
+      "crf": crf,
+      "encoderFps": encoderFps,
+      "quality": quality?.index,
+      "videoBitrate": videoBitrate,
+      "gop": gop,
+    };
+    data.removeWhere((key, value) => value == null);
+    return data;
+  }
 }
 
-enum VideoCodecs {
-  H264_HARDWARE,
-  H264_SOFT_OPENH264,
-  H264_SOFT_FFMPEG,
+class CameraComposeOption {
+  int outputWidth;
+  int outputHeight;
+  int frameRate;
+  int crf;
+  int gop;
+  int bitrate;
+  double scaleRate;
+  VideoCodecs videoCodecs;
+  VideoQuality quality;
+  VideoDisplayMode scaleMode;
+
+  CameraComposeOption(
+      {this.outputWidth,
+      this.outputHeight,
+      this.frameRate,
+      this.crf,
+      this.gop,
+      this.bitrate,
+      this.scaleRate,
+      this.videoCodecs,
+      this.quality,
+      this.scaleMode});
+
+  Map toMap() {
+    Map data = {
+      "outputWidth": outputWidth,
+      "outputHeight": outputHeight,
+      "frameRate": frameRate,
+      "crf": crf,
+      "gop": gop,
+      "bitrate": bitrate,
+      "scaleRate": scaleRate,
+      "videoCodecs": videoCodecs?.index,
+      "quality": quality?.index,
+      "scaleMode": scaleMode?.index,
+    };
+    data.removeWhere((key, value) => value == null);
+    return data;
+  }
 }
 
-enum CameraType { Back, Front }
+enum VideoCodecs { H264_HARDWARE, H264_SOFT_OPENH264, H264_SOFT_FFMPEG }
+
+enum VideoQuality { SSD, HD, SD, LD, PD, EPD }
+
+enum VideoDisplayMode { SCALE, FILL }

+ 1 - 1
test/flutter_ali_camera_test.dart

@@ -1,6 +1,6 @@
 import 'package:flutter/services.dart';
 import 'package:flutter_test/flutter_test.dart';
-import 'package:flutter_ali_camera/flutter_ali_camera.dart';
+import 'package:flutter_ali_camera/ali_camera.dart';
 
 void main() {
   const MethodChannel channel = MethodChannel('flutter_ali_camera');