├── .gitignore ├── .gradle ├── 5.1.1 │ ├── fileChanges │ │ └── last-build.bin │ ├── fileHashes │ │ └── fileHashes.lock │ └── gc.properties ├── buildOutputCleanup │ ├── buildOutputCleanup.lock │ └── cache.properties └── vcs-1 │ └── gc.properties ├── .metadata ├── CHANGELOG.md ├── LICENSE ├── README.md ├── android ├── .gitignore ├── build.gradle ├── gradle.properties ├── settings.gradle └── src │ └── main │ ├── AndroidManifest.xml │ ├── kotlin │ └── syscall │ │ └── zixuan │ │ └── com │ │ └── flutter_sys_call │ │ ├── FlutterSysCallPlugin.kt │ │ ├── VideoFileProvider.kt │ │ └── video │ │ └── takevideo │ │ ├── CameraActivity.kt │ │ ├── camera │ │ ├── CameraManager.kt │ │ ├── CameraProgressBar.kt │ │ ├── CameraUtils.kt │ │ ├── CameraView.kt │ │ ├── MediaPlayerManager.kt │ │ └── ViewClickOnSubscribe.kt │ │ └── utils │ │ ├── FileUtils.kt │ │ ├── LogUtils.kt │ │ ├── RequestCode.kt │ │ └── SPUtils.kt │ └── res │ ├── drawable │ ├── btn_camera_flash.xml │ ├── camera_choice.png │ ├── camera_close.png │ ├── camera_facing.png │ ├── camera_flash_close.png │ └── camera_flash_open.png │ ├── layout │ └── activity_camera.xml │ ├── values │ └── styles.xml │ └── xml │ └── video_file_path.xml ├── example ├── .flutter-plugins-dependencies ├── .gitignore ├── .metadata ├── README.md ├── android │ ├── app │ │ ├── build.gradle │ │ └── src │ │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── kotlin │ │ │ │ └── syscall │ │ │ │ │ └── zixuan │ │ │ │ │ └── com │ │ │ │ │ └── flutter_sys_call_example │ │ │ │ │ └── MainActivity.kt │ │ │ └── res │ │ │ │ ├── drawable │ │ │ │ └── launch_background.xml │ │ │ │ ├── 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 │ │ │ │ └── values │ │ │ │ └── styles.xml │ │ │ └── profile │ │ │ └── AndroidManifest.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ └── gradle-wrapper.properties │ └── settings.gradle ├── ios │ ├── Flutter │ │ ├── AppFrameworkInfo.plist │ │ ├── Debug.xcconfig │ │ ├── Flutter.podspec │ │ ├── Release.xcconfig │ │ └── flutter_export_environment.sh │ ├── Podfile │ ├── Runner.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── Runner │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ ├── 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-83.5x83.5@2x.png │ │ ├── Contents.json │ │ ├── LaunchImage.imageset │ │ │ ├── Contents.json │ │ │ ├── LaunchImage.png │ │ │ ├── LaunchImage@2x.png │ │ │ ├── LaunchImage@3x.png │ │ │ └── README.md │ │ ├── back_nor.imageset │ │ │ ├── Contents.json │ │ │ └── 微信图片_20190610092524.png │ │ ├── back_pressed.imageset │ │ │ ├── Contents.json │ │ │ └── 微信图片_20190610092518.png │ │ ├── device_scan.imageset │ │ │ ├── Contents.json │ │ │ └── device_scan@2x.png │ │ ├── qrcode_Scan_weixin_Line.imageset │ │ │ ├── Contents.json │ │ │ └── qrcode_Scan_weixin_Line@2x.png │ │ ├── qrcode_scan_btn_flash_down.imageset │ │ │ ├── Contents.json │ │ │ └── qrcode_scan_btn_flash_down@2x.png │ │ ├── qrcode_scan_btn_flash_nor.imageset │ │ │ ├── Contents.json │ │ │ └── qrcode_scan_btn_flash_nor@2x.png │ │ ├── qrcode_scan_btn_myqrcode_down.imageset │ │ │ ├── Contents.json │ │ │ └── qrcode_scan_btn_myqrcode_down@2x.png │ │ ├── qrcode_scan_btn_myqrcode_nor.imageset │ │ │ ├── Contents.json │ │ │ └── qrcode_scan_btn_myqrcode_nor@2x.png │ │ ├── qrcode_scan_btn_photo_down.imageset │ │ │ ├── Contents.json │ │ │ └── qrcode_scan_btn_photo_down@2x.png │ │ ├── qrcode_scan_btn_photo_nor.imageset │ │ │ ├── Contents.json │ │ │ └── qrcode_scan_btn_photo_nor@2x.png │ │ ├── qrcode_scan_btn_scan_off.imageset │ │ │ ├── Contents.json │ │ │ └── qrcode_scan_btn_scan_off@2x.png │ │ ├── qrcode_scan_full_net.imageset │ │ │ ├── Contents.json │ │ │ └── qrcode_scan_full_net.png │ │ ├── qrcode_scan_light_green.imageset │ │ │ ├── Contents.json │ │ │ └── qrcode_scan_light_green@2x.png │ │ ├── qrcode_scan_part_net.imageset │ │ │ ├── Contents.json │ │ │ └── qrcode_scan_part_net.png │ │ ├── qrcode_scan_titlebar_back_nor.imageset │ │ │ ├── Contents.json │ │ │ └── qrcode_scan_titlebar_back_nor@2x.png │ │ └── qrcode_scan_titlebar_back_pressed.imageset │ │ │ ├── Contents.json │ │ │ └── qrcode_scan_titlebar_back_pressed@2x.png │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── Info.plist │ │ └── Runner-Bridging-Header.h ├── lib │ ├── main.dart │ ├── main_page.dart │ └── preview_video_page.dart └── pubspec.yaml ├── flutter_sys_call.iml ├── ios ├── .gitignore ├── Assets │ └── .gitkeep ├── Classes │ ├── FlutterSysCallPlugin.h │ ├── FlutterSysCallPlugin.m │ ├── QQScanViewController.swift │ ├── SwiftFlutterSysCallPlugin.swift │ └── swiftScan.podspec └── flutter_sys_call.podspec ├── lib ├── flutter_sys_call.dart ├── kotlin-reflect-sources.jar ├── kotlin-reflect.jar ├── kotlin-stdlib-jdk7-sources.jar ├── kotlin-stdlib-jdk7.jar ├── kotlin-stdlib-jdk8-sources.jar ├── kotlin-stdlib-jdk8.jar ├── kotlin-stdlib-sources.jar ├── kotlin-stdlib.jar ├── kotlin-test-sources.jar └── kotlin-test.jar └── pubspec.yaml /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .DS_Store 3 | .dart_tool/ 4 | 5 | .packages 6 | .pub/ 7 | pubspec.lock 8 | 9 | build/ 10 | 11 | -------------------------------------------------------------------------------- /.gradle/5.1.1/fileChanges/last-build.bin: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gradle/5.1.1/fileHashes/fileHashes.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/.gradle/5.1.1/fileHashes/fileHashes.lock -------------------------------------------------------------------------------- /.gradle/5.1.1/gc.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/.gradle/5.1.1/gc.properties -------------------------------------------------------------------------------- /.gradle/buildOutputCleanup/buildOutputCleanup.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/.gradle/buildOutputCleanup/buildOutputCleanup.lock -------------------------------------------------------------------------------- /.gradle/buildOutputCleanup/cache.properties: -------------------------------------------------------------------------------- 1 | #Sat Jun 01 15:10:25 CST 2019 2 | gradle.version=5.1.1 3 | -------------------------------------------------------------------------------- /.gradle/vcs-1/gc.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/.gradle/vcs-1/gc.properties -------------------------------------------------------------------------------- /.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: 8661d8aecd626f7f57ccbcb735553edc05a2e713 8 | channel: stable 9 | 10 | project_type: plugin 11 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 1.0.1 2 | 1.更新插件内的第三方插件版本 3 | 4 | ## 1.0.0 5 | 1.实现设备震动调用 6 | 2.实现视频录制,二维码扫描,图片拍取 7 | 3.具体使用可参考example -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | TODO: Add your license here. 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # flutter_sys_call . 2 | [pub package](https://pub.flutter-io.cn/packages/flutter_sys_call) 3 | 4 | 系统调用小插件 5 | 6 | ## Getting Started 7 | 8 | This project is a starting point for a Flutter 9 | [plug-in package](https://flutter.io/developing-packages/), 10 | a specialized package that includes platform-specific implementation code for 11 | Android and/or iOS. 12 | 13 | For help getting started with Flutter, view our 14 | [online documentation](https://flutter.io/docs), which offers tutorials, 15 | samples, guidance on mobile development, and a full API reference. 16 | # flutter_sys_call 17 | 18 | 第一版支持系统调用震动功能 19 | 20 | # flutter_sys_call 21 | 22 | #使用方式 23 | 24 | Android需要加入震动权限: 25 | "" 26 | 27 | 导入:import 'package:flutter_sys_call/flutter_sys_call.dart'; 28 | 29 | 使用震动 FlutterSysCall.doVibrator; 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /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/build.gradle: -------------------------------------------------------------------------------- 1 | group 'syscall.zixuan.com.flutter_sys_call' 2 | version '1.0-SNAPSHOT' 3 | 4 | buildscript { 5 | ext.kotlin_version = '1.3.31' 6 | repositories { 7 | google() 8 | jcenter() 9 | } 10 | 11 | dependencies { 12 | classpath 'com.android.tools.build:gradle:3.4.2' 13 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 14 | } 15 | } 16 | 17 | rootProject.allprojects { 18 | repositories { 19 | google() 20 | jcenter() 21 | } 22 | } 23 | 24 | apply plugin: 'com.android.library' 25 | apply plugin: 'kotlin-android' 26 | 27 | android { 28 | compileSdkVersion 28 29 | 30 | sourceSets { 31 | main.java.srcDirs += 'src/main/kotlin' 32 | } 33 | defaultConfig { 34 | minSdkVersion 16 35 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 36 | } 37 | lintOptions { 38 | disable 'InvalidPackage' 39 | } 40 | } 41 | 42 | dependencies { 43 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 44 | //RXJava 45 | implementation 'io.reactivex:rxandroid:1.2.1' 46 | 47 | api 'androidx.appcompat:appcompat:1.0.0' 48 | 49 | implementation 'com.github.tbruyelle:rxpermissions:0.10.2' 50 | 51 | implementation 'com.github.yuzhiqiang1993:zxing:2.2.8' 52 | } 53 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'flutter_sys_call' 2 | -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 23 | 26 | 27 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /android/src/main/kotlin/syscall/zixuan/com/flutter_sys_call/FlutterSysCallPlugin.kt: -------------------------------------------------------------------------------- 1 | package syscall.zixuan.com.flutter_sys_call 2 | 3 | import android.Manifest 4 | import android.app.Activity 5 | import android.content.BroadcastReceiver 6 | import android.content.Context 7 | import android.content.Intent 8 | import android.content.pm.PackageManager 9 | import android.os.Vibrator 10 | import androidx.core.app.ActivityCompat 11 | import androidx.core.content.ContextCompat 12 | import io.flutter.plugin.common.EventChannel 13 | import io.flutter.plugin.common.MethodCall 14 | import io.flutter.plugin.common.MethodChannel 15 | import io.flutter.plugin.common.MethodChannel.MethodCallHandler 16 | import io.flutter.plugin.common.MethodChannel.Result 17 | import io.flutter.plugin.common.PluginRegistry 18 | import io.flutter.plugin.common.PluginRegistry.Registrar 19 | import syscall.zixuan.com.flutter_sys_call.video.takevideo.CameraActivity 20 | import syscall.zixuan.com.flutter_sys_call.video.takevideo.utils.RequestCode 21 | import androidx.core.app.ActivityCompat.startActivityForResult 22 | import com.yzq.zxinglibrary.android.CaptureActivity 23 | import com.yzq.zxinglibrary.common.Constant 24 | 25 | 26 | class FlutterSysCallPlugin(newActivity: Activity) : MethodCallHandler, PluginRegistry.ActivityResultListener, PluginRegistry.RequestPermissionsResultListener { 27 | 28 | var SCAN_CODE = 300; 29 | 30 | 31 | var activity: Activity? = null; 32 | 33 | private var result: Result? = null; 34 | 35 | init { 36 | activity = newActivity; 37 | } 38 | 39 | var permissionList = arrayOf(Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO) 40 | 41 | companion object { 42 | @JvmStatic 43 | fun registerWith(registrar: Registrar) { 44 | 45 | var flutterSysCallPlugin = FlutterSysCallPlugin(registrar.activity()) 46 | //方法调用监听 47 | val methodChannel = MethodChannel(registrar.messenger(), "flutter_sys_call") 48 | methodChannel.setMethodCallHandler(flutterSysCallPlugin) 49 | ///监听页面调用的回调 50 | // 注册ActivityResult回调 51 | registrar.addActivityResultListener(flutterSysCallPlugin); 52 | //权限回调监听 53 | registrar.addRequestPermissionsResultListener(flutterSysCallPlugin); 54 | 55 | ///事件上报监听 56 | val eventChannel = EventChannel(registrar.messenger(), "flutter_sys_call.even") 57 | 58 | eventChannel.setStreamHandler(object : EventChannel.StreamHandler { 59 | override fun onListen(objectc: Any?, evenSink: EventChannel.EventSink?) { 60 | 61 | } 62 | 63 | override fun onCancel(p0: Any?) { 64 | 65 | } 66 | 67 | }) 68 | 69 | } 70 | } 71 | 72 | override fun onMethodCall(call: MethodCall, result: Result) { 73 | 74 | this.result = result; 75 | 76 | when (call.method) { 77 | "getPlatformVersion" -> { 78 | result.success("Android ${android.os.Build.VERSION.RELEASE}") 79 | } 80 | "doVibrator" -> { 81 | doVibrator() 82 | result.success(true); 83 | } 84 | "recordVideo" -> { 85 | if (checkReadPermission(permissionList, 300)) { 86 | activity!!.startActivityForResult(Intent(activity, CameraActivity::class.java), 200) 87 | } 88 | } 89 | "QRScan" -> { 90 | val intent = Intent(activity!!, CaptureActivity::class.java) 91 | activity!!.startActivityForResult(intent, SCAN_CODE) 92 | } 93 | else -> { 94 | result.notImplemented() 95 | } 96 | } 97 | if (call.method == "getPlatformVersion") { 98 | 99 | } else { 100 | 101 | } 102 | 103 | 104 | } 105 | 106 | /** 107 | * 震动 108 | */ 109 | private fun doVibrator() { 110 | val vibrator = activity!!.getSystemService(Activity.VIBRATOR_SERVICE) as Vibrator; 111 | vibrator.vibrate(longArrayOf(100, 1000, 500, 1000), -1); 112 | } 113 | 114 | private fun checkReadPermission(permissions: Array, requestCode: Int): Boolean { 115 | 116 | var flag = true; 117 | for (permission in permissionList) { 118 | if (ContextCompat.checkSelfPermission(activity!!.baseContext, permission) != PackageManager.PERMISSION_GRANTED) { 119 | flag = false; 120 | ActivityCompat.requestPermissions(activity!!, permissions, requestCode); 121 | } 122 | 123 | } 124 | 125 | 126 | return flag; 127 | } 128 | 129 | ///Activity回调 130 | override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?): Boolean { 131 | 132 | System.out.println("返回码" + resultCode + "请求码" + requestCode) 133 | 134 | 135 | if (data != null) { 136 | print(requestCode); 137 | if (resultCode == RequestCode.TAKE_PHOTO) { 138 | ///拍图片 139 | ///返回图片路径 140 | result!!.success(data.getStringExtra("photo")) 141 | 142 | } else if (resultCode == RequestCode.TAKE_VIDEO) { 143 | ///拍视频 144 | ///返回视屏路径 145 | result!!.success(data.getStringExtra("video")) 146 | } else if (requestCode == SCAN_CODE) { 147 | result!!.success(data.getStringExtra(Constant.CODED_CONTENT)) 148 | } 149 | } 150 | 151 | 152 | return false; 153 | } 154 | 155 | ///请求权限回调 156 | override fun onRequestPermissionsResult(requestCode: Int, permissions: Array?, grants: IntArray?): Boolean { 157 | 158 | print("请求" + grants!!.toList()) 159 | 160 | var flag = true; 161 | for (grand in grants!!) { 162 | if (grand != PackageManager.PERMISSION_GRANTED) { 163 | flag = false; 164 | } 165 | } 166 | return false; 167 | 168 | } 169 | 170 | 171 | // fun createChargingStateChangeReceiver(events: EventChannel.EventSink): BroadcastReceiver { 172 | // 173 | // 174 | // 175 | // 176 | // } 177 | 178 | } 179 | -------------------------------------------------------------------------------- /android/src/main/kotlin/syscall/zixuan/com/flutter_sys_call/VideoFileProvider.kt: -------------------------------------------------------------------------------- 1 | package syscall.zixuan.com.flutter_sys_call 2 | 3 | import androidx.core.content.FileProvider 4 | 5 | /** 6 | * @author : yanghuaxuan / yanghuaxuan@seerbigdata.com 7 | * @date : 2019-06-01 8 | * @version : 1.0.0 9 | */ 10 | public class VideoFileProvider : FileProvider() { 11 | 12 | } -------------------------------------------------------------------------------- /android/src/main/kotlin/syscall/zixuan/com/flutter_sys_call/video/takevideo/CameraActivity.kt: -------------------------------------------------------------------------------- 1 | package syscall.zixuan.com.flutter_sys_call.video.takevideo 2 | 3 | import android.app.Activity 4 | import android.content.Context 5 | import android.content.Intent 6 | import android.graphics.PointF 7 | import android.graphics.SurfaceTexture 8 | import android.hardware.Camera 9 | import android.os.Bundle 10 | import android.view.Surface 11 | import android.view.TextureView 12 | import android.view.View 13 | import android.widget.ImageView 14 | import android.widget.RelativeLayout 15 | import android.widget.TextView 16 | import androidx.appcompat.app.AppCompatActivity 17 | import rx.Observable 18 | import rx.Subscriber 19 | import rx.Subscription 20 | import rx.android.schedulers.AndroidSchedulers 21 | import rx.schedulers.Schedulers 22 | import syscall.zixuan.com.flutter_sys_call.R 23 | import syscall.zixuan.com.flutter_sys_call.video.takevideo.camera.CameraManager 24 | import syscall.zixuan.com.flutter_sys_call.video.takevideo.camera.CameraProgressBar 25 | import syscall.zixuan.com.flutter_sys_call.video.takevideo.camera.CameraView 26 | import syscall.zixuan.com.flutter_sys_call.video.takevideo.camera.MediaPlayerManager 27 | import syscall.zixuan.com.flutter_sys_call.video.takevideo.utils.FileUtils 28 | import syscall.zixuan.com.flutter_sys_call.video.takevideo.utils.RequestCode 29 | 30 | import java.io.File 31 | import java.util.concurrent.TimeUnit 32 | 33 | 34 | class CameraActivity : AppCompatActivity(), View.OnClickListener { 35 | 36 | private var mContext: Context? = null 37 | /** 38 | * TextureView 39 | */ 40 | private var mTextureView: TextureView? = null 41 | /** 42 | * 带手势识别 43 | */ 44 | private var mCameraView: CameraView? = null 45 | /** 46 | * 录制按钮 47 | */ 48 | private var mProgressbar: CameraProgressBar? = null 49 | /** 50 | * 顶部像机设置 51 | */ 52 | private var rl_camera: RelativeLayout? = null 53 | /** 54 | * 关闭,选择,前后置 55 | */ 56 | private var iv_close: ImageView? = null 57 | private var iv_choice: ImageView? = null 58 | private var iv_facing: ImageView? = null 59 | /** 60 | * 是否在录制 61 | */ 62 | private var isRealRecord = false; 63 | /** 64 | * 是否选择了前置摄像头 65 | */ 66 | private var isFont = false; 67 | /** 68 | * 闪光 69 | */ 70 | private var tv_flash: TextView? = null 71 | /** 72 | * camera manager 73 | */ 74 | private var cameraManager: CameraManager? = null 75 | /** 76 | * player manager 77 | */ 78 | private var playerManager: MediaPlayerManager? = null 79 | /** 80 | * true代表视频录制,否则拍照 81 | */ 82 | private var isSupportRecord: Boolean = false 83 | /** 84 | * 视频录制地址 85 | */ 86 | private var recorderPath: String? = null 87 | /** 88 | * 录制视频的时间,毫秒 89 | */ 90 | private var recordSecond: Int = 0 91 | /** 92 | * 获取照片订阅, 进度订阅 93 | */ 94 | private var takePhotoSubscription: Subscription? = null 95 | private var progressSubscription: Subscription? = null 96 | /** 97 | * 是否正在录制 98 | */ 99 | private var isRecording: Boolean = false 100 | 101 | /** 102 | * 是否为点了拍摄状态(没有拍照预览的状态) 103 | */ 104 | private var isPhotoTakingState: Boolean = false 105 | private var mTv_tack: TextView? = null 106 | 107 | /** 108 | * camera回调监听 109 | */ 110 | private val listener = object : TextureView.SurfaceTextureListener { 111 | override fun onSurfaceTextureAvailable(texture: SurfaceTexture, width: Int, height: Int) { 112 | if (recorderPath != null) { 113 | iv_choice!!.visibility = View.VISIBLE 114 | setTakeButtonShow(false) 115 | playerManager!!.playMedia(Surface(texture), recorderPath!!) 116 | } else { 117 | setTakeButtonShow(true) 118 | iv_choice!!.visibility = View.GONE 119 | cameraManager!!.openCamera(this@CameraActivity, texture, width, height) 120 | } 121 | } 122 | 123 | override fun onSurfaceTextureSizeChanged(texture: SurfaceTexture, width: Int, height: Int) {} 124 | 125 | override fun onSurfaceTextureDestroyed(texture: SurfaceTexture): Boolean { 126 | return true 127 | } 128 | 129 | override fun onSurfaceTextureUpdated(texture: SurfaceTexture) {} 130 | } 131 | private var photo: String? = null 132 | 133 | private val callback = Camera.PictureCallback { data, camera -> 134 | setTakeButtonShow(false) 135 | takePhotoSubscription = Observable.create(object : Observable.OnSubscribe { 136 | override fun call(subscriber: Subscriber) { 137 | if (!subscriber.isUnsubscribed()) { 138 | val photoPath = FileUtils.getUploadPhotoFile(this@CameraActivity) 139 | //保存拍摄的图片 140 | isPhotoTakingState = FileUtils.savePhoto(photoPath, data, cameraManager!!.isCameraFrontFacing) 141 | if (isPhotoTakingState) { 142 | photo = photoPath 143 | } 144 | subscriber.onNext(isPhotoTakingState) 145 | } 146 | } 147 | }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()) 148 | .subscribe(object : Subscriber() { 149 | override fun onCompleted() { 150 | 151 | } 152 | 153 | override fun onError(e: Throwable) { 154 | 155 | } 156 | 157 | override fun onNext(aBoolean: Boolean?) { 158 | if (aBoolean != null && aBoolean) { 159 | iv_choice!!.visibility = View.VISIBLE 160 | } else { 161 | setTakeButtonShow(true) 162 | } 163 | } 164 | }) 165 | } 166 | 167 | override fun onCreate(savedInstanceState: Bundle?) { 168 | super.onCreate(savedInstanceState) 169 | mContext = this 170 | setContentView(R.layout.activity_camera) 171 | initView() 172 | initDatas() 173 | } 174 | 175 | 176 | private fun initView() { 177 | mTextureView = findViewById(R.id.mTextureView) as TextureView 178 | mCameraView = findViewById(R.id.mCameraView) as CameraView 179 | mProgressbar = findViewById(R.id.mProgressbar) as CameraProgressBar 180 | rl_camera = findViewById(R.id.rl_camera) as RelativeLayout 181 | iv_close = findViewById(R.id.iv_close) as ImageView 182 | iv_choice = findViewById(R.id.iv_choice) as ImageView 183 | iv_facing = findViewById(R.id.iv_facing) as ImageView 184 | tv_flash = findViewById(R.id.tv_flash) as TextView 185 | mTv_tack = findViewById(R.id.tv_tack) as TextView 186 | iv_close!!.setOnClickListener(this) 187 | iv_choice!!.setOnClickListener(this) 188 | iv_facing!!.setOnClickListener(this) 189 | tv_flash!!.setOnClickListener(this) 190 | } 191 | 192 | protected fun initDatas() { 193 | cameraManager = CameraManager.getInstance(application) 194 | playerManager = MediaPlayerManager.getInstance(application) 195 | cameraManager!!.setCameraType(if (isSupportRecord) 1 else 0) 196 | 197 | // tv_flash!!.visibility = if (cameraManager!!.isSupportFlashCamera) View.VISIBLE else View.GONE 198 | // setCameraFlashState() 199 | // iv_facing!!.visibility = if (cameraManager!!.isSupportFrontCamera) View.VISIBLE else View.GONE 200 | //rl_camera!!.visibility = if (cameraManager!!.isSupportFlashCamera || cameraManager!!.isSupportFrontCamera) 201 | // View.VISIBLE 202 | // else 203 | // View.GONE 204 | 205 | val max = MAX_RECORD_TIME / PLUSH_PROGRESS 206 | mProgressbar!!.setMaxProgress(max) 207 | 208 | mProgressbar!!.setOnProgressTouchListener(object : CameraProgressBar.OnProgressTouchListener { 209 | override fun onClick(progressBar: CameraProgressBar) { 210 | mTv_tack!!.visibility = View.GONE 211 | cameraManager!!.takePhoto(callback) 212 | } 213 | 214 | override fun onLongClick(progressBar: CameraProgressBar) { 215 | mTv_tack!!.visibility = View.GONE 216 | isSupportRecord = true 217 | cameraManager!!.setCameraType(1) 218 | rl_camera!!.visibility = View.GONE 219 | recorderPath = FileUtils.getUploadVideoFile(this@CameraActivity) 220 | cameraManager!!.startMediaRecord(recorderPath!!) 221 | isRecording = true 222 | progressSubscription = 223 | Observable.interval(100, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread()).take(max) 224 | .subscribe(object : Subscriber() { 225 | override fun onCompleted() { 226 | stopRecorder(true) 227 | } 228 | 229 | override fun onError(e: Throwable) { 230 | 231 | } 232 | 233 | override fun onNext(aLong: Long?) { 234 | mProgressbar!!.setProgress(mProgressbar!!.getProgress() + 1) 235 | } 236 | }) 237 | } 238 | 239 | override fun onZoom(zoom: Boolean) { 240 | cameraManager!!.handleZoom(zoom) 241 | } 242 | 243 | override fun onLongClickUp(progressBar: CameraProgressBar) { 244 | isSupportRecord = false 245 | cameraManager!!.setCameraType(0) 246 | stopRecorder(true) 247 | if (progressSubscription != null) { 248 | progressSubscription!!.unsubscribe() 249 | } 250 | } 251 | 252 | override fun onPointerDown(rawX: Float, rawY: Float) { 253 | if (mTextureView != null) { 254 | mCameraView!!.setFoucsPoint(PointF(rawX, rawY)) 255 | } 256 | } 257 | }) 258 | 259 | mCameraView!!.setOnViewTouchListener(object : CameraView.OnViewTouchListener { 260 | 261 | override fun handleFocus(x: Float, y: Float) { 262 | if (!isPhotoTakingState) { 263 | if (!cameraManager!!.isTakePhotoOrVideo) { 264 | cameraManager!!.handleFocusMetering(x, y) 265 | } 266 | 267 | } 268 | 269 | } 270 | 271 | override fun handleZoom(zoom: Boolean) { 272 | cameraManager!!.handleZoom(zoom) 273 | } 274 | }) 275 | } 276 | 277 | /** 278 | * 设置闪光状态 279 | */ 280 | private fun setCameraFlashState() { 281 | val flashState = cameraManager!!.cameraFlash 282 | when (flashState) { 283 | 0 //自动 284 | -> { 285 | tv_flash!!.isSelected = true 286 | tv_flash!!.text = "自动" 287 | } 288 | 1//open 289 | -> { 290 | tv_flash!!.isSelected = true 291 | tv_flash!!.text = "开启" 292 | } 293 | 2 //close 294 | -> { 295 | tv_flash!!.isSelected = false 296 | tv_flash!!.text = "关闭" 297 | } 298 | } 299 | } 300 | 301 | /** 302 | * 是否显示录制按钮 303 | * 304 | * @param isShow 305 | */ 306 | private fun setTakeButtonShow(isShow: Boolean) { 307 | if (isShow) { 308 | mProgressbar!!.setVisibility(View.VISIBLE) 309 | rl_camera!!.visibility = 310 | if (cameraManager!!.isSupportFlashCamera or cameraManager!!.isSupportFrontCamera) 311 | View.VISIBLE 312 | else 313 | View.GONE 314 | } else { 315 | mProgressbar!!.setVisibility(View.GONE) 316 | rl_camera!!.visibility = View.GONE 317 | } 318 | } 319 | 320 | /** 321 | * 停止拍摄 322 | */ 323 | private fun stopRecorder(play: Boolean) { 324 | 325 | cameraManager!!.isTakePhotoOrVideo = false; 326 | isRecording = false 327 | cameraManager!!.stopMediaRecord() 328 | recordSecond = mProgressbar!!.getProgress() * PLUSH_PROGRESS//录制多少毫秒 329 | mProgressbar!!.reset() 330 | if (recordSecond < MIN_RECORD_TIME) {//小于最小录制时间作废 331 | if (recorderPath != null) { 332 | FileUtils.delteFiles(File(recorderPath)) 333 | recorderPath = null 334 | recordSecond = 0 335 | } 336 | setTakeButtonShow(true) 337 | } else if (play && mTextureView != null && mTextureView!!.isAvailable) { 338 | setTakeButtonShow(false) 339 | mProgressbar!!.setVisibility(View.GONE) 340 | iv_choice!!.visibility = View.VISIBLE 341 | cameraManager!!.closeCamera() 342 | playerManager!!.playMedia(Surface(mTextureView!!.surfaceTexture), recorderPath!!) 343 | } 344 | } 345 | 346 | override fun onResume() { 347 | super.onResume() 348 | if (mTextureView!!.isAvailable) { 349 | if (recorderPath != null) {//优先播放视频 350 | iv_choice!!.visibility = View.VISIBLE 351 | setTakeButtonShow(false) 352 | playerManager!!.playMedia(Surface(mTextureView!!.surfaceTexture), recorderPath!!) 353 | } else { 354 | iv_choice!!.visibility = View.GONE 355 | setTakeButtonShow(true) 356 | cameraManager!!.openCamera( 357 | this, mTextureView!!.surfaceTexture, 358 | mTextureView!!.width, mTextureView!!.height 359 | ) 360 | } 361 | } else { 362 | mTextureView!!.surfaceTextureListener = listener 363 | } 364 | } 365 | 366 | override fun onPause() { 367 | if (progressSubscription != null) { 368 | progressSubscription!!.unsubscribe() 369 | } 370 | if (takePhotoSubscription != null) { 371 | takePhotoSubscription!!.unsubscribe() 372 | } 373 | if (isRecording) { 374 | stopRecorder(false) 375 | } 376 | cameraManager!!.closeCamera() 377 | playerManager!!.stopMedia() 378 | super.onPause() 379 | } 380 | 381 | override fun onDestroy() { 382 | mCameraView!!.removeOnZoomListener() 383 | super.onDestroy() 384 | } 385 | 386 | override fun onClick(v: View) { 387 | when (v.id) { 388 | R.id.iv_close -> { 389 | cameraManager!!.isTakePhotoOrVideo = false; 390 | mTv_tack!!.visibility = View.VISIBLE 391 | 392 | if (recorderPath != null) {//有拍摄好的正在播放,重新拍摄 393 | FileUtils.delteFiles(File(recorderPath)) 394 | recorderPath = null 395 | recordSecond = 0 396 | playerManager!!.stopMedia() 397 | setTakeButtonShow(true) 398 | iv_choice!!.visibility = View.GONE 399 | cameraManager!!.openCamera( 400 | this, 401 | mTextureView!!.surfaceTexture, 402 | mTextureView!!.width, 403 | mTextureView!!.height 404 | ) 405 | } else if (isPhotoTakingState) { 406 | isPhotoTakingState = false 407 | iv_choice!!.visibility = View.GONE 408 | setTakeButtonShow(true) 409 | cameraManager!!.restartPreview() 410 | } else { 411 | finish() 412 | } 413 | } 414 | R.id.iv_choice//选择图片或视频 415 | -> { 416 | //将拍摄的视频路径回传 417 | if (recorderPath != null) { 418 | val intent = Intent() 419 | intent.putExtra("video", recorderPath) 420 | setResult(RequestCode.TAKE_VIDEO, intent) 421 | } 422 | if (photo != null) { 423 | backPicture() 424 | } 425 | finish() 426 | } 427 | R.id.tv_flash -> { 428 | cameraManager!!.changeCameraFlash( 429 | mTextureView!!.surfaceTexture, 430 | mTextureView!!.width, mTextureView!!.height 431 | ) 432 | setCameraFlashState() 433 | } 434 | R.id.iv_facing -> cameraManager!!.changeCameraFacing( 435 | this, mTextureView!!.surfaceTexture, 436 | mTextureView!!.width, mTextureView!!.height 437 | ) 438 | } 439 | } 440 | 441 | private fun backPicture() { 442 | //将图片路径intent回传 443 | val intent = Intent() 444 | intent.putExtra("photo", photo) 445 | setResult(RequestCode.TAKE_PHOTO, intent) 446 | } 447 | 448 | companion object { 449 | /** 450 | * 获取相册 451 | */ 452 | val REQUEST_PHOTO = 1 453 | /** 454 | * 获取视频 455 | */ 456 | val REQUEST_VIDEO = 2 457 | /** 458 | * 最小录制时间 459 | */ 460 | private val MIN_RECORD_TIME = 1 * 1000 461 | /** 462 | * 最长录制时间 463 | */ 464 | private val MAX_RECORD_TIME = 10 * 1000 465 | /** 466 | * 刷新进度的间隔时间 467 | */ 468 | private val PLUSH_PROGRESS = 100 469 | 470 | fun lanuchForPhoto(context: Activity) { 471 | val intent = Intent(context, CameraActivity::class.java) 472 | context.startActivityForResult(intent, REQUEST_PHOTO) 473 | } 474 | } 475 | 476 | } 477 | -------------------------------------------------------------------------------- /android/src/main/kotlin/syscall/zixuan/com/flutter_sys_call/video/takevideo/camera/CameraManager.kt: -------------------------------------------------------------------------------- 1 | package syscall.zixuan.com.flutter_sys_call.video.takevideo.camera 2 | 3 | import android.app.Application 4 | import android.content.Context 5 | import android.graphics.Rect 6 | import android.graphics.RectF 7 | import android.graphics.SurfaceTexture 8 | import android.hardware.Camera 9 | import android.media.CamcorderProfile 10 | import android.media.MediaRecorder 11 | import android.widget.Toast 12 | import syscall.zixuan.com.flutter_sys_call.video.takevideo.utils.LogUtils 13 | 14 | 15 | import java.util.ArrayList 16 | 17 | 18 | /** 19 | * 相机管理类 20 | */ 21 | 22 | class CameraManager private constructor(private val context: Application) { 23 | /** 24 | * camera 25 | */ 26 | private var mCamera: Camera? = null 27 | /** 28 | * 视频录制 29 | */ 30 | private var mMediaRecorder: MediaRecorder? = null 31 | /** 32 | * 相机闪光状态 33 | */ 34 | var cameraFlash: Int = 0 35 | 36 | /** 37 | * 前后置状态 38 | */ 39 | private var cameraFacing = Camera.CameraInfo.CAMERA_FACING_BACK 40 | /** 41 | * 是否支持前置摄像,是否支持闪光 42 | */ 43 | val isSupportFrontCamera: Boolean 44 | 45 | val isSupportFlashCamera: Boolean 46 | 47 | ///是否已经拍摄到相应的照片或视频 48 | var isTakePhotoOrVideo = false; 49 | /** 50 | * 录制视频的相关参数 51 | */ 52 | private var mProfile: CamcorderProfile? = null 53 | /** 54 | * 0为拍照, 1为录像 55 | */ 56 | private var cameraType: Int = 0 57 | 58 | val isCameraFrontFacing: Boolean 59 | get() = cameraFacing == Camera.CameraInfo.CAMERA_FACING_FRONT 60 | 61 | init { 62 | isSupportFrontCamera = CameraUtils.isSupportFrontCamera 63 | isSupportFlashCamera = CameraUtils.isSupportFlashCamera(context) 64 | if (isSupportFrontCamera) { 65 | 66 | cameraFacing = CameraUtils.getCameraFacing(context, Camera.CameraInfo.CAMERA_FACING_BACK) 67 | } 68 | if (isSupportFlashCamera) { 69 | cameraFlash = CameraUtils.getCameraFlash(context) 70 | } 71 | } 72 | 73 | /** 74 | * 打开camera 75 | */ 76 | fun openCamera(context: Context, surfaceTexture: SurfaceTexture, width: Int, height: Int) { 77 | if (mCamera == null) { 78 | try { 79 | mCamera = Camera.open(cameraFacing)//打开当前选中的摄像头 80 | mProfile = CamcorderProfile.get(cameraFacing, CamcorderProfile.QUALITY_HIGH) 81 | mCamera!!.setDisplayOrientation(90)//默认竖直拍照 82 | mCamera!!.setPreviewTexture(surfaceTexture) 83 | initCameraParameters(cameraFacing, width, height) 84 | mCamera!!.startPreview() 85 | } catch (e: Exception) { 86 | if (mCamera != null) { 87 | mCamera!!.release() 88 | mCamera = null 89 | } 90 | } 91 | 92 | } 93 | } 94 | 95 | 96 | /** 97 | * 开启预览,前提是camera初始化了 98 | */ 99 | fun restartPreview() { 100 | if (mCamera == null) return 101 | try { 102 | val parameters = mCamera!!.parameters 103 | val zoom = parameters.zoom 104 | if (zoom > 0) { 105 | parameters.zoom = 0 106 | mCamera!!.parameters = parameters 107 | } 108 | mCamera!!.startPreview() 109 | } catch (e: Exception) { 110 | LogUtils.i(e) 111 | if (mCamera != null) { 112 | mCamera!!.release() 113 | mCamera = null 114 | } 115 | } 116 | 117 | } 118 | 119 | private fun initCameraParameters(cameraId: Int, width: Int, height: Int) { 120 | val parameters = mCamera!!.parameters 121 | if (cameraId == Camera.CameraInfo.CAMERA_FACING_BACK) { 122 | val focusModes = parameters.supportedFocusModes 123 | if (focusModes != null) { 124 | if (cameraType == 0) { 125 | if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) { 126 | parameters.focusMode = Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE 127 | } 128 | } else { 129 | if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) { 130 | parameters.focusMode = Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO 131 | } 132 | } 133 | } 134 | } 135 | parameters.setRotation(90)//设置旋转代码, 136 | when (cameraFlash) { 137 | 0 -> parameters.flashMode = Camera.Parameters.FLASH_MODE_AUTO 138 | 1 -> parameters.flashMode = Camera.Parameters.FLASH_MODE_TORCH 139 | 2 -> parameters.flashMode = Camera.Parameters.FLASH_MODE_OFF 140 | } 141 | val pictureSizes = parameters.supportedPictureSizes 142 | val previewSizes = parameters.supportedPreviewSizes 143 | if (!isEmpty(pictureSizes) && !isEmpty(previewSizes)) { 144 | /*for (Camera.Size size : pictureSizes) { 145 | LogUtils.i("pictureSize " + size.width + " " + size.height); 146 | } 147 | for (Camera.Size size : pictureSizes) { 148 | LogUtils.i("previewSize " + size.width + " " + size.height); 149 | }*/ 150 | val optimalPicSize = getOptimalSize(pictureSizes, width, height) 151 | val optimalPreSize = getOptimalSize(previewSizes, width, height) 152 | LogUtils.i("TextureSize " + width + " " + height + " optimalSize pic " + optimalPicSize!!.width + " " + optimalPicSize.height + " pre " + optimalPreSize!!.width + " " + optimalPreSize.height) 153 | parameters.setPictureSize(optimalPicSize.width, optimalPicSize.height) 154 | parameters.setPreviewSize(optimalPreSize.width, optimalPreSize.height) 155 | mProfile!!.videoFrameWidth = optimalPreSize.width 156 | mProfile!!.videoFrameHeight = optimalPreSize.height 157 | mProfile!!.videoBitRate = 5000000//此参数主要决定视频拍出大小 158 | } 159 | mCamera!!.parameters = parameters 160 | } 161 | 162 | /** 163 | * 释放摄像头 164 | */ 165 | fun closeCamera() { 166 | this.cameraType = 0 167 | if (mCamera != null) { 168 | try { 169 | mCamera!!.stopPreview() 170 | mCamera!!.release() 171 | mCamera = null 172 | } catch (e: Exception) { 173 | LogUtils.i(e) 174 | if (mCamera != null) { 175 | mCamera!!.release() 176 | mCamera = null 177 | } 178 | } 179 | 180 | } 181 | } 182 | 183 | /** 184 | * 集合不为空 185 | * 186 | * @param list 187 | * @param 188 | * @return 189 | */ 190 | private fun isEmpty(list: List?): Boolean { 191 | return list == null || list.isEmpty() 192 | } 193 | 194 | /** 195 | * 获取最佳预览相机Size参数 196 | * 197 | * @return 198 | */ 199 | private fun getOptimalSize(sizes: List, w: Int, h: Int): Camera.Size? { 200 | var optimalSize: Camera.Size? = null 201 | val targetRadio = h / w.toFloat() 202 | var optimalDif = java.lang.Float.MAX_VALUE //最匹配的比例 203 | var optimalMaxDif = Integer.MAX_VALUE//最优的最大值差距 204 | for (size in sizes) { 205 | val newOptimal = size.width / size.height.toFloat() 206 | val newDiff = Math.abs(newOptimal - targetRadio) 207 | if (newDiff < optimalDif) { //更好的尺寸 208 | optimalDif = newDiff 209 | optimalSize = size 210 | optimalMaxDif = Math.abs(h - size.width) 211 | } else if (newDiff == optimalDif) {//更好的尺寸 212 | val newOptimalMaxDif = Math.abs(h - size.width) 213 | if (newOptimalMaxDif < optimalMaxDif) { 214 | optimalDif = newDiff 215 | optimalSize = size 216 | optimalMaxDif = newOptimalMaxDif 217 | } 218 | } 219 | } 220 | return optimalSize 221 | } 222 | 223 | /** 224 | * 缩放 225 | * 226 | * @param isZoomIn 227 | */ 228 | fun handleZoom(isZoomIn: Boolean) { 229 | if (mCamera == null) return 230 | val params = mCamera!!.parameters ?: return 231 | if (params.isZoomSupported) { 232 | val maxZoom = params.maxZoom 233 | var zoom = params.zoom 234 | if (isZoomIn && zoom < maxZoom) { 235 | zoom++ 236 | } else if (zoom > 0) { 237 | zoom-- 238 | } 239 | params.zoom = zoom 240 | mCamera!!.parameters = params 241 | } else { 242 | LogUtils.i("zoom not supported") 243 | } 244 | } 245 | 246 | /** 247 | * 更换前后置摄像 248 | */ 249 | fun changeCameraFacing(context: Context, surfaceTexture: SurfaceTexture, width: Int, height: Int) { 250 | if (isSupportFrontCamera) { 251 | val cameraInfo = Camera.CameraInfo() 252 | val cameraCount = Camera.getNumberOfCameras()//得到摄像头的个数 253 | for (i in 0 until cameraCount) { 254 | Camera.getCameraInfo(i, cameraInfo)//得到每一个摄像头的信息 255 | if (cameraFacing == Camera.CameraInfo.CAMERA_FACING_FRONT) { //现在是后置,变更为前置 256 | if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {//代表摄像头的方位为前置 257 | closeCamera() 258 | cameraFacing = Camera.CameraInfo.CAMERA_FACING_BACK 259 | CameraUtils.setCameraFacing(context, cameraFacing) 260 | openCamera(context, surfaceTexture, width, height) 261 | break 262 | } 263 | } else {//现在是前置, 变更为后置 264 | if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {//代表摄像头的方位 265 | closeCamera() 266 | cameraFacing = Camera.CameraInfo.CAMERA_FACING_FRONT 267 | CameraUtils.setCameraFacing(context, cameraFacing) 268 | openCamera(context, surfaceTexture, width, height) 269 | break 270 | } 271 | } 272 | } 273 | } else { //不支持摄像机 274 | Toast.makeText(context, "您的手机不支持前置摄像", Toast.LENGTH_SHORT).show() 275 | } 276 | } 277 | 278 | /** 279 | * 改变闪光状态 280 | */ 281 | fun changeCameraFlash(surfaceTexture: SurfaceTexture, width: Int, height: Int) { 282 | if (!isSupportFlashCamera) { 283 | Toast.makeText(context, "您的手机不支闪光", Toast.LENGTH_SHORT).show() 284 | return 285 | } 286 | if (mCamera != null) { 287 | val parameters = mCamera!!.parameters 288 | if (parameters != null) { 289 | var newState = cameraFlash 290 | when (cameraFlash) { 291 | 0 //自动 292 | -> { 293 | parameters.flashMode = Camera.Parameters.FLASH_MODE_TORCH 294 | newState = 1 295 | } 296 | 1//open 297 | -> { 298 | parameters.flashMode = Camera.Parameters.FLASH_MODE_OFF 299 | newState = 2 300 | } 301 | 2 //close 302 | -> { 303 | parameters.flashMode = Camera.Parameters.FLASH_MODE_AUTO 304 | newState = 0 305 | } 306 | } 307 | cameraFlash = newState 308 | CameraUtils.setCameraFlash(context, newState) 309 | mCamera!!.parameters = parameters 310 | } 311 | } 312 | } 313 | 314 | /** 315 | * 拍照 316 | */ 317 | fun takePhoto(callback: Camera.PictureCallback) { 318 | if (mCamera != null) { 319 | try { 320 | isTakePhotoOrVideo = true; 321 | mCamera!!.takePicture(null, null, callback) 322 | 323 | } catch (e: Exception) { 324 | Toast.makeText(context, "拍摄失败", Toast.LENGTH_SHORT).show() 325 | } 326 | 327 | } 328 | } 329 | 330 | 331 | /** 332 | * 开始录制视频 333 | */ 334 | fun startMediaRecord(savePath: String) { 335 | 336 | if (mCamera == null || mProfile == null) return 337 | mCamera!!.unlock() 338 | if (mMediaRecorder == null) { 339 | mMediaRecorder = MediaRecorder() 340 | mMediaRecorder!!.setOrientationHint(90) 341 | } 342 | if (isCameraFrontFacing) { 343 | mMediaRecorder!!.setOrientationHint(270) 344 | } 345 | mMediaRecorder!!.reset() 346 | mMediaRecorder!!.setCamera(mCamera) 347 | mMediaRecorder!!.setVideoSource(MediaRecorder.VideoSource.CAMERA) 348 | mMediaRecorder!!.setAudioSource(MediaRecorder.AudioSource.DEFAULT) 349 | mMediaRecorder!!.setProfile(mProfile) 350 | mMediaRecorder!!.setOutputFile(savePath) 351 | try { 352 | mMediaRecorder!!.prepare() 353 | mMediaRecorder!!.start() 354 | } catch (e: Exception) { 355 | e.printStackTrace() 356 | 357 | } 358 | 359 | } 360 | 361 | /** 362 | * 停止录制 363 | */ 364 | fun stopMediaRecord() { 365 | this.cameraType = 0 366 | stopRecorder() 367 | releaseMediaRecorder() 368 | } 369 | 370 | private fun releaseMediaRecorder() { 371 | if (mMediaRecorder != null) { 372 | try { 373 | mMediaRecorder!!.reset() 374 | mMediaRecorder!!.release() 375 | mMediaRecorder = null 376 | mCamera!!.lock() 377 | } catch (e: Exception) { 378 | e.printStackTrace() 379 | LogUtils.i(e) 380 | } 381 | 382 | } 383 | } 384 | 385 | private fun stopRecorder() { 386 | isTakePhotoOrVideo=true; 387 | if (mMediaRecorder != null) { 388 | try { 389 | mMediaRecorder!!.stop() 390 | } catch (e: Exception) { 391 | e.printStackTrace() 392 | LogUtils.i(e) 393 | } 394 | 395 | } 396 | } 397 | 398 | /** 399 | * 设置对焦类型 400 | * 401 | * @param cameraType 402 | */ 403 | fun setCameraType(cameraType: Int) { 404 | this.cameraType = cameraType 405 | if (mCamera != null) {//拍摄视频时 406 | if (cameraFacing == Camera.CameraInfo.CAMERA_FACING_BACK) { 407 | val parameters = mCamera!!.parameters 408 | val focusModes = parameters.supportedFocusModes 409 | if (focusModes != null) { 410 | if (cameraType == 0) { 411 | if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) { 412 | parameters.focusMode = Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE 413 | } 414 | } else { 415 | if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) { 416 | parameters.focusMode = Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO 417 | } 418 | } 419 | } 420 | } 421 | } 422 | } 423 | 424 | /** 425 | * 对焦 426 | * 427 | * @param x 428 | * @param y 429 | */ 430 | fun handleFocusMetering(x: Float, y: Float) { 431 | 432 | 433 | val params = mCamera!!.parameters 434 | val previewSize = params.previewSize 435 | val focusRect = calculateTapArea(x, y, 1f, previewSize) 436 | val meteringRect = calculateTapArea(x, y, 1.5f, previewSize) 437 | mCamera!!.cancelAutoFocus() 438 | 439 | if (params.maxNumFocusAreas > 0) { 440 | val focusAreas = ArrayList() 441 | focusAreas.add(Camera.Area(focusRect, 1000)) 442 | params.focusAreas = focusAreas 443 | } else { 444 | LogUtils.i("focus areas not supported") 445 | } 446 | if (params.maxNumMeteringAreas > 0) { 447 | val meteringAreas = ArrayList() 448 | meteringAreas.add(Camera.Area(meteringRect, 1000)) 449 | params.meteringAreas = meteringAreas 450 | } else { 451 | LogUtils.i("metering areas not supported") 452 | } 453 | val currentFocusMode = params.focusMode 454 | params.focusMode = Camera.Parameters.FOCUS_MODE_AUTO 455 | mCamera!!.parameters = params 456 | 457 | mCamera!!.autoFocus { success, camera -> 458 | val params = camera.parameters 459 | params.focusMode = currentFocusMode 460 | camera.parameters = params 461 | } 462 | } 463 | 464 | private fun calculateTapArea(x: Float, y: Float, coefficient: Float, previewSize: Camera.Size): Rect { 465 | val focusAreaSize = 300f 466 | val areaSize = java.lang.Float.valueOf(focusAreaSize * coefficient).toInt() 467 | val centerX = (x / previewSize.width - 1000).toInt() 468 | val centerY = (y / previewSize.height - 1000).toInt() 469 | val left = clamp(centerX - areaSize / 2, -1000, 1000) 470 | val top = clamp(centerY - areaSize / 2, -1000, 1000) 471 | val rectF = RectF(left.toFloat(), top.toFloat(), (left + areaSize).toFloat(), (top + areaSize).toFloat()) 472 | return Rect(Math.round(rectF.left), Math.round(rectF.top), Math.round(rectF.right), Math.round(rectF.bottom)) 473 | } 474 | 475 | private fun clamp(x: Int, min: Int, max: Int): Int { 476 | if (x > max) { 477 | return max 478 | } 479 | return if (x < min) { 480 | min 481 | } else x 482 | } 483 | 484 | companion object { 485 | 486 | private var INSTANCE: CameraManager? = null 487 | 488 | fun getInstance(context: Application): CameraManager { 489 | if (INSTANCE == null) { 490 | synchronized(CameraManager::class.java) { 491 | if (INSTANCE == null) { 492 | INSTANCE = CameraManager(context) 493 | } 494 | } 495 | } 496 | return INSTANCE!! 497 | } 498 | } 499 | 500 | } 501 | -------------------------------------------------------------------------------- /android/src/main/kotlin/syscall/zixuan/com/flutter_sys_call/video/takevideo/camera/CameraProgressBar.kt: -------------------------------------------------------------------------------- 1 | package syscall.zixuan.com.flutter_sys_call.video.takevideo.camera 2 | 3 | import android.content.Context 4 | import android.content.res.TypedArray 5 | import android.graphics.Canvas 6 | import android.graphics.Color 7 | import android.graphics.Paint 8 | import android.graphics.RectF 9 | import android.os.Bundle 10 | import android.os.Parcelable 11 | 12 | import android.util.AttributeSet 13 | import android.view.GestureDetector 14 | import android.view.MotionEvent 15 | import android.view.View 16 | import android.view.ViewConfiguration 17 | import androidx.core.view.GestureDetectorCompat 18 | import androidx.core.view.MotionEventCompat 19 | import syscall.zixuan.com.flutter_sys_call.R 20 | 21 | 22 | class CameraProgressBar : View { 23 | /** 24 | * 默认缩小值 25 | */ 26 | private var scale = DEF_SCALE 27 | 28 | /** 29 | * 内圆颜色 30 | */ 31 | private var innerColor = Color.BLACK 32 | /** 33 | * 背景颜色 34 | */ 35 | private val backgroundColor = Color.WHITE 36 | /** 37 | * 外圆颜色 38 | */ 39 | private var outerColor = Color.parseColor("#e8e8e8") 40 | /** 41 | * 进度颜色 42 | */ 43 | private var progressColor = Color.parseColor("#2DD0CF") 44 | /** 45 | * 进度宽 46 | */ 47 | private var progressWidth = 10 48 | /** 49 | * 内圆宽度 50 | */ 51 | private var innerRadio = 10 52 | /** 53 | * 进度 54 | */ 55 | private var progress: Int = 0 56 | /** 57 | * 最大进度 58 | */ 59 | private var maxProgress = 100 60 | /** 61 | * paint 62 | */ 63 | private var backgroundPaint: Paint? = null 64 | private var progressPaint: Paint? = null 65 | private var innerPaint: Paint? = null 66 | /** 67 | * 圆的中心坐标点, 进度百分比 68 | */ 69 | private var sweepAngle: Float = 0.toFloat() 70 | /** 71 | * 手识识别 72 | */ 73 | private var mDetector: GestureDetectorCompat? = null 74 | /** 75 | * 是否为长按录制 76 | */ 77 | private var isLongClick: Boolean = false 78 | /** 79 | * 是否产生滑动 80 | */ 81 | private var isBeingDrag: Boolean = false 82 | /** 83 | * 滑动单位 84 | */ 85 | private var mTouchSlop: Int = 0 86 | /** 87 | * 记录上一次Y轴坐标点 88 | */ 89 | private var mLastY: Float = 0.toFloat() 90 | /** 91 | * 是否长按放大 92 | */ 93 | private var isLongScale: Boolean = false 94 | 95 | private var listener: OnProgressTouchListener? = null 96 | 97 | 98 | constructor(context: Context) : super(context) { 99 | init(context, null) 100 | } 101 | 102 | constructor(context: Context, attrs: AttributeSet) : super(context, attrs) { 103 | init(context, attrs) 104 | } 105 | 106 | constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { 107 | init(context, attrs) 108 | } 109 | 110 | private fun init(context: Context, attrs: AttributeSet?) { 111 | mTouchSlop = ViewConfiguration.get(context).scaledTouchSlop 112 | if (attrs != null) { 113 | val a = context.obtainStyledAttributes(attrs, R.styleable.CameraProgressBar) 114 | innerColor = a.getColor(R.styleable.CameraProgressBar_innerColor, innerColor) 115 | outerColor = a.getColor(R.styleable.CameraProgressBar_outerColor, outerColor) 116 | progressColor = a.getColor(R.styleable.CameraProgressBar_progressColor, progressColor) 117 | innerRadio = a.getDimensionPixelOffset(R.styleable.CameraProgressBar_innerRadio, innerRadio) 118 | progressWidth = a.getDimensionPixelOffset(R.styleable.CameraProgressBar_progressWidth, progressWidth) 119 | progress = a.getInt(R.styleable.CameraProgressBar_progres, progress) 120 | scale = a.getFloat(R.styleable.CameraProgressBar_scale, scale) 121 | isLongScale = a.getBoolean(R.styleable.CameraProgressBar_isLongScale, isLongScale) 122 | maxProgress = a.getInt(R.styleable.CameraProgressBar_maxProgress, maxProgress) 123 | a.recycle() 124 | } 125 | backgroundPaint = Paint() 126 | backgroundPaint!!.isAntiAlias = true 127 | backgroundPaint!!.color = backgroundColor 128 | 129 | progressPaint = Paint() 130 | progressPaint!!.isAntiAlias = true 131 | progressPaint!!.strokeWidth = progressWidth.toFloat() 132 | progressPaint!!.style = Paint.Style.STROKE 133 | 134 | innerPaint = Paint() 135 | innerPaint!!.isAntiAlias = true 136 | innerPaint!!.strokeWidth = innerRadio.toFloat() 137 | innerPaint!!.style = Paint.Style.STROKE 138 | 139 | sweepAngle = progress.toFloat() / maxProgress * 360 140 | 141 | mDetector = GestureDetectorCompat(context, object : GestureDetector.SimpleOnGestureListener() { 142 | override fun onSingleTapConfirmed(e: MotionEvent): Boolean { 143 | isLongClick = false 144 | if (this@CameraProgressBar.listener != null) { 145 | this@CameraProgressBar.listener!!.onClick(this@CameraProgressBar) 146 | } 147 | return super.onSingleTapConfirmed(e) 148 | } 149 | 150 | override fun onLongPress(e: MotionEvent) { 151 | isLongClick = true 152 | postInvalidate() 153 | mLastY = e.y 154 | if (this@CameraProgressBar.listener != null) { 155 | this@CameraProgressBar.listener!!.onLongClick(this@CameraProgressBar) 156 | } 157 | } 158 | }) 159 | mDetector!!.setIsLongpressEnabled(true) 160 | } 161 | 162 | override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { 163 | super.onMeasure(widthMeasureSpec, heightMeasureSpec) 164 | val width = View.MeasureSpec.getSize(widthMeasureSpec) 165 | val height = View.MeasureSpec.getSize(heightMeasureSpec) 166 | if (width > height) { 167 | setMeasuredDimension(height, height) 168 | } else { 169 | setMeasuredDimension(width, width) 170 | } 171 | } 172 | 173 | override fun onDraw(canvas: Canvas) { 174 | super.onDraw(canvas) 175 | val width = width 176 | val circle = width / 2.0f 177 | 178 | if (/*isLongScale && */!isLongClick) { 179 | canvas.scale(scale, scale, circle, circle) 180 | } 181 | 182 | 183 | //画内圆 184 | val backgroundRadio = circle - progressWidth.toFloat() - innerRadio.toFloat() 185 | canvas.drawCircle(circle, circle, backgroundRadio, backgroundPaint!!) 186 | 187 | //画内外环 188 | val halfInnerWidth = innerRadio / 2.0f + progressWidth 189 | val innerRectF = RectF(halfInnerWidth, halfInnerWidth, width - halfInnerWidth, width - halfInnerWidth) 190 | canvas.drawArc(innerRectF, -90f, 360f, true, innerPaint!!) 191 | 192 | progressPaint!!.color = outerColor 193 | val halfOuterWidth = progressWidth / 2.0f 194 | val outerRectF = RectF(halfOuterWidth, halfOuterWidth, getWidth() - halfOuterWidth, getWidth() - halfOuterWidth) 195 | canvas.drawArc(outerRectF, -90f, 360f, true, progressPaint!!) 196 | 197 | progressPaint!!.color = progressColor 198 | canvas.drawArc(outerRectF, -90f, sweepAngle, false, progressPaint!!) 199 | } 200 | 201 | override fun onTouchEvent(event: MotionEvent): Boolean { 202 | if (!isLongScale) { 203 | return super.onTouchEvent(event) 204 | } 205 | this.mDetector!!.onTouchEvent(event) 206 | when (MotionEventCompat.getActionMasked(event)) { 207 | MotionEvent.ACTION_DOWN -> { 208 | isLongClick = false 209 | isBeingDrag = false 210 | } 211 | MotionEvent.ACTION_MOVE -> if (isLongClick) { 212 | val y = event.y 213 | if (isBeingDrag) { 214 | val isUpScroll = y < mLastY 215 | mLastY = y 216 | if (this.listener != null) { 217 | this.listener!!.onZoom(isUpScroll) 218 | } 219 | } else { 220 | isBeingDrag = Math.abs(y - mLastY) > mTouchSlop 221 | } 222 | } 223 | MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> { 224 | isBeingDrag = false 225 | if (isLongClick) { 226 | isLongClick = false 227 | postInvalidate() 228 | if (this.listener != null) { 229 | this.listener!!.onLongClickUp(this) 230 | } 231 | } 232 | } 233 | MotionEvent.ACTION_POINTER_DOWN -> if (isLongClick) { 234 | if (this.listener != null) { 235 | this.listener!!.onPointerDown(event.rawX, event.rawY) 236 | } 237 | } 238 | } 239 | return true 240 | } 241 | 242 | override fun onSaveInstanceState(): Parcelable? { 243 | val bundle = Bundle() 244 | val superData = super.onSaveInstanceState() 245 | bundle.putParcelable("superData", superData) 246 | bundle.putInt("progress", progress) 247 | bundle.putInt("maxProgress", maxProgress) 248 | return bundle 249 | } 250 | 251 | override fun onRestoreInstanceState(state: Parcelable) { 252 | val bundle = state as Bundle 253 | val superData = bundle.getParcelable("superData") 254 | progress = bundle.getInt("progress") 255 | maxProgress = bundle.getInt("maxProgress") 256 | super.onRestoreInstanceState(superData) 257 | } 258 | 259 | /** 260 | * 设置进度 261 | * @param progress 262 | */ 263 | fun setProgress(progress: Int) { 264 | var progress = progress 265 | if (progress <= 0) progress = 0 266 | if (progress >= maxProgress) progress = maxProgress 267 | if (progress == this.progress) return 268 | this.progress = progress 269 | this.sweepAngle = progress.toFloat() / maxProgress * 360 270 | postInvalidate() 271 | } 272 | 273 | /** 274 | * 还原到初始状态 275 | */ 276 | fun reset() { 277 | isLongClick = false 278 | this.progress = 0 279 | this.sweepAngle = 0f 280 | postInvalidate() 281 | } 282 | 283 | fun getProgress(): Int { 284 | return progress 285 | } 286 | 287 | fun setLongScale(longScale: Boolean) { 288 | isLongScale = longScale 289 | } 290 | 291 | fun setMaxProgress(maxProgress: Int) { 292 | this.maxProgress = maxProgress 293 | } 294 | 295 | fun setOnProgressTouchListener(listener: OnProgressTouchListener) { 296 | this.listener = listener 297 | } 298 | 299 | /** 300 | * 进度触摸监听 301 | */ 302 | interface OnProgressTouchListener { 303 | /** 304 | * 单击 305 | * @param progressBar 306 | */ 307 | fun onClick(progressBar: CameraProgressBar) 308 | 309 | /** 310 | * 长按 311 | * @param progressBar 312 | */ 313 | fun onLongClick(progressBar: CameraProgressBar) 314 | 315 | /** 316 | * 移动 317 | * @param zoom true放大 318 | */ 319 | fun onZoom(zoom: Boolean) 320 | 321 | /** 322 | * 长按抬起 323 | * @param progressBar 324 | */ 325 | fun onLongClickUp(progressBar: CameraProgressBar) 326 | 327 | /** 328 | * 触摸对焦 329 | * @param rawX 330 | * @param rawY 331 | */ 332 | 333 | fun onPointerDown(rawX: Float, rawY: Float) 334 | } 335 | 336 | companion object { 337 | /** 338 | * 默认缩小值 339 | */ 340 | val DEF_SCALE = 0.75f 341 | } 342 | 343 | } 344 | -------------------------------------------------------------------------------- /android/src/main/kotlin/syscall/zixuan/com/flutter_sys_call/video/takevideo/camera/CameraUtils.kt: -------------------------------------------------------------------------------- 1 | package syscall.zixuan.com.flutter_sys_call.video.takevideo.camera 2 | 3 | import android.content.Context 4 | import android.content.pm.FeatureInfo 5 | import android.content.pm.PackageManager 6 | import android.hardware.Camera 7 | import syscall.zixuan.com.flutter_sys_call.video.takevideo.utils.SPUtils 8 | 9 | 10 | internal object CameraUtils { 11 | /** 12 | * 摄像机闪光灯状态 13 | */ 14 | val CAMERA_FLASH = "camera_flash" 15 | /** 16 | * 摄像机前后置状态 17 | */ 18 | val CAMERA_AROUND = "camera_around" 19 | 20 | /** 21 | * 摄像机是否支持前置拍照 22 | * @return 23 | */ 24 | val isSupportFrontCamera: Boolean 25 | get() { 26 | val cameraCount = Camera.getNumberOfCameras() 27 | val info = Camera.CameraInfo() 28 | for (i in 0 until cameraCount) { 29 | Camera.getCameraInfo(i, info) 30 | if (info.facing == 1) { 31 | return true 32 | } 33 | } 34 | return false 35 | } 36 | 37 | /** 38 | * 获取相机闪光灯状态 39 | * @return 0为自动,1为打开,其他为关闭 40 | */ 41 | fun getCameraFlash(context: Context): Int { 42 | return SPUtils.get(context, CAMERA_FLASH, 0) as Int 43 | } 44 | 45 | /** 46 | * 设置相机闪光状态 47 | * @param flash 48 | */ 49 | fun setCameraFlash(context: Context, flash: Int) { 50 | SPUtils.put(context, CAMERA_FLASH, flash) 51 | } 52 | 53 | /** 54 | * 获取摄像头是否为前置或后 55 | * 56 | * @param context 57 | * @return 0为后置,1为前置 58 | */ 59 | fun getCameraFacing(context: Context, defaultId: Int): Int { 60 | return SPUtils.get(context, CAMERA_AROUND, defaultId) as Int 61 | } 62 | 63 | /** 64 | * 设置摄像头前置或后 65 | * 66 | * @param context 67 | * @param around 68 | */ 69 | fun setCameraFacing(context: Context, around: Int) { 70 | SPUtils.put(context, CAMERA_AROUND, around) 71 | } 72 | 73 | /** 74 | * 是否支持闪光 75 | * @param context 76 | * @return 77 | */ 78 | fun isSupportFlashCamera(context: Context): Boolean { 79 | val features = context.packageManager.systemAvailableFeatures 80 | for (info in features) { 81 | if (PackageManager.FEATURE_CAMERA_FLASH == info.name) 82 | return true 83 | } 84 | return false 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /android/src/main/kotlin/syscall/zixuan/com/flutter_sys_call/video/takevideo/camera/CameraView.kt: -------------------------------------------------------------------------------- 1 | package syscall.zixuan.com.flutter_sys_call.video.takevideo.camera 2 | import android.content.Context 3 | import android.graphics.* 4 | import android.util.AttributeSet 5 | import android.view.MotionEvent 6 | import android.view.View 7 | import android.view.ViewParent 8 | import androidx.core.view.MotionEventCompat 9 | import rx.Observable 10 | import rx.Subscriber 11 | import rx.Subscription 12 | 13 | 14 | import java.util.concurrent.TimeUnit 15 | 16 | 17 | class CameraView : View { 18 | /** 19 | * focus paint 20 | */ 21 | private var paint: Paint? = null 22 | private var clearPaint: Paint? = null 23 | 24 | private val paintColor = Color.GREEN 25 | /** 26 | * 进度订阅 27 | */ 28 | private var subscription: Subscription? = null 29 | /** 30 | * focus rectf 31 | */ 32 | private val rectF = RectF() 33 | /** 34 | * focus size 35 | */ 36 | private val focusSize = 120 37 | 38 | private val lineSize = focusSize / 4 39 | /** 40 | * 上一次两指距离 41 | */ 42 | private var oldDist = 1f 43 | /** 44 | * 画笔宽 45 | */ 46 | private val paintWidth = 6.0f 47 | /** 48 | * s 49 | */ 50 | private var scale: Float = 0.toFloat() 51 | 52 | private var listener: OnViewTouchListener? = null 53 | 54 | constructor(context: Context) : super(context) { 55 | init() 56 | } 57 | 58 | constructor(context: Context, attrs: AttributeSet) : super(context, attrs) { 59 | init() 60 | } 61 | 62 | constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { 63 | init() 64 | } 65 | 66 | private fun init() { 67 | paint = Paint() 68 | paint!!.color = paintColor 69 | paint!!.style = Paint.Style.STROKE 70 | paint!!.strokeWidth = paintWidth 71 | 72 | clearPaint = Paint() 73 | clearPaint!!.xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR) 74 | } 75 | 76 | override fun onTouchEvent(event: MotionEvent): Boolean { 77 | val action = MotionEventCompat.getActionMasked(event) 78 | if (event.pointerCount == 1 && action == MotionEvent.ACTION_DOWN) { 79 | val x = event.x 80 | val y = event.y 81 | setFoucsPoint(x, y) 82 | if (listener != null) { 83 | listener!!.handleFocus(x, y) 84 | } 85 | } else if (event.pointerCount >= 2) { 86 | when (event.action and MotionEvent.ACTION_MASK) { 87 | MotionEvent.ACTION_POINTER_DOWN -> oldDist = getFingerSpacing(event) 88 | MotionEvent.ACTION_MOVE -> { 89 | val newDist = getFingerSpacing(event) 90 | if (newDist > oldDist) { 91 | if (this.listener != null) { 92 | this.listener!!.handleZoom(true) 93 | } 94 | } else if (newDist < oldDist) { 95 | if (this.listener != null) { 96 | this.listener!!.handleZoom(false) 97 | } 98 | } 99 | oldDist = newDist 100 | } 101 | } 102 | } 103 | return true 104 | } 105 | 106 | /** 107 | * 计算两点触控距离 108 | * @param event 109 | * @return 110 | */ 111 | private fun getFingerSpacing(event: MotionEvent): Float { 112 | val x = event.getX(0) - event.getX(1) 113 | val y = event.getY(0) - event.getY(1) 114 | return Math.sqrt((x * x + y * y).toDouble()).toFloat() 115 | } 116 | 117 | /** 118 | * 设置坐标点(坐标为rawX, rawY) 119 | */ 120 | fun setFoucsPoint(pointF: PointF) { 121 | val transPointF = transPointF(pointF, this) 122 | setFoucsPoint(transPointF.x, transPointF.y) 123 | } 124 | 125 | /** 126 | * 设置当前触摸点 127 | * @param x 128 | * @param y 129 | */ 130 | private fun setFoucsPoint(x: Float, y: Float) { 131 | if (subscription != null) { 132 | subscription!!.unsubscribe() 133 | } 134 | rectF.set(x - focusSize, y - focusSize, x + focusSize, y + focusSize) 135 | val count = ANIM_MILS / ANIM_UPDATE 136 | subscription = Observable.interval(ANIM_UPDATE.toLong(), TimeUnit.MILLISECONDS).take(count) 137 | .subscribe(object : Subscriber() { 138 | override fun onCompleted() { 139 | scale = 0f 140 | postInvalidate() 141 | } 142 | 143 | override fun onError(e: Throwable) { 144 | scale = 0f 145 | postInvalidate() 146 | } 147 | 148 | override fun onNext(aLong: Long?) { 149 | val current = (aLong ?: 0).toFloat() 150 | scale = 1 - current / count 151 | if (scale <= 0.5f) { 152 | scale = 0.5f 153 | } 154 | postInvalidate() 155 | } 156 | }) 157 | } 158 | 159 | override fun onDraw(canvas: Canvas) { 160 | super.onDraw(canvas) 161 | if (scale != 0f) { 162 | val centerX = rectF.centerX() 163 | val centerY = rectF.centerY() 164 | canvas.scale(scale, scale, centerX, centerY) 165 | canvas.drawRect(rectF, paint!!) 166 | canvas.drawLine(rectF.left, centerY, rectF.left + lineSize, centerY, paint!!) 167 | canvas.drawLine(rectF.right, centerY, rectF.right - lineSize, centerY, paint!!) 168 | canvas.drawLine(centerX, rectF.top, centerX, rectF.top + lineSize, paint!!) 169 | canvas.drawLine(centerX, rectF.bottom, centerX, rectF.bottom - lineSize, paint!!) 170 | } 171 | } 172 | 173 | override fun onDetachedFromWindow() { 174 | super.onDetachedFromWindow() 175 | if (subscription != null) { 176 | subscription!!.unsubscribe() 177 | } 178 | } 179 | 180 | /** 181 | * 根据raw坐标转换成屏幕中所在的坐标 182 | * @param pointF 183 | * @return 184 | */ 185 | private fun transPointF(pointF: PointF, view: View): PointF { 186 | pointF.x -= view.x 187 | pointF.y -= view.y 188 | val parent = view.parent 189 | return if (parent is View) { 190 | transPointF(pointF, parent as View) 191 | } else { 192 | pointF 193 | } 194 | } 195 | 196 | fun setOnViewTouchListener(listener: OnViewTouchListener) { 197 | this.listener = listener 198 | } 199 | 200 | fun removeOnZoomListener() { 201 | this.listener = null 202 | } 203 | 204 | interface OnViewTouchListener { 205 | /** 206 | * 对焦 207 | * @param x 208 | * @param y 209 | */ 210 | fun handleFocus(x: Float, y: Float) 211 | 212 | /** 213 | * 缩放 214 | * @param zoom true放大反之 215 | */ 216 | fun handleZoom(zoom: Boolean) 217 | 218 | } 219 | 220 | companion object { 221 | /** 222 | * 动画时长 223 | */ 224 | private val ANIM_MILS = 600 225 | /** 226 | * 动画每多久刷新一次 227 | */ 228 | private val ANIM_UPDATE = 30 229 | } 230 | 231 | } 232 | -------------------------------------------------------------------------------- /android/src/main/kotlin/syscall/zixuan/com/flutter_sys_call/video/takevideo/camera/MediaPlayerManager.kt: -------------------------------------------------------------------------------- 1 | package syscall.zixuan.com.flutter_sys_call.video.takevideo.camera 2 | import android.app.Application 3 | import android.media.MediaPlayer 4 | import android.view.Surface 5 | import syscall.zixuan.com.flutter_sys_call.video.takevideo.utils.LogUtils 6 | 7 | 8 | /** 9 | * 由于拍摄跟播放都关联TextureView,停止播放时要释放mediaplayer 10 | */ 11 | 12 | class MediaPlayerManager private constructor(private val app: Application) { 13 | 14 | private var mPlayer: MediaPlayer? = null 15 | 16 | /** 17 | * 播放Media 18 | */ 19 | fun playMedia(surface: Surface, mediaPath: String) { 20 | try { 21 | if (mPlayer == null) { 22 | mPlayer = MediaPlayer() 23 | mPlayer!!.setDataSource(mediaPath) 24 | } else { 25 | if (mPlayer!!.isPlaying) { 26 | mPlayer!!.stop() 27 | } 28 | mPlayer!!.reset() 29 | mPlayer!!.setDataSource(mediaPath) 30 | } 31 | mPlayer!!.setSurface(surface) 32 | mPlayer!!.isLooping = true 33 | mPlayer!!.prepareAsync() 34 | mPlayer!!.setOnPreparedListener { mp -> mp.start() } 35 | } catch (e: Exception) { 36 | LogUtils.i(e) 37 | } 38 | 39 | } 40 | 41 | /** 42 | * 停止播放Media 43 | */ 44 | fun stopMedia() { 45 | try { 46 | if (mPlayer != null) { 47 | if (mPlayer!!.isPlaying) { 48 | mPlayer!!.stop() 49 | } 50 | mPlayer!!.release() 51 | mPlayer = null 52 | } 53 | } catch (e: Exception) { 54 | LogUtils.i(e) 55 | } 56 | 57 | } 58 | 59 | companion object { 60 | 61 | private var INSTANCE: MediaPlayerManager? = null 62 | 63 | fun getInstance(app: Application): MediaPlayerManager { 64 | if (INSTANCE == null) { 65 | synchronized(CameraManager::class.java) { 66 | if (INSTANCE == null) { 67 | INSTANCE = MediaPlayerManager(app) 68 | } 69 | } 70 | } 71 | return INSTANCE!! 72 | } 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /android/src/main/kotlin/syscall/zixuan/com/flutter_sys_call/video/takevideo/camera/ViewClickOnSubscribe.kt: -------------------------------------------------------------------------------- 1 | package syscall.zixuan.com.flutter_sys_call.video.takevideo.camera 2 | 3 | import android.view.View 4 | import rx.Observable 5 | import rx.Subscriber 6 | import rx.android.MainThreadSubscription 7 | 8 | import java.util.ArrayList 9 | 10 | 11 | /** 12 | * 防抖点击事件绑定 可以参照rxbinding 13 | * 14 | * 15 | * ViewClickOnSubscribe click = new ViewClickOnSubscribe(); 16 | * click.addOnClickListener(tv_test); 17 | * click.addOnClickListener(tv_test1); 18 | * click.addOnClickListener(tv_test2); 19 | * 20 | * subscription = Observable.create(click).throttleFirst(500 , TimeUnit.MILLISECONDS ).subscribe(new Action1() { 21 | * @Override 22 | * public void call(View view) { 23 | * switch (view.getId()) { 24 | * case R.id.tv_test: 25 | * Log.i("you", "test"); 26 | * break; 27 | * case R.id.tv_test1: 28 | * Log.i("you", "test1"); 29 | * break; 30 | * } 31 | * } 32 | * }); 33 | * 34 | * Subscription subscription; 35 | * 36 | * @Override 37 | * protected void onDestroy() { 38 | * super.onDestroy(); 39 | * subscription.unsubscribe(); 40 | * } 41 | */ 42 | 43 | class ViewClickOnSubscribe : Observable.OnSubscribe { 44 | 45 | /** 46 | * 注册防抖点击的控件 47 | */ 48 | private val clickViews = ArrayList() 49 | 50 | /** 51 | * 添加控件点击事件 52 | * @param v 53 | */ 54 | fun addOnClickListener(v: View) { 55 | clickViews.add(v) 56 | } 57 | 58 | override fun call(subscriber: Subscriber) { 59 | val listener = View.OnClickListener { v -> 60 | if (!subscriber.isUnsubscribed()) { 61 | subscriber.onNext(v) 62 | } 63 | } 64 | for (v in clickViews) { 65 | v.setOnClickListener(listener) 66 | } 67 | subscriber.add(object : MainThreadSubscription() { 68 | protected override fun onUnsubscribe() { 69 | val iterator = clickViews.iterator() 70 | while (iterator.hasNext()) { 71 | iterator.next().setOnClickListener(null) 72 | iterator.remove() 73 | } 74 | } 75 | }) 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /android/src/main/kotlin/syscall/zixuan/com/flutter_sys_call/video/takevideo/utils/FileUtils.kt: -------------------------------------------------------------------------------- 1 | package syscall.zixuan.com.flutter_sys_call.video.takevideo.utils 2 | 3 | import android.content.Context 4 | import android.graphics.Bitmap 5 | import android.graphics.BitmapFactory 6 | import android.graphics.Matrix 7 | import android.os.Build 8 | import android.os.Environment 9 | import android.os.StatFs 10 | import android.text.TextUtils 11 | 12 | import java.io.* 13 | import java.text.DecimalFormat 14 | import java.text.SimpleDateFormat 15 | import java.util.Date 16 | import java.util.Random 17 | 18 | 19 | object FileUtils { 20 | /** 21 | * 随机命名 22 | */ 23 | private val RANDOM_STRING = "abcdefghijklmnopqrstuvwxyz0123456789" 24 | /** 25 | * 时间命名 26 | */ 27 | private val TIME_STRING = "yyyyMMdd_HHmmss" 28 | /** 29 | * 限制图片最大宽度进行压缩 30 | */ 31 | private val MAX_WIDTH = 720 32 | /** 33 | * 限制图片最大高度进行压缩 34 | */ 35 | private val MAX_HEIGHT = 1280 36 | /** 37 | * 上传最大图片限制 38 | */ 39 | private val MAX_UPLOAD_PHOTO_SIZE = 300 * 1024 40 | 41 | /** 42 | * 缓存文件根目录名 43 | */ 44 | private val FILE_DIR = "you" 45 | /** 46 | * 上传的照片文件路径 47 | */ 48 | private val UPLOAD_FILE = "upload" 49 | 50 | /** 51 | * SD卡是否存在 52 | */ 53 | val isSDCardExist: Boolean 54 | get() = Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED 55 | 56 | /** 57 | * sd卡容量 58 | * 59 | * @return 60 | */ 61 | val availableStorage: Long 62 | get() { 63 | var availableSize: Long = 0 64 | if (isSDCardExist) { 65 | val sdFile = Environment.getExternalStorageDirectory() 66 | val stat = StatFs(sdFile.path) 67 | if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN_MR2) { 68 | availableSize = stat.availableBytes 69 | } else { 70 | availableSize = stat.availableBlocks.toLong() * stat.blockSize 71 | } 72 | } 73 | return availableSize 74 | } 75 | 76 | val timeString: String 77 | get() = SimpleDateFormat(TIME_STRING).format(Date()) 78 | 79 | /** 80 | * 获取缓存目录路径 81 | * 82 | * @return 83 | */ 84 | fun getCacheDirPath(context: Context): String { 85 | if (isSDCardExist) { 86 | val path = Environment.getExternalStorageDirectory().toString() + File.separator + FILE_DIR + File.separator 87 | val directory = File(path) 88 | if (!directory.exists()) directory.mkdirs() 89 | return path 90 | } else { 91 | val directory = File(context.cacheDir, FileUtils.FILE_DIR) 92 | if (!directory.exists()) directory.mkdirs() 93 | return directory.absolutePath 94 | } 95 | } 96 | 97 | /** 98 | * 获取缓存目录 99 | * 100 | * @return 101 | */ 102 | fun getCacheDir(context: Context): File { 103 | if (isSDCardExist) { 104 | val path = Environment.getExternalStorageDirectory().toString() + File.separator + FILE_DIR + File.separator 105 | val directory = File(path) 106 | if (!directory.exists()) directory.mkdirs() 107 | return directory 108 | } else { 109 | val directory = File(context.cacheDir, FileUtils.FILE_DIR) 110 | if (!directory.exists()) directory.mkdirs() 111 | return directory 112 | } 113 | } 114 | 115 | /** 116 | * 获取上传的路径 117 | * 118 | * @return 119 | */ 120 | fun getUploadCachePath(context: Context): String { 121 | if (isSDCardExist) { 122 | val path = 123 | Environment.getExternalStorageDirectory().toString() + File.separator + FILE_DIR + File.separator + UPLOAD_FILE + File.separator 124 | val directory = File(path) 125 | if (!directory.exists()) directory.mkdirs() 126 | return path 127 | } else { 128 | val directory = File(context.cacheDir, FileUtils.FILE_DIR + File.separator + UPLOAD_FILE) 129 | if (!directory.exists()) directory.mkdirs() 130 | return directory.absolutePath 131 | } 132 | } 133 | 134 | /** 135 | * jpg文件名 136 | * @param context 137 | * @return 138 | */ 139 | fun getUploadPhotoFile(context: Context): String { 140 | return getUploadCachePath(context) + timeString + ".jpg" 141 | } 142 | 143 | /** 144 | * mp4文件名 145 | * @param context 146 | * @return 147 | */ 148 | fun getUploadVideoFile(context: Context): String { 149 | return getUploadCachePath(context) + timeString + ".mp4" 150 | } 151 | 152 | /** 153 | * 保存拍摄图片 154 | * @param photoPath 155 | * @param data 156 | * @param isFrontFacing 是否为前置拍摄 157 | * @return 158 | */ 159 | fun savePhoto(photoPath: String?, data: ByteArray?, isFrontFacing: Boolean): Boolean { 160 | if (photoPath != null && data != null) { 161 | var fos: FileOutputStream? = null 162 | try { 163 | var preBitmap = compressBitmap(data, MAX_WIDTH, MAX_HEIGHT) 164 | if (isFrontFacing) { 165 | val matrix = Matrix() 166 | matrix.postScale(1f, -1f) 167 | val newBitmap = 168 | Bitmap.createBitmap(preBitmap!!, 0, 0, preBitmap.width, preBitmap.height, matrix, true) 169 | preBitmap.recycle() 170 | preBitmap = newBitmap 171 | } 172 | val newDatas = compressBitmapToBytes(preBitmap, MAX_UPLOAD_PHOTO_SIZE) 173 | fos = FileOutputStream(photoPath) 174 | fos.write(newDatas) 175 | LogUtils.i("compress over ") 176 | return true 177 | } catch (e: Exception) { 178 | e.printStackTrace() 179 | LogUtils.i(e) 180 | } finally { 181 | closeCloseable(fos) 182 | } 183 | } 184 | return false 185 | } 186 | 187 | /** 188 | * 把字节流按照图片方式大小进行压缩 189 | * @param datas 190 | * @param w 191 | * @param h 192 | * @return 193 | */ 194 | fun compressBitmap(datas: ByteArray?, w: Int, h: Int): Bitmap? { 195 | if (datas != null) { 196 | val opts = BitmapFactory.Options() 197 | opts.inJustDecodeBounds = true 198 | BitmapFactory.decodeByteArray(datas, 0, datas.size, opts) 199 | if (opts.outWidth != 0 && opts.outHeight != 0) { 200 | LogUtils.i(opts.outWidth.toString() + " " + opts.outHeight) 201 | val scaleX = opts.outWidth / w 202 | val scaleY = opts.outHeight / h 203 | var scale = 1 204 | if (scaleX >= scaleY && scaleX >= 1) { 205 | scale = scaleX 206 | } 207 | if (scaleX < scaleY && scaleY >= 1) { 208 | scale = scaleY 209 | } 210 | opts.inJustDecodeBounds = false 211 | opts.inSampleSize = scale 212 | LogUtils.i("compressBitmap inSampleSize " + datas.size + " " + scale) 213 | return BitmapFactory.decodeByteArray(datas, 0, datas.size, opts) 214 | } 215 | } 216 | return null 217 | } 218 | 219 | /** 220 | * 质量压缩图片 221 | * @param bitmap 222 | * @param maxSize 223 | * @return 224 | */ 225 | fun compressBitmapToBytes(bitmap: Bitmap?, maxSize: Int): ByteArray? { 226 | if (bitmap == null) return null 227 | val baos = ByteArrayOutputStream() 228 | bitmap.compress(Bitmap.CompressFormat.JPEG, 90, baos) 229 | var datas = baos.toByteArray() 230 | var options = 80 231 | var longs = datas.size 232 | while (longs > maxSize && options > 0) { 233 | LogUtils.i("compressBitmapToBytes $longs $options") 234 | baos.reset() 235 | bitmap.compress(Bitmap.CompressFormat.JPEG, options, baos) 236 | datas = baos.toByteArray() 237 | longs = datas.size 238 | options -= 20 239 | } 240 | return datas 241 | } 242 | 243 | /** 244 | * 获取文件路径下所有文件大小, 适当放到子线程中执行 245 | * 246 | * @param file 247 | * @return 248 | */ 249 | fun getFileSize(file: File?): Long { 250 | if (file == null || !file.exists()) return 0 251 | var totalSize: Long = 0 252 | if (file.isDirectory) { 253 | val files = file.listFiles() 254 | for (f in files) { 255 | totalSize += getFileSize(f) 256 | } 257 | return totalSize 258 | } else { 259 | return file.length() 260 | } 261 | } 262 | 263 | /** 264 | * 删除文件夹下所有文件,适当放到子线程中执行 265 | * 266 | * @param file 267 | */ 268 | fun delteFiles(file: File?) { 269 | if (file == null || !file.exists()) return 270 | if (file.isDirectory) { 271 | val files = file.listFiles() 272 | for (f in files) { 273 | if (!f.isDirectory) { 274 | f.delete() 275 | } 276 | } 277 | } else { 278 | file.delete() 279 | } 280 | } 281 | 282 | /** 283 | * 关闭资源 284 | * 285 | * @param close 286 | */ 287 | fun closeCloseable(close: Closeable?) { 288 | if (close != null) { 289 | try { 290 | close.close() 291 | } catch (e: IOException) { 292 | e.printStackTrace() 293 | } 294 | 295 | } 296 | } 297 | 298 | /** 299 | * 文件大小 300 | * 301 | * @param fileS 302 | * @return 303 | */ 304 | fun formetFileSize(fileS: Long): String { 305 | if (fileS <= 0) return "0B" 306 | return if (fileS < 1024) { 307 | DecimalFormat("#.00").format(fileS.toDouble()) + "B" 308 | } else if (fileS < 1048576) { 309 | DecimalFormat("#.00").format(fileS.toDouble() / 1024) + "KB" 310 | } else if (fileS < 1073741824) { 311 | DecimalFormat("#.00").format(fileS.toDouble() / 1048576) + "MB" 312 | } else { 313 | DecimalFormat("#.00").format(fileS.toDouble() / 1073741824) + "GB" 314 | } 315 | } 316 | 317 | /** 318 | * 获取随机文件名称字符串 319 | * 320 | * @param length 生成字符串的长度 321 | * @return 322 | */ 323 | fun getRandomString(length: Int): String { 324 | val random = Random() 325 | val sb = StringBuffer() 326 | for (i in 0 until length) { 327 | val number = random.nextInt(RANDOM_STRING.length) 328 | sb.append(RANDOM_STRING[number]) 329 | } 330 | return sb.toString() 331 | } 332 | 333 | /** 334 | * 将字符串写入文件中 335 | * 336 | * @param str 需要写入的字符串 337 | * @param file 写入文件的路径 338 | * @param append true 追加写入 false 覆盖写入 339 | * @return 340 | */ 341 | fun writeFile(str: String, file: File?, append: Boolean): Boolean { 342 | if (TextUtils.isEmpty(str) || file == null) return false 343 | var fw: FileWriter? = null 344 | try { 345 | fw = FileWriter(file, append) 346 | fw.write(str) 347 | fw.flush() 348 | return true 349 | } catch (e: Exception) { 350 | e.printStackTrace() 351 | } finally { 352 | closeCloseable(fw) 353 | } 354 | return false 355 | } 356 | 357 | } 358 | -------------------------------------------------------------------------------- /android/src/main/kotlin/syscall/zixuan/com/flutter_sys_call/video/takevideo/utils/LogUtils.kt: -------------------------------------------------------------------------------- 1 | package syscall.zixuan.com.flutter_sys_call.video.takevideo.utils 2 | 3 | 4 | import android.util.Log 5 | 6 | import java.io.PrintWriter 7 | import java.io.StringWriter 8 | import java.io.Writer 9 | 10 | 11 | object LogUtils { 12 | 13 | private val IS_DEBUG = true 14 | 15 | private val TAG = "you" 16 | 17 | fun e(tag: String, msg: String) { 18 | if (IS_DEBUG) Log.e(tag, msg) 19 | } 20 | 21 | fun i(tag: String, msg: String) { 22 | if (IS_DEBUG) Log.i(tag, msg) 23 | } 24 | 25 | fun d(tag: String, msg: String) { 26 | if (IS_DEBUG) Log.d(tag, msg) 27 | } 28 | 29 | fun v(tag: String, msg: String) { 30 | if (IS_DEBUG) Log.v(tag, msg) 31 | } 32 | 33 | fun w(tag: String, msg: String) { 34 | if (IS_DEBUG) Log.w(tag, msg) 35 | } 36 | 37 | fun e(msg: String) { 38 | if (IS_DEBUG) Log.e(TAG, msg) 39 | } 40 | 41 | fun i(msg: String) { 42 | i(TAG, msg) 43 | } 44 | 45 | fun d(msg: String) { 46 | d(TAG, msg) 47 | } 48 | 49 | fun v(msg: String) { 50 | v(TAG, msg) 51 | } 52 | 53 | fun w(msg: String) { 54 | w(TAG, msg) 55 | } 56 | 57 | fun i(tag: String, e: Throwable) { 58 | if (IS_DEBUG) { 59 | val info = StringWriter() 60 | val printWriter = PrintWriter(info) 61 | e.printStackTrace(printWriter) 62 | 63 | var cause: Throwable? = e.cause 64 | while (cause != null) { 65 | cause.printStackTrace(printWriter) 66 | cause = cause.cause 67 | } 68 | i(tag, info.toString()) 69 | } 70 | } 71 | 72 | fun i(e: Throwable) { 73 | i(TAG, e) 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /android/src/main/kotlin/syscall/zixuan/com/flutter_sys_call/video/takevideo/utils/RequestCode.kt: -------------------------------------------------------------------------------- 1 | package syscall.zixuan.com.flutter_sys_call.video.takevideo.utils 2 | 3 | 4 | object RequestCode { 5 | val CAPTURE_VIDEO = 1// 拍摄视频 6 | val GET_LOCAL_VIDEO = 2// 选择视频 7 | val GET_LOCAL_FILE = 3 // 选择文件 8 | val PICK_IMAGE = 4 9 | val PICKER_IMAGE_PREVIEW = 5 10 | val PREVIEW_IMAGE_FROM_CAMERA = 6 11 | val GET_LOCAL_IMAGE = 7// 相册 12 | 13 | val TAKE_PHOTO = 99 14 | val TAKE_VIDEO = 88 15 | } 16 | -------------------------------------------------------------------------------- /android/src/main/kotlin/syscall/zixuan/com/flutter_sys_call/video/takevideo/utils/SPUtils.kt: -------------------------------------------------------------------------------- 1 | package syscall.zixuan.com.flutter_sys_call.video.takevideo.utils 2 | 3 | 4 | import android.content.Context 5 | import android.content.SharedPreferences 6 | import androidx.core.content.SharedPreferencesCompat 7 | 8 | 9 | object SPUtils { 10 | 11 | /** 12 | * 保存在手机里面的文件名 13 | */ 14 | val FILE_NAME = "share_data" 15 | /** 16 | * 是否引导 17 | */ 18 | val HAS_SPLASH = "has_splash" 19 | /** 20 | * 用户Session值 21 | */ 22 | val USER_ACCOUNT = "user_account" 23 | 24 | /** 25 | * 保存数据 26 | * @param context 27 | * @param key 28 | * @param value 29 | */ 30 | fun put(context: Context, key: String, value: Any) { 31 | val sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE) 32 | val editor = sp.edit() 33 | if (value is String) { 34 | editor.putString(key, value) 35 | } else if (value is Int) { 36 | editor.putInt(key, value) 37 | } else if (value is Boolean) { 38 | editor.putBoolean(key, value) 39 | } else if (value is Float) { 40 | editor.putFloat(key, value) 41 | } else if (value is Long) { 42 | editor.putLong(key, value) 43 | } else { 44 | editor.putString(key, value.toString()) 45 | } 46 | 47 | SharedPreferencesCompat.EditorCompat.getInstance().apply(editor) 48 | } 49 | 50 | /** 51 | * 获取数据 52 | * @param context 53 | * @param key 54 | * @param defValue 55 | * @return 56 | */ 57 | operator fun get(context: Context, key: String, defValue: Any): Any? { 58 | val sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE) 59 | if (defValue is String) { 60 | return sp.getString(key, defValue) 61 | } else if (defValue is Int) { 62 | return sp.getInt(key, defValue) 63 | } else if (defValue is Boolean) { 64 | return sp.getBoolean(key, defValue) 65 | } else if (defValue is Float) { 66 | return sp.getFloat(key, defValue) 67 | } else if (defValue is Long) { 68 | return sp.getLong(key, defValue) 69 | } 70 | return null 71 | } 72 | 73 | /** 74 | * 移除数据 75 | * @param context 76 | * @param key 77 | */ 78 | fun remove(context: Context, key: String) { 79 | val sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE) 80 | val editor = sp.edit() 81 | editor.remove(key) 82 | SharedPreferencesCompat.EditorCompat.getInstance().apply(editor) 83 | } 84 | 85 | /** 86 | * 清空保存数据 87 | * @param context 88 | */ 89 | fun clear(context: Context) { 90 | val sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE) 91 | val editor = sp.edit() 92 | editor.clear() 93 | SharedPreferencesCompat.EditorCompat.getInstance().apply(editor) 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /android/src/main/res/drawable/btn_camera_flash.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /android/src/main/res/drawable/camera_choice.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/android/src/main/res/drawable/camera_choice.png -------------------------------------------------------------------------------- /android/src/main/res/drawable/camera_close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/android/src/main/res/drawable/camera_close.png -------------------------------------------------------------------------------- /android/src/main/res/drawable/camera_facing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/android/src/main/res/drawable/camera_facing.png -------------------------------------------------------------------------------- /android/src/main/res/drawable/camera_flash_close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/android/src/main/res/drawable/camera_flash_close.png -------------------------------------------------------------------------------- /android/src/main/res/drawable/camera_flash_open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/android/src/main/res/drawable/camera_flash_open.png -------------------------------------------------------------------------------- /android/src/main/res/layout/activity_camera.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 19 | 20 | 27 | 28 | 39 | 40 | 48 | 49 | 50 | 51 | 58 | 59 | 65 | 66 | 75 | 76 | 84 | 85 | 86 | 87 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /android/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /android/src/main/res/xml/video_file_path.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /example/.flutter-plugins-dependencies: -------------------------------------------------------------------------------- 1 | {"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_sys_call","path":"/Volumes/data/flutter_root/flutter_sys_call/","dependencies":["permission_handler","path_provider"]},{"name":"path_provider","path":"/Users/yanghuaxuan/flutter/.pub-cache/hosted/pub.flutter-io.cn/path_provider-0.5.0+1/","dependencies":[]},{"name":"permission_handler","path":"/Users/yanghuaxuan/flutter/.pub-cache/hosted/pub.flutter-io.cn/permission_handler-5.0.1+1/","dependencies":[]},{"name":"video_player","path":"/Users/yanghuaxuan/flutter/.pub-cache/hosted/pub.flutter-io.cn/video_player-0.10.11+2/","dependencies":[]}],"android":[{"name":"flutter_sys_call","path":"/Volumes/data/flutter_root/flutter_sys_call/","dependencies":["permission_handler","path_provider"]},{"name":"path_provider","path":"/Users/yanghuaxuan/flutter/.pub-cache/hosted/pub.flutter-io.cn/path_provider-0.5.0+1/","dependencies":[]},{"name":"permission_handler","path":"/Users/yanghuaxuan/flutter/.pub-cache/hosted/pub.flutter-io.cn/permission_handler-5.0.1+1/","dependencies":[]},{"name":"video_player","path":"/Users/yanghuaxuan/flutter/.pub-cache/hosted/pub.flutter-io.cn/video_player-0.10.11+2/","dependencies":[]}],"macos":[],"linux":[],"windows":[],"web":[{"name":"video_player_web","path":"/Users/yanghuaxuan/flutter/.pub-cache/hosted/pub.flutter-io.cn/video_player_web-0.1.3+2/","dependencies":[]}]},"dependencyGraph":[{"name":"flutter_sys_call","dependencies":["permission_handler","path_provider"]},{"name":"path_provider","dependencies":[]},{"name":"permission_handler","dependencies":[]},{"name":"video_player","dependencies":["video_player_web"]},{"name":"video_player_web","dependencies":[]}],"date_created":"2020-08-10 17:02:05.678165","version":"1.17.3"} -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.lock 4 | *.log 5 | *.pyc 6 | *.swp 7 | .DS_Store 8 | .atom/ 9 | .buildlog/ 10 | .history 11 | .svn/ 12 | 13 | # IntelliJ related 14 | *.iml 15 | *.ipr 16 | *.iws 17 | .idea/ 18 | 19 | # Visual Studio Code related 20 | .vscode/ 21 | 22 | # Flutter repo-specific 23 | /bin/cache/ 24 | /bin/mingit/ 25 | /dev/benchmarks/mega_gallery/ 26 | /dev/bots/.recipe_deps 27 | /dev/bots/android_tools/ 28 | /dev/docs/doc/ 29 | /dev/docs/flutter.docs.zip 30 | /dev/docs/lib/ 31 | /dev/docs/pubspec.yaml 32 | /packages/flutter/coverage/ 33 | version 34 | 35 | # packages file containing multi-root paths 36 | .packages.generated 37 | 38 | # Flutter/Dart/Pub related 39 | **/doc/api/ 40 | .dart_tool/ 41 | .flutter-plugins 42 | .packages 43 | .pub-cache/ 44 | .pub/ 45 | build/ 46 | flutter_*.png 47 | linked_*.ds 48 | unlinked.ds 49 | unlinked_spec.ds 50 | 51 | # Android related 52 | **/android/**/gradle-wrapper.jar 53 | **/android/.gradle 54 | **/android/captures/ 55 | **/android/gradlew 56 | **/android/gradlew.bat 57 | **/android/local.properties 58 | **/android/**/GeneratedPluginRegistrant.java 59 | **/android/key.properties 60 | *.jks 61 | 62 | # iOS/XCode related 63 | **/ios/**/*.mode1v3 64 | **/ios/**/*.mode2v3 65 | **/ios/**/*.moved-aside 66 | **/ios/**/*.pbxuser 67 | **/ios/**/*.perspectivev3 68 | **/ios/**/*sync/ 69 | **/ios/**/.sconsign.dblite 70 | **/ios/**/.tags* 71 | **/ios/**/.vagrant/ 72 | **/ios/**/DerivedData/ 73 | **/ios/**/Icon? 74 | **/ios/**/Pods/ 75 | **/ios/**/.symlinks/ 76 | **/ios/**/profile 77 | **/ios/**/xcuserdata 78 | **/ios/.generated/ 79 | **/ios/Flutter/App.framework 80 | **/ios/Flutter/Flutter.framework 81 | **/ios/Flutter/Generated.xcconfig 82 | **/ios/Flutter/app.flx 83 | **/ios/Flutter/app.zip 84 | **/ios/Flutter/flutter_assets/ 85 | **/ios/ServiceDefinitions.json 86 | **/ios/Runner/GeneratedPluginRegistrant.* 87 | 88 | # Coverage 89 | coverage/ 90 | 91 | # Exceptions to above rules. 92 | !**/ios/**/default.mode1v3 93 | !**/ios/**/default.mode2v3 94 | !**/ios/**/default.pbxuser 95 | !**/ios/**/default.perspectivev3 96 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages -------------------------------------------------------------------------------- /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: 8661d8aecd626f7f57ccbcb735553edc05a2e713 8 | channel: stable 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # flutter_sys_call_example 2 | 3 | Demonstrates how to use the flutter_sys_call 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.io/docs/get-started/codelab) 12 | - [Cookbook: Useful Flutter samples](https://flutter.io/docs/cookbook) 13 | 14 | For help getting started with Flutter, view our 15 | [online documentation](https://flutter.io/docs), which offers tutorials, 16 | samples, guidance on mobile development, and a full API reference. 17 | -------------------------------------------------------------------------------- /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 plugin: 'kotlin-android' 26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 27 | 28 | android { 29 | compileSdkVersion 28 30 | 31 | sourceSets { 32 | main.java.srcDirs += 'src/main/kotlin' 33 | } 34 | 35 | lintOptions { 36 | disable 'InvalidPackage' 37 | } 38 | 39 | defaultConfig { 40 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 41 | applicationId "syscall.zixuan.com.flutter_sys_call_example" 42 | minSdkVersion 16 43 | targetSdkVersion 28 44 | versionCode flutterVersionCode.toInteger() 45 | versionName flutterVersionName 46 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 47 | } 48 | 49 | buildTypes { 50 | release { 51 | // TODO: Add your own signing config for the release build. 52 | // Signing with the debug keys for now, so `flutter run --release` works. 53 | signingConfig signingConfigs.debug 54 | } 55 | } 56 | } 57 | 58 | flutter { 59 | source '../..' 60 | } 61 | 62 | dependencies { 63 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 64 | testImplementation 'junit:junit:4.12' 65 | androidTestImplementation 'androidx.test:runner:1.2.0' 66 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' 67 | } 68 | -------------------------------------------------------------------------------- /example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 9 | 10 | 11 | 15 | 22 | 26 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /example/android/app/src/main/kotlin/syscall/zixuan/com/flutter_sys_call_example/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package syscall.zixuan.com.flutter_sys_call_example 2 | 3 | import android.os.Bundle 4 | 5 | import io.flutter.app.FlutterActivity 6 | import io.flutter.plugins.GeneratedPluginRegistrant 7 | 8 | class MainActivity: FlutterActivity() { 9 | override fun onCreate(savedInstanceState: Bundle?) { 10 | super.onCreate(savedInstanceState) 11 | GeneratedPluginRegistrant.registerWith(this) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/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/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/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/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/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/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /example/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.3.31' 3 | repositories { 4 | google() 5 | jcenter() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:4.0.0' 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | } 12 | } 13 | 14 | allprojects { 15 | repositories { 16 | google() 17 | jcenter() 18 | maven { url 'https://jitpack.io' } 19 | } 20 | } 21 | 22 | 23 | 24 | rootProject.buildDir = '../build' 25 | subprojects { 26 | project.buildDir = "${rootProject.buildDir}/${project.name}" 27 | } 28 | subprojects { 29 | project.evaluationDependsOn(':app') 30 | } 31 | 32 | task clean(type: Delete) { 33 | delete rootProject.buildDir 34 | } 35 | -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | android.enableJetifier=true 2 | android.useAndroidX=true 3 | org.gradle.jvmargs=-Xmx1536M 4 | android.enableR8=true 5 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 23 08:50:38 CEST 2017 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 | -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() 4 | 5 | def plugins = new Properties() 6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') 7 | if (pluginsFile.exists()) { 8 | pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } 9 | } 10 | 11 | plugins.each { name, path -> 12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() 13 | include ":$name" 14 | project(":$name").projectDir = pluginDirectory 15 | } 16 | -------------------------------------------------------------------------------- /example/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 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 | -------------------------------------------------------------------------------- /example/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /example/ios/Flutter/Flutter.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # NOTE: This podspec is NOT to be published. It is only used as a local source! 3 | # 4 | 5 | Pod::Spec.new do |s| 6 | s.name = 'Flutter' 7 | s.version = '1.0.0' 8 | s.summary = 'High-performance, high-fidelity mobile apps.' 9 | s.description = <<-DESC 10 | Flutter provides an easy and productive way to build and deploy high-performance mobile apps for Android and iOS. 11 | DESC 12 | s.homepage = 'https://flutter.io' 13 | s.license = { :type => 'MIT' } 14 | s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' } 15 | s.source = { :git => 'https://github.com/flutter/engine', :tag => s.version.to_s } 16 | s.ios.deployment_target = '8.0' 17 | s.vendored_frameworks = 'Flutter.framework' 18 | end 19 | -------------------------------------------------------------------------------- /example/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /example/ios/Flutter/flutter_export_environment.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # This is a generated file; do not edit or check into version control. 3 | export "FLUTTER_ROOT=/Users/yanghuaxuan/flutter" 4 | export "FLUTTER_APPLICATION_PATH=/Volumes/data/flutter_root/flutter_sys_call/example" 5 | export "FLUTTER_TARGET=/Volumes/data/flutter_root/flutter_sys_call/example/lib/main.dart" 6 | export "FLUTTER_BUILD_DIR=build" 7 | export "SYMROOT=${SOURCE_ROOT}/../build/ios" 8 | export "OTHER_LDFLAGS=$(inherited) -framework Flutter" 9 | export "FLUTTER_FRAMEWORK_DIR=/Users/yanghuaxuan/flutter/bin/cache/artifacts/engine/ios" 10 | export "FLUTTER_BUILD_NAME=1.0.0" 11 | export "FLUTTER_BUILD_NUMBER=1" 12 | export "TRACK_WIDGET_CREATION=true" 13 | export "DART_DEFINES=flutter.inspector.structuredErrors=true" 14 | -------------------------------------------------------------------------------- /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 parse_KV_file(file, separator='=') 14 | file_abs_path = File.expand_path(file) 15 | if !File.exists? file_abs_path 16 | return []; 17 | end 18 | pods_ary = [] 19 | skip_line_start_symbols = ["#", "/"] 20 | File.foreach(file_abs_path) { |line| 21 | next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ } 22 | plugin = line.split(pattern=separator) 23 | if plugin.length == 2 24 | podname = plugin[0].strip() 25 | path = plugin[1].strip() 26 | podpath = File.expand_path("#{path}", file_abs_path) 27 | pods_ary.push({:name => podname, :path => podpath}); 28 | else 29 | puts "Invalid plugin specification: #{line}" 30 | end 31 | } 32 | return pods_ary 33 | end 34 | 35 | target 'Runner' do 36 | use_frameworks! 37 | # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock 38 | # referring to absolute paths on developers' machines. 39 | system('rm -rf .symlinks') 40 | system('mkdir -p .symlinks/plugins') 41 | 42 | # Flutter Pods 43 | generated_xcode_build_settings = parse_KV_file('./Flutter/Generated.xcconfig') 44 | if generated_xcode_build_settings.empty? 45 | puts "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter packages get is executed first." 46 | end 47 | generated_xcode_build_settings.map { |p| 48 | if p[:name] == 'FLUTTER_FRAMEWORK_DIR' 49 | symlink = File.join('.symlinks', 'flutter') 50 | File.symlink(File.dirname(p[:path]), symlink) 51 | pod 'Flutter', :path => File.join(symlink, File.basename(p[:path])) 52 | end 53 | } 54 | 55 | 56 | 57 | # Plugin Pods 58 | plugin_pods = parse_KV_file('../.flutter-plugins') 59 | plugin_pods.map { |p| 60 | symlink = File.join('.symlinks', 'plugins', p[:name]) 61 | File.symlink(p[:path], symlink) 62 | pod p[:name], :path => File.join(symlink, 'ios') 63 | } 64 | end 65 | 66 | post_install do |installer| 67 | installer.pods_project.targets.each do |target| 68 | target.build_configurations.each do |config| 69 | config.build_settings['ENABLE_BITCODE'] = 'NO' 70 | end 71 | end 72 | end 73 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 11 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 12 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 13 | 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; }; 14 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 15 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 16 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 17 | D1820D3DBD9D88943154F46E /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F30E02949AF940FA27044C40 /* Pods_Runner.framework */; }; 18 | /* End PBXBuildFile section */ 19 | 20 | /* Begin PBXCopyFilesBuildPhase section */ 21 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = { 22 | isa = PBXCopyFilesBuildPhase; 23 | buildActionMask = 2147483647; 24 | dstPath = ""; 25 | dstSubfolderSpec = 10; 26 | files = ( 27 | ); 28 | name = "Embed Frameworks"; 29 | runOnlyForDeploymentPostprocessing = 0; 30 | }; 31 | /* End PBXCopyFilesBuildPhase section */ 32 | 33 | /* Begin PBXFileReference section */ 34 | 0D36AF9FE33B512C67B0A902 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 35 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 36 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 37 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 38 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 39 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 40 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 41 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 42 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 43 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 44 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 45 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 46 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 47 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 48 | 99EA0982369CF902C8CBE0EC /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; 49 | D1AFCEBDC5321672A10938A9 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 50 | F30E02949AF940FA27044C40 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 51 | /* End PBXFileReference section */ 52 | 53 | /* Begin PBXFrameworksBuildPhase section */ 54 | 97C146EB1CF9000F007C117D /* Frameworks */ = { 55 | isa = PBXFrameworksBuildPhase; 56 | buildActionMask = 2147483647; 57 | files = ( 58 | D1820D3DBD9D88943154F46E /* Pods_Runner.framework in Frameworks */, 59 | ); 60 | runOnlyForDeploymentPostprocessing = 0; 61 | }; 62 | /* End PBXFrameworksBuildPhase section */ 63 | 64 | /* Begin PBXGroup section */ 65 | 9740EEB11CF90186004384FC /* Flutter */ = { 66 | isa = PBXGroup; 67 | children = ( 68 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 69 | 9740EEB21CF90195004384FC /* Debug.xcconfig */, 70 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 71 | 9740EEB31CF90195004384FC /* Generated.xcconfig */, 72 | ); 73 | name = Flutter; 74 | sourceTree = ""; 75 | }; 76 | 97C146E51CF9000F007C117D = { 77 | isa = PBXGroup; 78 | children = ( 79 | 9740EEB11CF90186004384FC /* Flutter */, 80 | 97C146F01CF9000F007C117D /* Runner */, 81 | 97C146EF1CF9000F007C117D /* Products */, 82 | F15E0DB8DD15E9310E577760 /* Pods */, 83 | E70D9F8C0A45A019F7FB6BA7 /* Frameworks */, 84 | ); 85 | sourceTree = ""; 86 | }; 87 | 97C146EF1CF9000F007C117D /* Products */ = { 88 | isa = PBXGroup; 89 | children = ( 90 | 97C146EE1CF9000F007C117D /* Runner.app */, 91 | ); 92 | name = Products; 93 | sourceTree = ""; 94 | }; 95 | 97C146F01CF9000F007C117D /* Runner */ = { 96 | isa = PBXGroup; 97 | children = ( 98 | 97C146FA1CF9000F007C117D /* Main.storyboard */, 99 | 97C146FD1CF9000F007C117D /* Assets.xcassets */, 100 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 101 | 97C147021CF9000F007C117D /* Info.plist */, 102 | 97C146F11CF9000F007C117D /* Supporting Files */, 103 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 104 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 105 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, 106 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, 107 | ); 108 | path = Runner; 109 | sourceTree = ""; 110 | }; 111 | 97C146F11CF9000F007C117D /* Supporting Files */ = { 112 | isa = PBXGroup; 113 | children = ( 114 | ); 115 | name = "Supporting Files"; 116 | sourceTree = ""; 117 | }; 118 | E70D9F8C0A45A019F7FB6BA7 /* Frameworks */ = { 119 | isa = PBXGroup; 120 | children = ( 121 | F30E02949AF940FA27044C40 /* Pods_Runner.framework */, 122 | ); 123 | name = Frameworks; 124 | sourceTree = ""; 125 | }; 126 | F15E0DB8DD15E9310E577760 /* Pods */ = { 127 | isa = PBXGroup; 128 | children = ( 129 | D1AFCEBDC5321672A10938A9 /* Pods-Runner.debug.xcconfig */, 130 | 0D36AF9FE33B512C67B0A902 /* Pods-Runner.release.xcconfig */, 131 | 99EA0982369CF902C8CBE0EC /* Pods-Runner.profile.xcconfig */, 132 | ); 133 | path = Pods; 134 | sourceTree = ""; 135 | }; 136 | /* End PBXGroup section */ 137 | 138 | /* Begin PBXNativeTarget section */ 139 | 97C146ED1CF9000F007C117D /* Runner */ = { 140 | isa = PBXNativeTarget; 141 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; 142 | buildPhases = ( 143 | 9BF59C98BD1624F67A9A7E45 /* [CP] Check Pods Manifest.lock */, 144 | 9740EEB61CF901F6004384FC /* Run Script */, 145 | 97C146EA1CF9000F007C117D /* Sources */, 146 | 97C146EB1CF9000F007C117D /* Frameworks */, 147 | 97C146EC1CF9000F007C117D /* Resources */, 148 | 9705A1C41CF9048500538489 /* Embed Frameworks */, 149 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 150 | 7909EEA3E9DE43958FCD6809 /* [CP] Embed Pods Frameworks */, 151 | ); 152 | buildRules = ( 153 | ); 154 | dependencies = ( 155 | ); 156 | name = Runner; 157 | productName = Runner; 158 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */; 159 | productType = "com.apple.product-type.application"; 160 | }; 161 | /* End PBXNativeTarget section */ 162 | 163 | /* Begin PBXProject section */ 164 | 97C146E61CF9000F007C117D /* Project object */ = { 165 | isa = PBXProject; 166 | attributes = { 167 | LastUpgradeCheck = 0910; 168 | ORGANIZATIONNAME = "The Chromium Authors"; 169 | TargetAttributes = { 170 | 97C146ED1CF9000F007C117D = { 171 | CreatedOnToolsVersion = 7.3.1; 172 | DevelopmentTeam = VP5Y6VP5AK; 173 | LastSwiftMigration = 0910; 174 | ProvisioningStyle = Automatic; 175 | }; 176 | }; 177 | }; 178 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; 179 | compatibilityVersion = "Xcode 3.2"; 180 | developmentRegion = English; 181 | hasScannedForEncodings = 0; 182 | knownRegions = ( 183 | English, 184 | en, 185 | Base, 186 | ); 187 | mainGroup = 97C146E51CF9000F007C117D; 188 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */; 189 | projectDirPath = ""; 190 | projectRoot = ""; 191 | targets = ( 192 | 97C146ED1CF9000F007C117D /* Runner */, 193 | ); 194 | }; 195 | /* End PBXProject section */ 196 | 197 | /* Begin PBXResourcesBuildPhase section */ 198 | 97C146EC1CF9000F007C117D /* Resources */ = { 199 | isa = PBXResourcesBuildPhase; 200 | buildActionMask = 2147483647; 201 | files = ( 202 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 203 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 204 | 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */, 205 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 206 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, 207 | ); 208 | runOnlyForDeploymentPostprocessing = 0; 209 | }; 210 | /* End PBXResourcesBuildPhase section */ 211 | 212 | /* Begin PBXShellScriptBuildPhase section */ 213 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { 214 | isa = PBXShellScriptBuildPhase; 215 | buildActionMask = 2147483647; 216 | files = ( 217 | ); 218 | inputPaths = ( 219 | ); 220 | name = "Thin Binary"; 221 | outputPaths = ( 222 | ); 223 | runOnlyForDeploymentPostprocessing = 0; 224 | shellPath = /bin/sh; 225 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; 226 | }; 227 | 7909EEA3E9DE43958FCD6809 /* [CP] Embed Pods Frameworks */ = { 228 | isa = PBXShellScriptBuildPhase; 229 | buildActionMask = 2147483647; 230 | files = ( 231 | ); 232 | inputPaths = ( 233 | "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", 234 | "${PODS_ROOT}/../.symlinks/flutter/ios/Flutter.framework", 235 | "${BUILT_PRODUCTS_DIR}/MACamera/MACamera.framework", 236 | "${BUILT_PRODUCTS_DIR}/flutter_sys_call/flutter_sys_call.framework", 237 | "${BUILT_PRODUCTS_DIR}/path_provider/path_provider.framework", 238 | "${BUILT_PRODUCTS_DIR}/swiftScan/swiftScan.framework", 239 | "${BUILT_PRODUCTS_DIR}/video_player/video_player.framework", 240 | ); 241 | name = "[CP] Embed Pods Frameworks"; 242 | outputPaths = ( 243 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework", 244 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MACamera.framework", 245 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_sys_call.framework", 246 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider.framework", 247 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/swiftScan.framework", 248 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/video_player.framework", 249 | ); 250 | runOnlyForDeploymentPostprocessing = 0; 251 | shellPath = /bin/sh; 252 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; 253 | showEnvVarsInLog = 0; 254 | }; 255 | 9740EEB61CF901F6004384FC /* Run Script */ = { 256 | isa = PBXShellScriptBuildPhase; 257 | buildActionMask = 2147483647; 258 | files = ( 259 | ); 260 | inputPaths = ( 261 | ); 262 | name = "Run Script"; 263 | outputPaths = ( 264 | ); 265 | runOnlyForDeploymentPostprocessing = 0; 266 | shellPath = /bin/sh; 267 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; 268 | }; 269 | 9BF59C98BD1624F67A9A7E45 /* [CP] Check Pods Manifest.lock */ = { 270 | isa = PBXShellScriptBuildPhase; 271 | buildActionMask = 2147483647; 272 | files = ( 273 | ); 274 | inputFileListPaths = ( 275 | ); 276 | inputPaths = ( 277 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 278 | "${PODS_ROOT}/Manifest.lock", 279 | ); 280 | name = "[CP] Check Pods Manifest.lock"; 281 | outputFileListPaths = ( 282 | ); 283 | outputPaths = ( 284 | "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", 285 | ); 286 | runOnlyForDeploymentPostprocessing = 0; 287 | shellPath = /bin/sh; 288 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /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"; 289 | showEnvVarsInLog = 0; 290 | }; 291 | /* End PBXShellScriptBuildPhase section */ 292 | 293 | /* Begin PBXSourcesBuildPhase section */ 294 | 97C146EA1CF9000F007C117D /* Sources */ = { 295 | isa = PBXSourcesBuildPhase; 296 | buildActionMask = 2147483647; 297 | files = ( 298 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, 299 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, 300 | ); 301 | runOnlyForDeploymentPostprocessing = 0; 302 | }; 303 | /* End PBXSourcesBuildPhase section */ 304 | 305 | /* Begin PBXVariantGroup section */ 306 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = { 307 | isa = PBXVariantGroup; 308 | children = ( 309 | 97C146FB1CF9000F007C117D /* Base */, 310 | ); 311 | name = Main.storyboard; 312 | sourceTree = ""; 313 | }; 314 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { 315 | isa = PBXVariantGroup; 316 | children = ( 317 | 97C147001CF9000F007C117D /* Base */, 318 | ); 319 | name = LaunchScreen.storyboard; 320 | sourceTree = ""; 321 | }; 322 | /* End PBXVariantGroup section */ 323 | 324 | /* Begin XCBuildConfiguration section */ 325 | 249021D3217E4FDB00AE95B9 /* Profile */ = { 326 | isa = XCBuildConfiguration; 327 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 328 | buildSettings = { 329 | ALWAYS_SEARCH_USER_PATHS = NO; 330 | CLANG_ANALYZER_NONNULL = YES; 331 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 332 | CLANG_CXX_LIBRARY = "libc++"; 333 | CLANG_ENABLE_MODULES = YES; 334 | CLANG_ENABLE_OBJC_ARC = YES; 335 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 336 | CLANG_WARN_BOOL_CONVERSION = YES; 337 | CLANG_WARN_COMMA = YES; 338 | CLANG_WARN_CONSTANT_CONVERSION = YES; 339 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 340 | CLANG_WARN_EMPTY_BODY = YES; 341 | CLANG_WARN_ENUM_CONVERSION = YES; 342 | CLANG_WARN_INFINITE_RECURSION = YES; 343 | CLANG_WARN_INT_CONVERSION = YES; 344 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 345 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 346 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 347 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 348 | CLANG_WARN_STRICT_PROTOTYPES = YES; 349 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 350 | CLANG_WARN_UNREACHABLE_CODE = YES; 351 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 352 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 353 | COPY_PHASE_STRIP = NO; 354 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 355 | ENABLE_NS_ASSERTIONS = NO; 356 | ENABLE_STRICT_OBJC_MSGSEND = YES; 357 | GCC_C_LANGUAGE_STANDARD = gnu99; 358 | GCC_NO_COMMON_BLOCKS = YES; 359 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 360 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 361 | GCC_WARN_UNDECLARED_SELECTOR = YES; 362 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 363 | GCC_WARN_UNUSED_FUNCTION = YES; 364 | GCC_WARN_UNUSED_VARIABLE = YES; 365 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 366 | MTL_ENABLE_DEBUG_INFO = NO; 367 | SDKROOT = iphoneos; 368 | TARGETED_DEVICE_FAMILY = "1,2"; 369 | VALIDATE_PRODUCT = YES; 370 | }; 371 | name = Profile; 372 | }; 373 | 249021D4217E4FDB00AE95B9 /* Profile */ = { 374 | isa = XCBuildConfiguration; 375 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 376 | buildSettings = { 377 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 378 | CODE_SIGN_IDENTITY = "iPhone Developer"; 379 | CODE_SIGN_STYLE = Automatic; 380 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 381 | DEVELOPMENT_TEAM = VP5Y6VP5AK; 382 | ENABLE_BITCODE = NO; 383 | FRAMEWORK_SEARCH_PATHS = ( 384 | "$(inherited)", 385 | "$(PROJECT_DIR)/Flutter", 386 | ); 387 | INFOPLIST_FILE = Runner/Info.plist; 388 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 389 | LIBRARY_SEARCH_PATHS = ( 390 | "$(inherited)", 391 | "$(PROJECT_DIR)/Flutter", 392 | ); 393 | PRODUCT_BUNDLE_IDENTIFIER = syscall.zixuan.com.flutterSysCallExample; 394 | PRODUCT_NAME = "$(TARGET_NAME)"; 395 | PROVISIONING_PROFILE_SPECIFIER = ""; 396 | SWIFT_VERSION = 4.0; 397 | VERSIONING_SYSTEM = "apple-generic"; 398 | }; 399 | name = Profile; 400 | }; 401 | 97C147031CF9000F007C117D /* Debug */ = { 402 | isa = XCBuildConfiguration; 403 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 404 | buildSettings = { 405 | ALWAYS_SEARCH_USER_PATHS = NO; 406 | CLANG_ANALYZER_NONNULL = YES; 407 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 408 | CLANG_CXX_LIBRARY = "libc++"; 409 | CLANG_ENABLE_MODULES = YES; 410 | CLANG_ENABLE_OBJC_ARC = YES; 411 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 412 | CLANG_WARN_BOOL_CONVERSION = YES; 413 | CLANG_WARN_COMMA = YES; 414 | CLANG_WARN_CONSTANT_CONVERSION = YES; 415 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 416 | CLANG_WARN_EMPTY_BODY = YES; 417 | CLANG_WARN_ENUM_CONVERSION = YES; 418 | CLANG_WARN_INFINITE_RECURSION = YES; 419 | CLANG_WARN_INT_CONVERSION = YES; 420 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 421 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 422 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 423 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 424 | CLANG_WARN_STRICT_PROTOTYPES = YES; 425 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 426 | CLANG_WARN_UNREACHABLE_CODE = YES; 427 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 428 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 429 | COPY_PHASE_STRIP = NO; 430 | DEBUG_INFORMATION_FORMAT = dwarf; 431 | ENABLE_STRICT_OBJC_MSGSEND = YES; 432 | ENABLE_TESTABILITY = YES; 433 | GCC_C_LANGUAGE_STANDARD = gnu99; 434 | GCC_DYNAMIC_NO_PIC = NO; 435 | GCC_NO_COMMON_BLOCKS = YES; 436 | GCC_OPTIMIZATION_LEVEL = 0; 437 | GCC_PREPROCESSOR_DEFINITIONS = ( 438 | "DEBUG=1", 439 | "$(inherited)", 440 | ); 441 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 442 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 443 | GCC_WARN_UNDECLARED_SELECTOR = YES; 444 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 445 | GCC_WARN_UNUSED_FUNCTION = YES; 446 | GCC_WARN_UNUSED_VARIABLE = YES; 447 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 448 | MTL_ENABLE_DEBUG_INFO = YES; 449 | ONLY_ACTIVE_ARCH = YES; 450 | SDKROOT = iphoneos; 451 | TARGETED_DEVICE_FAMILY = "1,2"; 452 | }; 453 | name = Debug; 454 | }; 455 | 97C147041CF9000F007C117D /* Release */ = { 456 | isa = XCBuildConfiguration; 457 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 458 | buildSettings = { 459 | ALWAYS_SEARCH_USER_PATHS = NO; 460 | CLANG_ANALYZER_NONNULL = YES; 461 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 462 | CLANG_CXX_LIBRARY = "libc++"; 463 | CLANG_ENABLE_MODULES = YES; 464 | CLANG_ENABLE_OBJC_ARC = YES; 465 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 466 | CLANG_WARN_BOOL_CONVERSION = YES; 467 | CLANG_WARN_COMMA = YES; 468 | CLANG_WARN_CONSTANT_CONVERSION = YES; 469 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 470 | CLANG_WARN_EMPTY_BODY = YES; 471 | CLANG_WARN_ENUM_CONVERSION = YES; 472 | CLANG_WARN_INFINITE_RECURSION = YES; 473 | CLANG_WARN_INT_CONVERSION = YES; 474 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 475 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 476 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 477 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 478 | CLANG_WARN_STRICT_PROTOTYPES = YES; 479 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 480 | CLANG_WARN_UNREACHABLE_CODE = YES; 481 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 482 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 483 | COPY_PHASE_STRIP = NO; 484 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 485 | ENABLE_NS_ASSERTIONS = NO; 486 | ENABLE_STRICT_OBJC_MSGSEND = YES; 487 | GCC_C_LANGUAGE_STANDARD = gnu99; 488 | GCC_NO_COMMON_BLOCKS = YES; 489 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 490 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 491 | GCC_WARN_UNDECLARED_SELECTOR = YES; 492 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 493 | GCC_WARN_UNUSED_FUNCTION = YES; 494 | GCC_WARN_UNUSED_VARIABLE = YES; 495 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 496 | MTL_ENABLE_DEBUG_INFO = NO; 497 | SDKROOT = iphoneos; 498 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 499 | TARGETED_DEVICE_FAMILY = "1,2"; 500 | VALIDATE_PRODUCT = YES; 501 | }; 502 | name = Release; 503 | }; 504 | 97C147061CF9000F007C117D /* Debug */ = { 505 | isa = XCBuildConfiguration; 506 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 507 | buildSettings = { 508 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 509 | CLANG_ENABLE_MODULES = YES; 510 | CODE_SIGN_IDENTITY = "iPhone Developer"; 511 | CODE_SIGN_STYLE = Automatic; 512 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 513 | DEVELOPMENT_TEAM = VP5Y6VP5AK; 514 | ENABLE_BITCODE = NO; 515 | FRAMEWORK_SEARCH_PATHS = ( 516 | "$(inherited)", 517 | "$(PROJECT_DIR)/Flutter", 518 | ); 519 | INFOPLIST_FILE = Runner/Info.plist; 520 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 521 | LIBRARY_SEARCH_PATHS = ( 522 | "$(inherited)", 523 | "$(PROJECT_DIR)/Flutter", 524 | ); 525 | PRODUCT_BUNDLE_IDENTIFIER = syscall.zixuan.com.flutterSysCallExample; 526 | PRODUCT_NAME = "$(TARGET_NAME)"; 527 | PROVISIONING_PROFILE_SPECIFIER = ""; 528 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 529 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 530 | SWIFT_SWIFT3_OBJC_INFERENCE = On; 531 | SWIFT_VERSION = 4.0; 532 | VERSIONING_SYSTEM = "apple-generic"; 533 | }; 534 | name = Debug; 535 | }; 536 | 97C147071CF9000F007C117D /* Release */ = { 537 | isa = XCBuildConfiguration; 538 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 539 | buildSettings = { 540 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 541 | CLANG_ENABLE_MODULES = YES; 542 | CODE_SIGN_IDENTITY = "iPhone Developer"; 543 | CODE_SIGN_STYLE = Automatic; 544 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 545 | DEVELOPMENT_TEAM = VP5Y6VP5AK; 546 | ENABLE_BITCODE = NO; 547 | FRAMEWORK_SEARCH_PATHS = ( 548 | "$(inherited)", 549 | "$(PROJECT_DIR)/Flutter", 550 | ); 551 | INFOPLIST_FILE = Runner/Info.plist; 552 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 553 | LIBRARY_SEARCH_PATHS = ( 554 | "$(inherited)", 555 | "$(PROJECT_DIR)/Flutter", 556 | ); 557 | PRODUCT_BUNDLE_IDENTIFIER = syscall.zixuan.com.flutterSysCallExample; 558 | PRODUCT_NAME = "$(TARGET_NAME)"; 559 | PROVISIONING_PROFILE_SPECIFIER = ""; 560 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 561 | SWIFT_SWIFT3_OBJC_INFERENCE = On; 562 | SWIFT_VERSION = 4.0; 563 | VERSIONING_SYSTEM = "apple-generic"; 564 | }; 565 | name = Release; 566 | }; 567 | /* End XCBuildConfiguration section */ 568 | 569 | /* Begin XCConfigurationList section */ 570 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { 571 | isa = XCConfigurationList; 572 | buildConfigurations = ( 573 | 97C147031CF9000F007C117D /* Debug */, 574 | 97C147041CF9000F007C117D /* Release */, 575 | 249021D3217E4FDB00AE95B9 /* Profile */, 576 | ); 577 | defaultConfigurationIsVisible = 0; 578 | defaultConfigurationName = Release; 579 | }; 580 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { 581 | isa = XCConfigurationList; 582 | buildConfigurations = ( 583 | 97C147061CF9000F007C117D /* Debug */, 584 | 97C147071CF9000F007C117D /* Release */, 585 | 249021D4217E4FDB00AE95B9 /* Profile */, 586 | ); 587 | defaultConfigurationIsVisible = 0; 588 | defaultConfigurationName = Release; 589 | }; 590 | /* End XCConfigurationList section */ 591 | }; 592 | rootObject = 97C146E61CF9000F007C117D /* Project object */; 593 | } 594 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 33 | 34 | 40 | 41 | 42 | 43 | 44 | 45 | 56 | 58 | 64 | 65 | 66 | 67 | 68 | 69 | 75 | 77 | 83 | 84 | 85 | 86 | 88 | 89 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /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/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/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/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/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/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/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/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/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/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/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/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/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/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/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/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/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/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/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/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/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/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/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/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/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/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /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/ios/Runner/Assets.xcassets/back_nor.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "微信图片_20190610092524.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/back_nor.imageset/微信图片_20190610092524.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/example/ios/Runner/Assets.xcassets/back_nor.imageset/微信图片_20190610092524.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/back_pressed.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "微信图片_20190610092518.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/back_pressed.imageset/微信图片_20190610092518.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/example/ios/Runner/Assets.xcassets/back_pressed.imageset/微信图片_20190610092518.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/device_scan.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "device_scan@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/device_scan.imageset/device_scan@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/example/ios/Runner/Assets.xcassets/device_scan.imageset/device_scan@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/qrcode_Scan_weixin_Line.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "qrcode_Scan_weixin_Line@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/qrcode_Scan_weixin_Line.imageset/qrcode_Scan_weixin_Line@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/example/ios/Runner/Assets.xcassets/qrcode_Scan_weixin_Line.imageset/qrcode_Scan_weixin_Line@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/qrcode_scan_btn_flash_down.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "qrcode_scan_btn_flash_down@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/qrcode_scan_btn_flash_down.imageset/qrcode_scan_btn_flash_down@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/example/ios/Runner/Assets.xcassets/qrcode_scan_btn_flash_down.imageset/qrcode_scan_btn_flash_down@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/qrcode_scan_btn_flash_nor.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "qrcode_scan_btn_flash_nor@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/qrcode_scan_btn_flash_nor.imageset/qrcode_scan_btn_flash_nor@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/example/ios/Runner/Assets.xcassets/qrcode_scan_btn_flash_nor.imageset/qrcode_scan_btn_flash_nor@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/qrcode_scan_btn_myqrcode_down.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "qrcode_scan_btn_myqrcode_down@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/qrcode_scan_btn_myqrcode_down.imageset/qrcode_scan_btn_myqrcode_down@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/example/ios/Runner/Assets.xcassets/qrcode_scan_btn_myqrcode_down.imageset/qrcode_scan_btn_myqrcode_down@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/qrcode_scan_btn_myqrcode_nor.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "qrcode_scan_btn_myqrcode_nor@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/qrcode_scan_btn_myqrcode_nor.imageset/qrcode_scan_btn_myqrcode_nor@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/example/ios/Runner/Assets.xcassets/qrcode_scan_btn_myqrcode_nor.imageset/qrcode_scan_btn_myqrcode_nor@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/qrcode_scan_btn_photo_down.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "qrcode_scan_btn_photo_down@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/qrcode_scan_btn_photo_down.imageset/qrcode_scan_btn_photo_down@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/example/ios/Runner/Assets.xcassets/qrcode_scan_btn_photo_down.imageset/qrcode_scan_btn_photo_down@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/qrcode_scan_btn_photo_nor.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "qrcode_scan_btn_photo_nor@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/qrcode_scan_btn_photo_nor.imageset/qrcode_scan_btn_photo_nor@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/example/ios/Runner/Assets.xcassets/qrcode_scan_btn_photo_nor.imageset/qrcode_scan_btn_photo_nor@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/qrcode_scan_btn_scan_off.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "qrcode_scan_btn_scan_off@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/qrcode_scan_btn_scan_off.imageset/qrcode_scan_btn_scan_off@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/example/ios/Runner/Assets.xcassets/qrcode_scan_btn_scan_off.imageset/qrcode_scan_btn_scan_off@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/qrcode_scan_full_net.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "qrcode_scan_full_net.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/qrcode_scan_full_net.imageset/qrcode_scan_full_net.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/example/ios/Runner/Assets.xcassets/qrcode_scan_full_net.imageset/qrcode_scan_full_net.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/qrcode_scan_light_green.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "qrcode_scan_light_green@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/qrcode_scan_light_green.imageset/qrcode_scan_light_green@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/example/ios/Runner/Assets.xcassets/qrcode_scan_light_green.imageset/qrcode_scan_light_green@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/qrcode_scan_part_net.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "qrcode_scan_part_net.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/qrcode_scan_part_net.imageset/qrcode_scan_part_net.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/example/ios/Runner/Assets.xcassets/qrcode_scan_part_net.imageset/qrcode_scan_part_net.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/qrcode_scan_titlebar_back_nor.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "qrcode_scan_titlebar_back_nor@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/qrcode_scan_titlebar_back_nor.imageset/qrcode_scan_titlebar_back_nor@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/example/ios/Runner/Assets.xcassets/qrcode_scan_titlebar_back_nor.imageset/qrcode_scan_titlebar_back_nor@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/qrcode_scan_titlebar_back_pressed.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "qrcode_scan_titlebar_back_pressed@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/qrcode_scan_titlebar_back_pressed.imageset/qrcode_scan_titlebar_back_pressed@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/example/ios/Runner/Assets.xcassets/qrcode_scan_titlebar_back_pressed.imageset/qrcode_scan_titlebar_back_pressed@2x.png -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /example/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSMicrophoneUsageDescription 6 | 需要使用您的录音设备进行视频录制 7 | NSPhotoLibraryUsageDescription 8 | 此功能需要调用您的图库 9 | NSCameraUsageDescription 10 | 此功能需要访问你的相机 11 | CFBundleDevelopmentRegion 12 | en 13 | CFBundleExecutable 14 | $(EXECUTABLE_NAME) 15 | CFBundleIdentifier 16 | $(PRODUCT_BUNDLE_IDENTIFIER) 17 | CFBundleInfoDictionaryVersion 18 | 6.0 19 | CFBundleName 20 | flutter_sys_call_example 21 | CFBundlePackageType 22 | APPL 23 | CFBundleShortVersionString 24 | $(FLUTTER_BUILD_NAME) 25 | CFBundleSignature 26 | ???? 27 | CFBundleVersion 28 | $(FLUTTER_BUILD_NUMBER) 29 | LSRequiresIPhoneOS 30 | 31 | UILaunchStoryboardName 32 | LaunchScreen 33 | UIMainStoryboardFile 34 | Main 35 | UISupportedInterfaceOrientations 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationLandscapeLeft 39 | UIInterfaceOrientationLandscapeRight 40 | 41 | UISupportedInterfaceOrientations~ipad 42 | 43 | UIInterfaceOrientationPortrait 44 | UIInterfaceOrientationPortraitUpsideDown 45 | UIInterfaceOrientationLandscapeLeft 46 | UIInterfaceOrientationLandscapeRight 47 | 48 | UIViewControllerBasedStatusBarAppearance 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /example/ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" -------------------------------------------------------------------------------- /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_sys_call/flutter_sys_call.dart'; 6 | import 'main_page.dart'; 7 | import 'preview_video_page.dart'; 8 | 9 | void main() => runApp(MyApp()); 10 | 11 | class MyApp extends StatefulWidget { 12 | @override 13 | _MyAppState createState() => _MyAppState(); 14 | } 15 | 16 | class _MyAppState extends State { 17 | String _platformVersion = 'Unknown'; 18 | 19 | @override 20 | void initState() { 21 | super.initState(); 22 | initPlatformState(); 23 | } 24 | 25 | // Platform messages are asynchronous, so we initialize in an async method. 26 | Future initPlatformState() async { 27 | String platformVersion; 28 | // Platform messages may fail, so we use a try/catch PlatformException. 29 | try { 30 | platformVersion = await FlutterSysCall.platformVersion; 31 | } on PlatformException { 32 | platformVersion = 'Failed to get platform version.'; 33 | } 34 | 35 | // If the widget was removed from the tree while the asynchronous platform 36 | // message was in flight, we want to discard the reply rather than calling 37 | // setState to update our non-existent appearance. 38 | if (!mounted) return; 39 | 40 | setState(() { 41 | _platformVersion = platformVersion; 42 | }); 43 | } 44 | 45 | @override 46 | Widget build(BuildContext context) { 47 | return MaterialApp(home: MainPage()); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /example/lib/main_page.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter_sys_call/flutter_sys_call.dart'; 5 | import 'preview_video_page.dart'; 6 | import 'package:path_provider/path_provider.dart'; 7 | 8 | class MainPage extends StatefulWidget { 9 | @override 10 | State createState() { 11 | return MainStat(); 12 | } 13 | } 14 | 15 | class MainStat extends State { 16 | @override 17 | Widget build(BuildContext context) { 18 | return Scaffold( 19 | appBar: AppBar( 20 | title: const Text('Plugin example app'), 21 | ), 22 | body: Center( 23 | child: Column( 24 | children: [ 25 | RaisedButton( 26 | onPressed: () { 27 | doVibrator(); 28 | }, 29 | child: Text("震动"), 30 | ), 31 | RaisedButton( 32 | onPressed: () { 33 | takePhotoOrVideo(context); 34 | }, 35 | child: Text("拍视频"), 36 | ), 37 | RaisedButton( 38 | onPressed: () { 39 | qrScan(); 40 | }, 41 | child: Text("扫描二维码"), 42 | ), 43 | ], 44 | )), 45 | ); 46 | } 47 | 48 | ///调用震动 49 | doVibrator() async { 50 | await FlutterSysCall.doVibrator; 51 | } 52 | 53 | ///调用视频录像 54 | takePhotoOrVideo(BuildContext context) async { 55 | Map path = await FlutterSysCall.doTakeVideo; 56 | print(path); 57 | 58 | if (path["fileType"].isNotEmpty) { 59 | if (path["fileType"] == "image") { 60 | print("这是一张图片" + path["filePath"]); 61 | } else { 62 | print("这是视频"); 63 | Navigator.push( 64 | context, 65 | MaterialPageRoute( 66 | builder: (context) => PreviewVideoPage( 67 | path["filePath"].replaceAll(RegExp("file://"), "")))); 68 | } 69 | } else { 70 | print("可能已经拒绝了权限的分配"); 71 | } 72 | 73 | print(path); 74 | } 75 | 76 | ///调用二维码扫一扫 77 | qrScan() async { 78 | String result = await FlutterSysCall.qrScan; 79 | print(result); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /example/lib/preview_video_page.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:video_player/video_player.dart'; 5 | 6 | class PreviewVideoPage extends StatefulWidget { 7 | PreviewVideoPage(this.path, {Key key}) : super(key: key); 8 | 9 | String path; 10 | 11 | @override 12 | State createState() { 13 | return PreviewVideoState(); 14 | } 15 | } 16 | 17 | class PreviewVideoState extends State { 18 | ///视频控制器 19 | VideoPlayerController _controller; 20 | 21 | bool isLoading = true; 22 | 23 | @override 24 | void initState() { 25 | super.initState(); 26 | 27 | _controller = VideoPlayerController.file(File(widget.path)) 28 | ..initialize().then((da) { 29 | _controller.play(); 30 | isLoading = false; 31 | setState(() {}); 32 | }); 33 | } 34 | 35 | @override 36 | Widget build(BuildContext context) { 37 | return Scaffold( 38 | body: Container( 39 | color: Colors.black, 40 | child: Stack( 41 | children: [ 42 | Center( 43 | child: _controller.value.initialized 44 | ? AspectRatio( 45 | aspectRatio: _controller.value.aspectRatio, 46 | child: VideoPlayer(_controller), 47 | ) 48 | : Container(), 49 | ), 50 | Center( 51 | child: Offstage( 52 | offstage: _controller.value.isPlaying, 53 | child: FloatingActionButton( 54 | onPressed: () { 55 | setState(() { 56 | _controller.value.isPlaying 57 | ? _controller.pause() 58 | : _controller.play(); 59 | }); 60 | }, 61 | child: isLoading 62 | ? Text("加载中") 63 | : _controller.value.isPlaying 64 | ? Container() 65 | : IconButton( 66 | icon: Icon(Icons.play_arrow), 67 | onPressed: () { 68 | _controller.play(); 69 | })), 70 | )), 71 | ConstrainedBox( 72 | constraints: BoxConstraints( 73 | maxHeight: kToolbarHeight + MediaQuery.of(context).padding.top), 74 | child: AppBar( 75 | backgroundColor: Colors.transparent, 76 | ), 77 | ) 78 | ], 79 | ), 80 | )); 81 | } 82 | 83 | @override 84 | void dispose() { 85 | _controller.dispose(); 86 | super.dispose(); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flutter_sys_call_example 2 | description: Demonstrates how to use the flutter_sys_call plugin. 3 | publish_to: 'none' 4 | 5 | environment: 6 | sdk: ">=2.1.0 <3.0.0" 7 | 8 | dependencies: 9 | flutter: 10 | sdk: flutter 11 | 12 | # The following adds the Cupertino Icons font to your application. 13 | # Use with the CupertinoIcons class for iOS style icons. 14 | cupertino_icons: ^0.1.2 15 | #视频预览 16 | path_provider: ^0.5.0+1 17 | video_player: ^0.10.2 18 | 19 | 20 | dev_dependencies: 21 | flutter_test: 22 | sdk: flutter 23 | flutter_sys_call: 24 | path: ../ 25 | 26 | 27 | # For information on the generic Dart part of this file, see the 28 | # following page: https://www.dartlang.org/tools/pub/pubspec 29 | 30 | # The following section is specific to Flutter. 31 | flutter: 32 | 33 | # The following line ensures that the Material Icons font is 34 | # included with your application, so that you can use the icons in 35 | # the material Icons class. 36 | uses-material-design: true 37 | 38 | # To add assets to your application, add an assets section, like this: 39 | # assets: 40 | # - images/a_dot_burr.jpeg 41 | # - images/a_dot_ham.jpeg 42 | 43 | # An image asset can refer to one or more resolution-specific "variants", see 44 | # https://flutter.io/assets-and-images/#resolution-aware. 45 | 46 | # For details regarding adding assets from package dependencies, see 47 | # https://flutter.io/assets-and-images/#from-packages 48 | 49 | # To add custom fonts to your application, add a fonts section here, 50 | # in this "flutter" section. Each entry in this list should have a 51 | # "family" key with the font family name, and a "fonts" key with a 52 | # list giving the asset and other descriptors for the font. For 53 | # example: 54 | # fonts: 55 | # - family: Schyler 56 | # fonts: 57 | # - asset: fonts/Schyler-Regular.ttf 58 | # - asset: fonts/Schyler-Italic.ttf 59 | # style: italic 60 | # - family: Trajan Pro 61 | # fonts: 62 | # - asset: fonts/TrajanPro.ttf 63 | # - asset: fonts/TrajanPro_Bold.ttf 64 | # weight: 700 65 | # 66 | # For details regarding fonts from package dependencies, 67 | # see https://flutter.io/custom-fonts/#from-packages 68 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /ios/Assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/ios/Assets/.gitkeep -------------------------------------------------------------------------------- /ios/Classes/FlutterSysCallPlugin.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | @interface FlutterSysCallPlugin : NSObject 5 | @end 6 | -------------------------------------------------------------------------------- /ios/Classes/FlutterSysCallPlugin.m: -------------------------------------------------------------------------------- 1 | #import "FlutterSysCallPlugin.h" 2 | 3 | #import 4 | 5 | 6 | @implementation FlutterSysCallPlugin 7 | + (void)registerWithRegistrar:(NSObject*)registrar { 8 | [SwiftFlutterSysCallPlugin registerWithRegistrar:registrar]; 9 | } 10 | @end 11 | -------------------------------------------------------------------------------- /ios/Classes/QQScanViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // QQScanViewController.swift 3 | // flutter_sys_call 4 | // 5 | // Created by 华轩 on 2019/6/6. 6 | // 7 | 8 | import Foundation 9 | // 10 | // QQScanViewController.swift 11 | // swiftScan 12 | // 13 | // Created by xialibing on 15/12/10. 14 | // Copyright © 2015年 xialibing. All rights reserved. 15 | // 16 | import UIKit 17 | import swiftScan 18 | 19 | 20 | typealias QBcode = (String) ->() 21 | 22 | 23 | class QQScanViewController: LBXScanViewController { 24 | 25 | var code="" 26 | 27 | /** 28 | @brief 扫码区域上方提示文字 29 | */ 30 | var topTitle: UILabel? 31 | 32 | /** 33 | @brief 闪关灯开启状态 34 | */ 35 | var isOpenedFlash: Bool = false 36 | 37 | // MARK: - 底部几个功能:开启闪光灯、相册、返回 38 | //底部显示的功能项 39 | var bottomItemsView: UIView? 40 | 41 | //相册 42 | var btnPhoto: UIButton = UIButton() 43 | 44 | //闪光灯 45 | var btnFlash: UIButton = UIButton() 46 | 47 | //我的二维码 48 | var btnMyQR: UIButton = UIButton() 49 | 50 | var qbCode: QBcode? 51 | 52 | // 或者使用实例方法调用(方法名字不固定,但参数是必须的) 53 | open func setMyChangeName(tempClose: @escaping QBcode) { 54 | self.qbCode = tempClose 55 | } 56 | 57 | override func viewDidLoad() { 58 | 59 | super.viewDidLoad() 60 | 61 | //需要识别后的图像 62 | setNeedCodeImage(needCodeImg: true) 63 | 64 | //框向上移动10个像素 65 | scanStyle?.centerUpOffset += 10 66 | 67 | // Do any additional setup after loading the view. 68 | } 69 | 70 | override func viewDidAppear(_ animated: Bool) { 71 | 72 | super.viewDidAppear(animated) 73 | 74 | drawBottomItems() 75 | } 76 | 77 | override func handleCodeResult(arrayResult: [LBXScanResult]) { 78 | 79 | for result: LBXScanResult in arrayResult { 80 | if let str = result.strScanned { 81 | print("扫码结果"+str) 82 | } 83 | } 84 | 85 | let result: LBXScanResult = arrayResult[0] 86 | 87 | self.dismiss(animated: true) { 88 | self.qbCode!(result.strScanned!); 89 | } 90 | 91 | } 92 | 93 | func drawBottomItems() { 94 | if (bottomItemsView != nil) { 95 | 96 | return 97 | } 98 | 99 | let yMax = self.view.frame.maxY - self.view.frame.minY 100 | 101 | bottomItemsView = UIView(frame: CGRect(x: 0.0, y: yMax-100, width: self.view.frame.size.width, height: 100 ) ) 102 | 103 | bottomItemsView!.backgroundColor = UIColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 0.6) 104 | 105 | self.view .addSubview(bottomItemsView!) 106 | 107 | let size = CGSize(width: 65, height: 87) 108 | 109 | self.btnFlash = UIButton() 110 | btnFlash.bounds = CGRect(x: 0, y: 0, width: size.width, height: size.height) 111 | btnFlash.center = CGPoint(x: bottomItemsView!.frame.width/2, y: bottomItemsView!.frame.height/2) 112 | 113 | btnFlash.setImage(UIImage(named: "qrcode_scan_btn_flash_nor"), for:UIControl.State.normal) 114 | btnFlash.addTarget(self, action: #selector(QQScanViewController.openOrCloseFlash), for: UIControl.Event.touchUpInside) 115 | 116 | 117 | self.btnPhoto = UIButton() 118 | btnPhoto.bounds = btnFlash.bounds 119 | btnPhoto.center = CGPoint(x: bottomItemsView!.frame.width/4, y: bottomItemsView!.frame.height/2) 120 | btnPhoto.setImage(UIImage(named: "qrcode_scan_btn_photo_nor"), for: UIControl.State.normal) 121 | btnPhoto.setImage(UIImage(named: "qrcode_scan_btn_photo_down"), for: UIControl.State.highlighted) 122 | // btnPhoto.addTarget(self, action: Selector(("openPhotoAlbum")), for: UIControlEvents.touchUpInside) 123 | btnPhoto.addTarget(self, action: #selector(QQScanViewController.openLocalPhotoAlbum), for: UIControl.Event.touchUpInside) 124 | 125 | self.btnMyQR = UIButton() 126 | btnMyQR.bounds = btnFlash.bounds; 127 | btnMyQR.center = CGPoint(x: bottomItemsView!.frame.width * 3/4, y: bottomItemsView!.frame.height/2); 128 | btnMyQR.setImage(UIImage(named: "back_nor"), for: UIControl.State.normal) 129 | btnMyQR.setImage(UIImage(named: "back_pressed"), for: UIControl.State.highlighted) 130 | btnMyQR.addTarget(self, action: #selector(QQScanViewController.myCode), for: UIControl.Event.touchUpInside) 131 | 132 | bottomItemsView?.addSubview(btnPhoto) 133 | bottomItemsView?.addSubview(btnFlash) 134 | bottomItemsView?.addSubview(btnMyQR) 135 | 136 | self.view .addSubview(bottomItemsView!) 137 | self.startScan(); 138 | 139 | } 140 | 141 | @objc func openLocalPhotoAlbum() 142 | { 143 | super.openPhotoAlbum(); 144 | } 145 | 146 | //开关闪光灯 147 | @objc func openOrCloseFlash() { 148 | scanObj?.changeTorch() 149 | 150 | isOpenedFlash = !isOpenedFlash 151 | 152 | if isOpenedFlash 153 | { 154 | btnFlash.setImage(UIImage(named: "qrcode_scan_btn_flash_down"), for:UIControl.State.normal) 155 | } 156 | else 157 | { 158 | btnFlash.setImage(UIImage(named: "qrcode_scan_btn_flash_nor"), for:UIControl.State.normal) 159 | 160 | } 161 | } 162 | 163 | @objc func myCode() { 164 | qbCode!("") 165 | self.dismiss(animated: true, completion: nil) 166 | } 167 | 168 | } 169 | -------------------------------------------------------------------------------- /ios/Classes/SwiftFlutterSysCallPlugin.swift: -------------------------------------------------------------------------------- 1 | import Flutter 2 | import UIKit 3 | import AudioToolbox 4 | import MACamera 5 | import swiftScan 6 | 7 | public class SwiftFlutterSysCallPlugin: NSObject, FlutterPlugin { 8 | var controller: FlutterViewController! 9 | var flutterResult:FlutterResult!; 10 | var messenger: FlutterBinaryMessenger; 11 | var timer:Timer!; 12 | var second=3; 13 | 14 | 15 | init(cont: FlutterViewController, messenger: FlutterBinaryMessenger) { 16 | self.controller = cont; 17 | self.messenger = messenger; 18 | super.init(); 19 | } 20 | 21 | public static func register(with registrar: FlutterPluginRegistrar) { 22 | 23 | let channel = FlutterMethodChannel(name: "flutter_sys_call", binaryMessenger: registrar.messenger()) 24 | let app = UIApplication.shared; 25 | let controller : FlutterViewController = app.delegate!.window!!.rootViewController as! FlutterViewController; 26 | let instance = SwiftFlutterSysCallPlugin.init(cont: controller, messenger: registrar.messenger()) 27 | registrar.addMethodCallDelegate(instance, channel: channel) 28 | } 29 | 30 | public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { 31 | flutterResult=result; 32 | switch call.method { 33 | case "getPlatformVersion": 34 | result("iOS " + UIDevice.current.systemVersion); 35 | break; 36 | case "doVibrator": 37 | if(timer==nil){ 38 | timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(updataSecond), userInfo: nil, repeats: true) 39 | //调用fire()会立即启动计时器 40 | timer!.fire() 41 | } 42 | 43 | 44 | break; 45 | case "recordVideo": 46 | showCameras(); 47 | break; 48 | case "QRScan": 49 | showScanView(); 50 | break; 51 | default: 52 | result(true); 53 | } 54 | } 55 | 56 | //定时震动 57 | @objc func updataSecond() { 58 | if second>1 { 59 | AudioServicesPlaySystemSound(kSystemSoundID_Vibrate); 60 | second -= 1 61 | }else { 62 | //取消定时任务 63 | second=3 64 | timer.invalidate() 65 | timer=nil 66 | 67 | } 68 | } 69 | 70 | //显示摄像头 71 | 72 | func showCameras(){ 73 | 74 | 75 | MACameraController.allowCameraAndPhoto { (allow) in 76 | let mController=MACameraController.init() 77 | mController.cameraCompletion={(mController,usn,image,krk) -> () in 78 | 79 | mController?.dismiss(animated: true, completion: nil) 80 | 81 | if(krk){ 82 | self.flutterResult(usn!.path); 83 | }else{ 84 | 85 | if(image==nil){ 86 | self.showCameras(); 87 | return; 88 | } 89 | 90 | //要写入的文件夹路径和图片名 91 | let dt:String = NSTemporaryDirectory().appending("seer.png") as String; 92 | 93 | //将Image文件写入 如上的文件夹 94 | try? UIImagePNGRepresentation(image!)?.write(to: URL(fileURLWithPath: dt)) 95 | 96 | self.flutterResult(dt) 97 | 98 | } 99 | 100 | 101 | } 102 | 103 | 104 | self.controller.present(mController, animated: true, completion:nil) 105 | } 106 | } 107 | 108 | 109 | func showScanView(){ 110 | let vc = QQScanViewController() 111 | vc.setMyChangeName{ 112 | (qbCode) in 113 | self.flutterResult(qbCode) 114 | } 115 | var style = LBXScanViewStyle() 116 | style.animationImage = UIImage(named: "qrcode_scan_light_green") 117 | vc.scanStyle = style 118 | controller.present(vc, animated: true, completion: nil) 119 | } 120 | } 121 | 122 | class Url { 123 | var url = ""; 124 | 125 | } 126 | -------------------------------------------------------------------------------- /ios/Classes/swiftScan.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'swiftScan' 3 | s.version = '1.1.5' 4 | s.summary = 'ios swift scan wrapper' 5 | s.homepage = 'https://github.com/MxABC/swiftScan' 6 | s.license = 'MIT' 7 | s.authors = {'MxABC' => 'lbxia20091227@foxmail.com'} 8 | s.platform = :ios, '8.0' 9 | s.source = {:git => 'https://github.com/MxABC/swiftScan.git', :tag => s.version} 10 | s.ios.deployment_target = "8.0" 11 | s.source_files = 'Source/*.swift' 12 | end 13 | -------------------------------------------------------------------------------- /ios/flutter_sys_call.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html 3 | # 4 | Pod::Spec.new do |s| 5 | s.name = 'flutter_sys_call' 6 | s.version = '0.0.1' 7 | s.summary = 'A new Flutter plugin.' 8 | s.description = <<-DESC 9 | A new Flutter plugin. 10 | DESC 11 | s.homepage = 'http://example.com' 12 | s.license = { :file => '../LICENSE' } 13 | s.author = { 'Your Company' => 'email@example.com' } 14 | s.source = { :path => '.' } 15 | s.source_files = 'Classes/**/*' 16 | s.public_header_files = 'Classes/**/*.h' 17 | s.dependency 'Flutter' 18 | s.dependency 'MACamera' 19 | s.dependency 'swiftScan', '~> 1.1.2' 20 | s.ios.deployment_target = '8.0' 21 | end 22 | 23 | -------------------------------------------------------------------------------- /lib/flutter_sys_call.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:io'; 3 | import 'package:flutter/services.dart'; 4 | 5 | import 'package:permission_handler/permission_handler.dart'; 6 | import 'package:path_provider/path_provider.dart'; 7 | 8 | class FlutterSysCall { 9 | static const MethodChannel _channel = const MethodChannel('flutter_sys_call'); 10 | 11 | static Future get platformVersion async { 12 | final String version = await _channel.invokeMethod('getPlatformVersion'); 13 | return version; 14 | } 15 | 16 | static Future get doVibrator async { 17 | final bool result = await _channel.invokeMethod('doVibrator'); 18 | return result; 19 | } 20 | 21 | static Future> get doTakeVideo async { 22 | bool isPermission = await requestPermission(Platform.isAndroid 23 | ? [Permission.camera, Permission.microphone, Permission.storage] 24 | : [Permission.camera, Permission.microphone, Permission.photos]); 25 | if (isPermission) { 26 | String result = await _channel.invokeMethod('recordVideo'); 27 | 28 | String path = (await getApplicationDocumentsDirectory()).path; 29 | String fileEnd = result.substring(result.length - 3, result.length); 30 | print(fileEnd); 31 | String fileType; 32 | 33 | if (fileEnd == "jpg" || fileEnd == "png") { 34 | if (Platform.isIOS) { 35 | result = (await File(result).rename(path + "/temp." + fileEnd)).path; 36 | } 37 | fileType = "image"; 38 | } else { 39 | if (Platform.isIOS) { 40 | result = (await File(result).rename(path + "/temp." + fileEnd)).path; 41 | } 42 | fileType = "video"; 43 | } 44 | 45 | return {"fileType": fileType, "filePath": result}; 46 | } else { 47 | return {"fileType": "", "filePath": ""}; 48 | } 49 | } 50 | 51 | static Future get qrScan async { 52 | bool isPermission = await requestPermission([ 53 | Permission.camera, 54 | ]); 55 | if (isPermission) { 56 | final String result = await _channel.invokeMethod('QRScan'); 57 | return result; 58 | } else { 59 | return "0"; 60 | } 61 | } 62 | 63 | ///请求权限 64 | static Future requestPermission( 65 | List permissionsList) async { 66 | var flag = true; 67 | Map permissions = 68 | await await [ 69 | Permission.storage, 70 | Permission.camera 71 | ].request(); 72 | permissions.forEach((Permission pg, PermissionStatus status) { 73 | if (status != PermissionStatus.granted) { 74 | flag = false; 75 | } 76 | }); 77 | 78 | return flag; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /lib/kotlin-reflect-sources.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/lib/kotlin-reflect-sources.jar -------------------------------------------------------------------------------- /lib/kotlin-reflect.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/lib/kotlin-reflect.jar -------------------------------------------------------------------------------- /lib/kotlin-stdlib-jdk7-sources.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/lib/kotlin-stdlib-jdk7-sources.jar -------------------------------------------------------------------------------- /lib/kotlin-stdlib-jdk7.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/lib/kotlin-stdlib-jdk7.jar -------------------------------------------------------------------------------- /lib/kotlin-stdlib-jdk8-sources.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/lib/kotlin-stdlib-jdk8-sources.jar -------------------------------------------------------------------------------- /lib/kotlin-stdlib-jdk8.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/lib/kotlin-stdlib-jdk8.jar -------------------------------------------------------------------------------- /lib/kotlin-stdlib-sources.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/lib/kotlin-stdlib-sources.jar -------------------------------------------------------------------------------- /lib/kotlin-stdlib.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/lib/kotlin-stdlib.jar -------------------------------------------------------------------------------- /lib/kotlin-test-sources.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/lib/kotlin-test-sources.jar -------------------------------------------------------------------------------- /lib/kotlin-test.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YHX520/flutter_sys_call/68ee3bbc34f11fa48515f9beb04eb541260b42fd/lib/kotlin-test.jar -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flutter_sys_call 2 | description: 一个用来调用系统小功能的插件,目前包括震动,视频录制,二维码识别 3 | version: 1.0.1 4 | author: "yhx <646903573@qq.com>" 5 | homepage: "https://github.com/YHX520/flutter_sys_call" 6 | 7 | environment: 8 | sdk: ">=2.1.0 <3.0.0" 9 | 10 | dependencies: 11 | flutter: 12 | sdk: flutter 13 | permission_handler: ^5.0.1+1 14 | 15 | path_provider: ^1.6.11 16 | 17 | dev_dependencies: 18 | flutter_test: 19 | sdk: flutter 20 | 21 | # For information on the generic Dart part of this file, see the 22 | # following page: https://www.dartlang.org/tools/pub/pubspec 23 | 24 | # The following section is specific to Flutter. 25 | flutter: 26 | # This section identifies this Flutter project as a plugin project. 27 | # The androidPackage and pluginClass identifiers should not ordinarily 28 | # be modified. They are used by the tooling to maintain consistency when 29 | # adding or updating assets for this project. 30 | plugin: 31 | androidPackage: syscall.zixuan.com.flutter_sys_call 32 | pluginClass: FlutterSysCallPlugin 33 | 34 | # To add assets to your plugin package, add an assets section, like this: 35 | # assets: 36 | # - images/a_dot_burr.jpeg 37 | # - images/a_dot_ham.jpeg 38 | # 39 | # For details regarding assets in packages, see 40 | # https://flutter.io/assets-and-images/#from-packages 41 | # 42 | # An image asset can refer to one or more resolution-specific "variants", see 43 | # https://flutter.io/assets-and-images/#resolution-aware. 44 | 45 | # To add custom fonts to your plugin package, add a fonts section here, 46 | # in this "flutter" section. Each entry in this list should have a 47 | # "family" key with the font family name, and a "fonts" key with a 48 | # list giving the asset and other descriptors for the font. For 49 | # example: 50 | # fonts: 51 | # - family: Schyler 52 | # fonts: 53 | # - asset: fonts/Schyler-Regular.ttf 54 | # - asset: fonts/Schyler-Italic.ttf 55 | # style: italic 56 | # - family: Trajan Pro 57 | # fonts: 58 | # - asset: fonts/TrajanPro.ttf 59 | # - asset: fonts/TrajanPro_Bold.ttf 60 | # weight: 700 61 | # 62 | # For details regarding fonts in packages, see 63 | # https://flutter.io/custom-fonts/#from-packages 64 | --------------------------------------------------------------------------------