├── .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