Toggle navigation
Toggle navigation
This project
Loading...
Sign in
flutter_package
/
mobile_scanner
Go to a project
Toggle navigation
Projects
Groups
Snippets
Help
Toggle navigation pinning
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Builds
Commits
Authored by
Julian Steenbakker
2022-04-26 12:29:02 +0200
Browse Files
Options
Browse Files
Download
Plain Diff
Committed by
GitHub
2022-04-26 12:29:02 +0200
Commit
325d3932c305d88eab494b1578a9a73f287aed98
325d3932
2 parents
dbec3812
c0fbb46b
Merge pull request #110 from juliansteenbakker/lint
Apply flutter lint
Show whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
273 additions
and
240 deletions
README.md
analysis_options.yaml
example/analysis_options.yaml
example/ios/Runner.xcodeproj/project.pbxproj
example/lib/barcode_scanner_controller.dart
example/lib/barcode_scanner_without_controller.dart
example/lib/main.dart
example/pubspec.yaml
lib/mobile_scanner.dart
lib/mobile_scanner_web_plugin.dart
lib/src/mobile_scanner.dart
lib/src/mobile_scanner_arguments.dart
lib/src/mobile_scanner_controller.dart
lib/src/objects/barcode.dart
lib/src/objects/barcode_utility.dart
lib/src/web/jsqr.dart
lib/src/web/media.dart
lib/src/web/qr_scanner.dart
pubspec.yaml
README.md
View file @
325d393
# mobile_scanner
[

](https://pub.dev/packages/mobile_scanner)
[

](https://pub.dev/packages/lint)
[

](https://github.com/juliansteenbakker/mobile_scanner/actions/workflows/flutter.yml)
[

](https://github.com/sponsors/juliansteenbakker)
...
...
analysis_options.yaml
View file @
325d393
include
:
package:flutter_lints/flutter.yaml
linter
:
rules
:
unawaited_futures
:
true
\ No newline at end of file
include
:
package:lint/analysis_options_package.yaml
\ No newline at end of file
...
...
example/analysis_options.yaml
View file @
325d393
# This file configures the analyzer, which statically analyzes Dart code to
# check for errors, warnings, and lints.
#
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
# invoked from the command line by running `flutter analyze`.
# The following line activates a set of recommended lints for Flutter apps,
# packages, and plugins designed to encourage good coding practices.
include
:
package:flutter_lints/flutter.yaml
linter
:
# The lint rules applied to this project can be customized in the
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
# included above or to enable additional rules. A list of all available lints
# and their documentation is published at
# https://dart-lang.github.io/linter/lints/index.html.
#
# Instead of disabling a lint rule for the entire project in the
# section below, it can also be suppressed for a single line of code
# or a specific dart file by using the `// ignore: name_of_lint` and
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
# producing the lint.
rules
:
# avoid_print: false # Uncomment to disable the `avoid_print` rule
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options
include
:
package:lint/analysis_options.yaml
\ No newline at end of file
...
...
example/ios/Runner.xcodeproj/project.pbxproj
View file @
325d393
...
...
@@ -355,7 +355,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM =
75Y2P2WSQQ
;
DEVELOPMENT_TEAM =
3K8Q7WKS3W
;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
...
...
@@ -484,7 +484,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM =
75Y2P2WSQQ
;
DEVELOPMENT_TEAM =
3K8Q7WKS3W
;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
...
...
@@ -507,7 +507,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM =
75Y2P2WSQQ
;
DEVELOPMENT_TEAM =
3K8Q7WKS3W
;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
...
...
example/lib/barcode_scanner_controller.dart
View file @
325d393
...
...
@@ -27,7 +27,8 @@ class _BarcodeScannerWithControllerState
Widget
build
(
BuildContext
context
)
{
return
Scaffold
(
backgroundColor:
Colors
.
black
,
body:
Builder
(
builder:
(
context
)
{
body:
Builder
(
builder:
(
context
)
{
return
Stack
(
children:
[
MobileScanner
(
...
...
@@ -42,7 +43,8 @@ class _BarcodeScannerWithControllerState
setState
(()
{
this
.
barcode
=
barcode
.
rawValue
;
});
}),
},
),
Align
(
alignment:
Alignment
.
bottomCenter
,
child:
Container
(
...
...
@@ -50,7 +52,6 @@ class _BarcodeScannerWithControllerState
height:
100
,
color:
Colors
.
black
.
withOpacity
(
0.4
),
child:
Row
(
crossAxisAlignment:
CrossAxisAlignment
.
center
,
mainAxisAlignment:
MainAxisAlignment
.
spaceEvenly
,
children:
[
IconButton
(
...
...
@@ -58,13 +59,23 @@ class _BarcodeScannerWithControllerState
icon:
ValueListenableBuilder
(
valueListenable:
controller
.
torchState
,
builder:
(
context
,
state
,
child
)
{
if
(
state
==
null
)
{
return
const
Icon
(
Icons
.
flash_off
,
color:
Colors
.
grey
,
);
}
switch
(
state
as
TorchState
)
{
case
TorchState
.
off
:
return
const
Icon
(
Icons
.
flash_off
,
color:
Colors
.
grey
);
return
const
Icon
(
Icons
.
flash_off
,
color:
Colors
.
grey
,
);
case
TorchState
.
on
:
return
const
Icon
(
Icons
.
flash_on
,
color:
Colors
.
yellow
);
return
const
Icon
(
Icons
.
flash_on
,
color:
Colors
.
yellow
,
);
}
},
),
...
...
@@ -78,11 +89,10 @@ class _BarcodeScannerWithControllerState
:
const
Icon
(
Icons
.
play_arrow
),
iconSize:
32.0
,
onPressed:
()
=>
setState
(()
{
isStarted
?
controller
.
stop
()
:
controller
.
start
();
isStarted
?
controller
.
stop
()
:
controller
.
start
();
isStarted
=
!
isStarted
;
})),
}),
),
Center
(
child:
SizedBox
(
width:
MediaQuery
.
of
(
context
).
size
.
width
-
200
,
...
...
@@ -104,6 +114,9 @@ class _BarcodeScannerWithControllerState
icon:
ValueListenableBuilder
(
valueListenable:
controller
.
cameraFacingState
,
builder:
(
context
,
state
,
child
)
{
if
(
state
==
null
)
{
return
const
Icon
(
Icons
.
camera_front
);
}
switch
(
state
as
CameraFacing
)
{
case
CameraFacing
.
front
:
return
const
Icon
(
Icons
.
camera_front
);
...
...
@@ -123,20 +136,25 @@ class _BarcodeScannerWithControllerState
final
ImagePicker
_picker
=
ImagePicker
();
// Pick an image
final
XFile
?
image
=
await
_picker
.
pickImage
(
source
:
ImageSource
.
gallery
);
source
:
ImageSource
.
gallery
,
);
if
(
image
!=
null
)
{
if
(
await
controller
.
analyzeImage
(
image
.
path
))
{
ScaffoldMessenger
.
of
(
context
)
.
showSnackBar
(
const
SnackBar
(
if
(!
mounted
)
return
;
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
const
SnackBar
(
content:
Text
(
'Barcode found!'
),
backgroundColor:
Colors
.
green
,
));
),
);
}
else
{
ScaffoldMessenger
.
of
(
context
)
.
showSnackBar
(
const
SnackBar
(
if
(!
mounted
)
return
;
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
const
SnackBar
(
content:
Text
(
'No barcode found!'
),
backgroundColor:
Colors
.
red
,
));
),
);
}
}
},
...
...
@@ -147,7 +165,8 @@ class _BarcodeScannerWithControllerState
),
],
);
}),
},
),
);
}
}
...
...
example/lib/barcode_scanner_without_controller.dart
View file @
325d393
...
...
@@ -18,7 +18,8 @@ class _BarcodeScannerWithoutControllerState
Widget
build
(
BuildContext
context
)
{
return
Scaffold
(
backgroundColor:
Colors
.
black
,
body:
Builder
(
builder:
(
context
)
{
body:
Builder
(
builder:
(
context
)
{
return
Stack
(
children:
[
MobileScanner
(
...
...
@@ -28,7 +29,8 @@ class _BarcodeScannerWithoutControllerState
setState
(()
{
this
.
barcode
=
barcode
.
rawValue
;
});
}),
},
),
Align
(
alignment:
Alignment
.
bottomCenter
,
child:
Container
(
...
...
@@ -36,7 +38,6 @@ class _BarcodeScannerWithoutControllerState
height:
100
,
color:
Colors
.
black
.
withOpacity
(
0.4
),
child:
Row
(
crossAxisAlignment:
CrossAxisAlignment
.
center
,
mainAxisAlignment:
MainAxisAlignment
.
spaceEvenly
,
children:
[
Center
(
...
...
@@ -61,7 +62,8 @@ class _BarcodeScannerWithoutControllerState
),
],
);
}),
},
),
);
}
}
...
...
example/lib/main.dart
View file @
325d393
...
...
@@ -16,21 +16,25 @@ class MyHome extends StatelessWidget {
height:
MediaQuery
.
of
(
context
).
size
.
height
,
child:
Column
(
mainAxisAlignment:
MainAxisAlignment
.
center
,
crossAxisAlignment:
CrossAxisAlignment
.
center
,
children:
[
ElevatedButton
(
onPressed:
()
{
Navigator
.
of
(
context
).
push
(
MaterialPageRoute
(
Navigator
.
of
(
context
).
push
(
MaterialPageRoute
(
builder:
(
context
)
=>
const
BarcodeScannerWithController
(),
));
),
);
},
child:
const
Text
(
'MobileScanner with Controller'
),
),
ElevatedButton
(
onPressed:
()
{
Navigator
.
of
(
context
).
push
(
MaterialPageRoute
(
builder:
(
context
)
=>
const
BarcodeScannerWithoutController
(),
));
Navigator
.
of
(
context
).
push
(
MaterialPageRoute
(
builder:
(
context
)
=>
const
BarcodeScannerWithoutController
(),
),
);
},
child:
const
Text
(
'MobileScanner without Controller'
),
),
...
...
example/pubspec.yaml
View file @
325d393
...
...
@@ -6,9 +6,9 @@ environment:
sdk
:
"
>=2.12.0
<3.0.0"
dependencies
:
image_picker
:
^0.8.4+9
flutter
:
sdk
:
flutter
image_picker
:
^0.8.4+9
mobile_scanner
:
path
:
../
...
...
@@ -16,7 +16,7 @@ dependencies:
dev_dependencies
:
flutter_test
:
sdk
:
flutter
flutter_lints
:
^1.0.4
lint
:
^1.8.2
flutter
:
uses-material-design
:
true
...
...
lib/mobile_scanner.dart
View file @
325d393
library
mobile_scanner
;
export
'src/mobile_scanner.dart'
;
export
'src/mobile_scanner_controller.dart'
;
export
'src/mobile_scanner_arguments.dart'
;
export
'src/mobile_scanner_controller.dart'
;
export
'src/objects/barcode.dart'
;
...
...
lib/mobile_scanner_web_plugin.dart
View file @
325d393
import
'dart:async'
;
import
'dart:html'
as
html
;
import
'dart:ui'
as
ui
;
import
'package:flutter/material.dart'
;
import
'package:flutter/services.dart'
;
import
'package:flutter_web_plugins/flutter_web_plugins.dart'
;
import
'package:mobile_scanner/mobile_scanner.dart'
;
import
'package:mobile_scanner/src/web/jsqr.dart'
;
import
'dart:html'
as
html
;
import
'dart:ui'
as
ui
;
import
'package:mobile_scanner/src/web/media.dart'
;
/// This plugin is the web implementation of mobile_scanner.
/// It only supports QR codes.
class
MobileScannerWebPlugin
{
static
void
registerWith
(
Registrar
registrar
)
{
PluginEventChannel
event
=
PluginEventChannel
(
final
PluginEventChannel
event
=
PluginEventChannel
(
'dev.steenbakker.mobile_scanner/scanner/event'
,
const
StandardMethodCodec
(),
registrar
);
MethodChannel
channel
=
MethodChannel
(
registrar
,
);
final
MethodChannel
channel
=
MethodChannel
(
'dev.steenbakker.mobile_scanner/scanner/method'
,
const
StandardMethodCodec
(),
registrar
);
registrar
,
);
final
MobileScannerWebPlugin
instance
=
MobileScannerWebPlugin
();
WidgetsFlutterBinding
.
ensureInitialized
();
...
...
@@ -51,16 +52,17 @@ class MobileScannerWebPlugin {
Future
<
dynamic
>
handleMethodCall
(
MethodCall
call
)
async
{
switch
(
call
.
method
)
{
case
'start'
:
return
await
_start
(
call
.
arguments
);
return
_start
(
call
.
arguments
as
Map
);
case
'torch'
:
return
await
_torch
(
call
.
arguments
);
return
_torch
(
call
.
arguments
);
case
'stop'
:
return
await
cancel
();
return
cancel
();
default
:
throw
PlatformException
(
code:
'Unimplemented'
,
details:
"The mobile_scanner plugin for web doesn't implement "
"the method '
${call.method}
'"
);
"the method '
${call.method}
'"
,
);
}
}
...
...
@@ -77,21 +79,22 @@ class MobileScannerWebPlugin {
}
/// Starts the video stream and the scanner
Future
<
Map
>
_start
(
arguments
)
async
{
Future
<
Map
>
_start
(
Map
arguments
)
async
{
vidDiv
.
children
=
[
video
];
var
cameraFacing
=
CameraFacing
.
front
;
if
(
arguments
.
containsKey
(
'facing'
))
{
cameraFacing
=
CameraFacing
.
values
[
arguments
[
'facing'
]];
cameraFacing
=
CameraFacing
.
values
[
arguments
[
'facing'
]
as
int
];
}
// See https://github.com/flutter/flutter/issues/41563
// ignore: UNDEFINED_PREFIXED_NAME
// ignore: UNDEFINED_PREFIXED_NAME
, avoid_dynamic_calls
ui
.
platformViewRegistry
.
registerViewFactory
(
viewID
,
(
int
id
)
=>
vidDiv
..
style
.
width
=
'100%'
..
style
.
height
=
'100%'
);
..
style
.
height
=
'100%'
,
);
// Check if stream is running
if
(
_localStream
!=
null
)
{
...
...
@@ -104,13 +107,14 @@ class MobileScannerWebPlugin {
try
{
// Check if browser supports multiple camera's and set if supported
Map
?
capabilities
=
final
Map
?
capabilities
=
html
.
window
.
navigator
.
mediaDevices
?.
getSupportedConstraints
();
if
(
capabilities
!=
null
&&
capabilities
[
'facingMode'
])
{
var
constraints
=
{
if
(
capabilities
!=
null
&&
capabilities
[
'facingMode'
]
as
bool
)
{
final
constraints
=
{
'video'
:
VideoOptions
(
facingMode:
(
cameraFacing
==
CameraFacing
.
front
?
'user'
:
'environment'
))
cameraFacing
==
CameraFacing
.
front
?
'user'
:
'environment'
,
)
};
_localStream
=
...
...
@@ -156,6 +160,8 @@ class MobileScannerWebPlugin {
final
sources
=
await
html
.
window
.
navigator
.
mediaDevices
!.
enumerateDevices
();
for
(
final
e
in
sources
)
{
// TODO:
// ignore: avoid_dynamic_calls
if
(
e
.
kind
==
'videoinput'
)
{
return
true
;
}
...
...
lib/src/mobile_scanner.dart
View file @
325d393
...
...
@@ -28,13 +28,13 @@ class MobileScanner extends StatefulWidget {
final
bool
allowDuplicates
;
/// Create a [MobileScanner] with a [controller], the [controller] must has been initialized.
const
MobileScanner
(
{
Key
?
key
,
const
MobileScanner
({
Key
?
key
,
this
.
onDetect
,
this
.
controller
,
this
.
fit
=
BoxFit
.
cover
,
this
.
allowDuplicates
=
false
})
:
super
(
key:
key
);
this
.
allowDuplicates
=
false
,
})
:
super
(
key:
key
);
@override
State
<
MobileScanner
>
createState
()
=>
_MobileScannerState
();
...
...
@@ -69,7 +69,8 @@ class _MobileScannerState extends State<MobileScanner>
@override
Widget
build
(
BuildContext
context
)
{
return
LayoutBuilder
(
builder:
(
context
,
BoxConstraints
constraints
)
{
return
LayoutBuilder
(
builder:
(
context
,
BoxConstraints
constraints
)
{
return
ValueListenableBuilder
(
valueListenable:
controller
.
args
,
builder:
(
context
,
value
,
child
)
{
...
...
@@ -81,10 +82,10 @@ class _MobileScannerState extends State<MobileScanner>
if
(!
widget
.
allowDuplicates
)
{
if
(
lastScanned
!=
barcode
.
rawValue
)
{
lastScanned
=
barcode
.
rawValue
;
widget
.
onDetect
!(
barcode
,
value
as
MobileScannerArguments
);
widget
.
onDetect
!(
barcode
,
value
!
as
MobileScannerArguments
);
}
}
else
{
widget
.
onDetect
!(
barcode
,
value
as
MobileScannerArguments
);
widget
.
onDetect
!(
barcode
,
value
!
as
MobileScannerArguments
);
}
});
return
ClipRect
(
...
...
@@ -104,8 +105,10 @@ class _MobileScannerState extends State<MobileScanner>
),
);
}
});
});
},
);
},
);
}
@override
...
...
lib/src/mobile_scanner_arguments.dart
View file @
325d393
...
...
@@ -13,6 +13,10 @@ class MobileScannerArguments {
final
String
?
webId
;
/// Create a [MobileScannerArguments].
MobileScannerArguments
(
{
this
.
textureId
,
required
this
.
size
,
required
this
.
hasTorch
,
this
.
webId
});
MobileScannerArguments
({
this
.
textureId
,
required
this
.
size
,
required
this
.
hasTorch
,
this
.
webId
,
});
}
...
...
lib/src/mobile_scanner_controller.dart
View file @
325d393
...
...
@@ -5,8 +5,7 @@ import 'package:flutter/cupertino.dart';
import
'package:flutter/foundation.dart'
;
import
'package:flutter/services.dart'
;
import
'package:mobile_scanner/mobile_scanner.dart'
;
import
'objects/barcode_utility.dart'
;
import
'package:mobile_scanner/src/objects/barcode_utility.dart'
;
/// The facing of a camera.
enum
CameraFacing
{
...
...
@@ -56,11 +55,12 @@ class MobileScannerController {
Stream
<
Barcode
>
get
barcodes
=>
barcodesController
.
stream
;
MobileScannerController
(
{
this
.
facing
=
CameraFacing
.
back
,
MobileScannerController
({
this
.
facing
=
CameraFacing
.
back
,
this
.
ratio
,
this
.
torchEnabled
,
this
.
formats
})
{
this
.
formats
,
})
{
// In case a new instance is created before calling dispose()
if
(
_controllerHashcode
!=
null
)
{
stop
();
...
...
@@ -80,26 +80,30 @@ class MobileScannerController {
// Listen to events from the platform specific code
events
=
eventChannel
.
receiveBroadcastStream
()
.
listen
((
data
)
=>
handleEvent
(
data
));
.
listen
((
data
)
=>
handleEvent
(
data
as
Map
));
}
void
handleEvent
(
Map
<
dynamic
,
dynamic
>
event
)
{
void
handleEvent
(
Map
event
)
{
final
name
=
event
[
'name'
];
final
data
=
event
[
'data'
];
switch
(
name
)
{
case
'torchState'
:
final
state
=
TorchState
.
values
[
data
];
final
state
=
TorchState
.
values
[
data
as
int
];
torchState
.
value
=
state
;
break
;
case
'barcode'
:
final
barcode
=
Barcode
.
fromNative
(
data
);
final
barcode
=
Barcode
.
fromNative
(
data
as
Map
);
barcodesController
.
add
(
barcode
);
break
;
case
'barcodeMac'
:
barcodesController
.
add
(
Barcode
(
rawValue:
data
[
'payload'
]));
barcodesController
.
add
(
Barcode
(
rawValue:
(
data
as
Map
)[
'payload'
]
as
String
,
),
);
break
;
case
'barcodeWeb'
:
barcodesController
.
add
(
Barcode
(
rawValue:
data
));
barcodesController
.
add
(
Barcode
(
rawValue:
data
as
String
));
break
;
default
:
throw
UnimplementedError
();
...
...
@@ -129,11 +133,12 @@ class MobileScannerController {
// Check authorization status
if
(!
kIsWeb
)
{
MobileScannerState
state
=
MobileScannerState
.
values
[
await
methodChannel
.
invokeMethod
(
'state'
)];
MobileScannerState
state
=
MobileScannerState
.
values
[
await
methodChannel
.
invokeMethod
(
'state'
)
as
int
];
switch
(
state
)
{
case
MobileScannerState
.
undetermined
:
final
bool
result
=
await
methodChannel
.
invokeMethod
(
'request'
);
final
bool
result
=
await
methodChannel
.
invokeMethod
(
'request'
)
as
bool
;
state
=
result
?
MobileScannerState
.
authorized
:
MobileScannerState
.
denied
;
...
...
@@ -149,7 +154,7 @@ class MobileScannerController {
cameraFacingState
.
value
=
facing
;
// Set the starting arguments for the camera
Map
arguments
=
{};
final
Map
arguments
=
{};
arguments
[
'facing'
]
=
facing
.
index
;
if
(
ratio
!=
null
)
arguments
[
'ratio'
]
=
ratio
;
if
(
torchEnabled
!=
null
)
arguments
[
'torch'
]
=
torchEnabled
;
...
...
@@ -166,7 +171,9 @@ class MobileScannerController {
Map
<
String
,
dynamic
>?
startResult
=
{};
try
{
startResult
=
await
methodChannel
.
invokeMapMethod
<
String
,
dynamic
>(
'start'
,
arguments
);
'start'
,
arguments
,
);
}
on
PlatformException
catch
(
error
)
{
debugPrint
(
'
${error.code}
:
${error.message}
'
);
isStarting
=
false
;
...
...
@@ -179,18 +186,23 @@ class MobileScannerController {
throw
PlatformException
(
code:
'INITIALIZATION ERROR'
);
}
hasTorch
=
startResult
[
'torchable'
];
hasTorch
=
startResult
[
'torchable'
]
as
bool
;
if
(
kIsWeb
)
{
args
.
value
=
MobileScannerArguments
(
webId:
startResult
[
'ViewID'
],
size:
Size
(
startResult
[
'videoWidth'
],
startResult
[
'videoHeight'
]),
hasTorch:
hasTorch
);
webId:
startResult
[
'ViewID'
]
as
String
?,
size:
Size
(
startResult
[
'videoWidth'
]
as
double
,
startResult
[
'videoHeight'
]
as
double
,
),
hasTorch:
hasTorch
,
);
}
else
{
args
.
value
=
MobileScannerArguments
(
textureId:
startResult
[
'textureId'
],
size:
toSize
(
startResult
[
'size'
]),
hasTorch:
hasTorch
);
textureId:
startResult
[
'textureId'
]
as
int
,
size:
toSize
(
startResult
[
'size'
]
as
Map
),
hasTorch:
hasTorch
,
);
}
isStarting
=
false
;
...
...
@@ -214,7 +226,7 @@ class MobileScannerController {
return
;
}
TorchState
state
=
final
TorchState
state
=
torchState
.
value
==
TorchState
.
off
?
TorchState
.
on
:
TorchState
.
off
;
try
{
...
...
@@ -233,7 +245,8 @@ class MobileScannerController {
await
methodChannel
.
invokeMethod
(
'stop'
);
}
on
PlatformException
catch
(
error
)
{
debugPrint
(
'
${error.code}
: camera is stopped! Please start before switching camera.'
);
'
${error.code}
: camera is stopped! Please start before switching camera.'
,
);
return
;
}
facing
=
...
...
@@ -247,7 +260,7 @@ class MobileScannerController {
///
/// [path] The path of the image on the devices
Future
<
bool
>
analyzeImage
(
String
path
)
async
{
return
await
methodChannel
.
invokeMethod
(
'analyzeImage'
,
path
)
;
return
methodChannel
.
invokeMethod
(
'analyzeImage'
,
path
)
as
bool
;
}
/// Disposes the MobileScannerController and closes all listeners.
...
...
lib/src/objects/barcode.dart
View file @
325d393
import
'dart:typed_data'
;
import
'dart:ui'
;
import
'barcode_utility.dart'
;
import
'
package:mobile_scanner/src/objects/
barcode_utility.dart'
;
/// Represents a single recognized barcode and its value.
class
Barcode
{
...
...
@@ -63,8 +63,8 @@ class Barcode {
/// Gets parsed WiFi AP details.
final
WiFi
?
wifi
;
Barcode
(
{
this
.
corners
,
Barcode
({
this
.
corners
,
this
.
format
=
BarcodeFormat
.
ean13
,
this
.
rawBytes
,
this
.
type
=
BarcodeType
.
text
,
...
...
@@ -77,24 +77,25 @@ class Barcode {
this
.
sms
,
this
.
url
,
this
.
wifi
,
required
this
.
rawValue
});
required
this
.
rawValue
,
});
/// Create a [Barcode] from native data.
Barcode
.
fromNative
(
Map
<
dynamic
,
dynamic
>
data
)
:
corners
=
toCorners
(
data
[
'corners'
]),
format
=
toFormat
(
data
[
'format'
]),
rawBytes
=
data
[
'rawBytes'
],
rawValue
=
data
[
'rawValue'
],
type
=
BarcodeType
.
values
[
data
[
'type'
]],
calendarEvent
=
toCalendarEvent
(
data
[
'calendarEvent'
]),
contactInfo
=
toContactInfo
(
data
[
'contactInfo'
]),
driverLicense
=
toDriverLicense
(
data
[
'driverLicense'
]),
email
=
toEmail
(
data
[
'email'
]),
geoPoint
=
toGeoPoint
(
data
[
'geoPoint'
]),
phone
=
toPhone
(
data
[
'phone'
]),
sms
=
toSMS
(
data
[
'sms'
]),
url
=
toUrl
(
data
[
'url'
]),
wifi
=
toWiFi
(
data
[
'wifi'
]);
Barcode
.
fromNative
(
Map
data
)
:
corners
=
toCorners
(
data
[
'corners'
]
as
List
?),
format
=
toFormat
(
data
[
'format'
]
as
int
),
rawBytes
=
data
[
'rawBytes'
]
as
Uint8List
?,
rawValue
=
data
[
'rawValue'
]
as
String
?,
type
=
BarcodeType
.
values
[
data
[
'type'
]
as
int
],
calendarEvent
=
toCalendarEvent
(
data
[
'calendarEvent'
]
as
Map
?),
contactInfo
=
toContactInfo
(
data
[
'contactInfo'
]
as
Map
?),
driverLicense
=
toDriverLicense
(
data
[
'driverLicense'
]
as
Map
?),
email
=
toEmail
(
data
[
'email'
]
as
Map
?),
geoPoint
=
toGeoPoint
(
data
[
'geoPoint'
]
as
Map
?),
phone
=
toPhone
(
data
[
'phone'
]
as
Map
?),
sms
=
toSMS
(
data
[
'sms'
]
as
Map
?),
url
=
toUrl
(
data
[
'url'
]
as
Map
?),
wifi
=
toWiFi
(
data
[
'wifi'
]
as
Map
?);
}
/// A calendar event extracted from QRCode.
...
...
@@ -135,14 +136,18 @@ class CalendarEvent {
final
String
?
summary
;
/// Create a [CalendarEvent] from native data.
CalendarEvent
.
fromNative
(
Map
<
dynamic
,
dynamic
>
data
)
:
description
=
data
[
'description'
],
start
=
DateTime
.
tryParse
(
data
[
'start'
]),
end
=
DateTime
.
tryParse
(
data
[
'end'
]),
location
=
data
[
'location'
],
organizer
=
data
[
'organizer'
],
status
=
data
[
'status'
],
summary
=
data
[
'summary'
];
CalendarEvent
.
fromNative
(
Map
data
)
:
description
=
data
[
'description'
]
as
String
?,
start
=
data
[
'start'
]
!=
null
?
DateTime
.
tryParse
(
data
[
'start'
]
as
String
)
:
null
,
end
=
data
[
'end'
]
!=
null
?
DateTime
.
tryParse
(
data
[
'end'
]
as
String
)
:
null
,
location
=
data
[
'location'
]
as
String
?,
organizer
=
data
[
'organizer'
]
as
String
?,
status
=
data
[
'status'
]
as
String
?,
summary
=
data
[
'summary'
]
as
String
?;
}
/// A person's or organization's business card. For example a VCARD.
...
...
@@ -183,17 +188,20 @@ class ContactInfo {
final
List
<
String
>?
urls
;
/// Create a [ContactInfo] from native data.
ContactInfo
.
fromNative
(
Map
<
dynamic
,
dynamic
>
data
)
ContactInfo
.
fromNative
(
Map
data
)
:
addresses
=
List
.
unmodifiable
(
data
[
'addresses'
].
map
((
e
)
=>
Address
.
fromNative
(
e
))),
emails
=
List
.
unmodifiable
(
data
[
'emails'
].
map
((
e
)
=>
Email
.
fromNative
(
e
))),
name
=
toName
(
data
[
'name'
]),
organization
=
data
[
'organization'
],
phones
=
List
.
unmodifiable
(
data
[
'phones'
].
map
((
e
)
=>
Phone
.
fromNative
(
e
))),
title
=
data
[
'title'
],
urls
=
List
.
unmodifiable
(
data
[
'urls'
]);
(
data
[
'addresses'
]
as
List
).
map
((
e
)
=>
Address
.
fromNative
(
e
as
Map
)),
),
emails
=
List
.
unmodifiable
(
(
data
[
'emails'
]
as
List
).
map
((
e
)
=>
Email
.
fromNative
(
e
as
Map
)),
),
name
=
toName
(
data
[
'name'
]
as
Map
?),
organization
=
data
[
'organization'
]
as
String
?,
phones
=
List
.
unmodifiable
(
(
data
[
'phones'
]
as
List
).
map
((
e
)
=>
Phone
.
fromNative
(
e
as
Map
)),
),
title
=
data
[
'title'
]
as
String
?,
urls
=
List
.
unmodifiable
(
data
[
'urls'
]
as
List
);
}
/// An address.
...
...
@@ -207,9 +215,9 @@ class Address {
final
AddressType
?
type
;
/// Create a [Address] from native data.
Address
.
fromNative
(
Map
<
dynamic
,
dynamic
>
data
)
:
addressLines
=
List
.
unmodifiable
(
data
[
'addressLines'
]),
type
=
AddressType
.
values
[
data
[
'type'
]];
Address
.
fromNative
(
Map
data
)
:
addressLines
=
List
.
unmodifiable
(
data
[
'addressLines'
]
as
List
),
type
=
AddressType
.
values
[
data
[
'type'
]
as
int
];
}
/// A person's name, both formatted version and individual name components.
...
...
@@ -250,14 +258,14 @@ class PersonName {
final
String
?
pronunciation
;
/// Create a [PersonName] from native data.
PersonName
.
fromNative
(
Map
<
dynamic
,
dynamic
>
data
)
:
first
=
data
[
'first'
],
middle
=
data
[
'middle'
],
last
=
data
[
'last'
],
prefix
=
data
[
'prefix'
],
suffix
=
data
[
'suffix'
],
formattedName
=
data
[
'formattedName'
],
pronunciation
=
data
[
'pronunciation'
];
PersonName
.
fromNative
(
Map
data
)
:
first
=
data
[
'first'
]
as
String
?,
middle
=
data
[
'middle'
]
as
String
?,
last
=
data
[
'last'
]
as
String
?,
prefix
=
data
[
'prefix'
]
as
String
?,
suffix
=
data
[
'suffix'
]
as
String
?,
formattedName
=
data
[
'formattedName'
]
as
String
?,
pronunciation
=
data
[
'pronunciation'
]
as
String
?;
}
/// A driver license or ID card.
...
...
@@ -335,21 +343,21 @@ class DriverLicense {
final
String
?
middleName
;
/// Create a [DriverLicense] from native data.
DriverLicense
.
fromNative
(
Map
<
dynamic
,
dynamic
>
data
)
:
addressCity
=
data
[
'addressCity'
],
addressState
=
data
[
'addressState'
],
addressStreet
=
data
[
'addressStreet'
],
addressZip
=
data
[
'addressZip'
],
birthDate
=
data
[
'birthDate'
],
documentType
=
data
[
'documentType'
],
expiryDate
=
data
[
'expiryDate'
],
firstName
=
data
[
'firstName'
],
gender
=
data
[
'gender'
],
issueDate
=
data
[
'issueDate'
],
issuingCountry
=
data
[
'issuingCountry'
],
lastName
=
data
[
'lastName'
],
licenseNumber
=
data
[
'licenseNumber'
],
middleName
=
data
[
'middleName'
];
DriverLicense
.
fromNative
(
Map
data
)
:
addressCity
=
data
[
'addressCity'
]
as
String
?,
addressState
=
data
[
'addressState'
]
as
String
?,
addressStreet
=
data
[
'addressStreet'
]
as
String
?,
addressZip
=
data
[
'addressZip'
]
as
String
?,
birthDate
=
data
[
'birthDate'
]
as
String
?,
documentType
=
data
[
'documentType'
]
as
String
?,
expiryDate
=
data
[
'expiryDate'
]
as
String
?,
firstName
=
data
[
'firstName'
]
as
String
?,
gender
=
data
[
'gender'
]
as
String
?,
issueDate
=
data
[
'issueDate'
]
as
String
?,
issuingCountry
=
data
[
'issuingCountry'
]
as
String
?,
lastName
=
data
[
'lastName'
]
as
String
?,
licenseNumber
=
data
[
'licenseNumber'
]
as
String
?,
middleName
=
data
[
'middleName'
]
as
String
?;
}
/// An email message from a 'MAILTO:' or similar QRCode type.
...
...
@@ -376,11 +384,11 @@ class Email {
final
EmailType
?
type
;
/// Create a [Email] from native data.
Email
.
fromNative
(
Map
<
dynamic
,
dynamic
>
data
)
:
address
=
data
[
'address'
],
body
=
data
[
'body'
],
subject
=
data
[
'subject'
],
type
=
EmailType
.
values
[
data
[
'type'
]];
Email
.
fromNative
(
Map
data
)
:
address
=
data
[
'address'
]
as
String
?,
body
=
data
[
'body'
]
as
String
?,
subject
=
data
[
'subject'
]
as
String
?,
type
=
EmailType
.
values
[
data
[
'type'
]
as
int
];
}
/// GPS coordinates from a 'GEO:' or similar QRCode type.
...
...
@@ -392,9 +400,9 @@ class GeoPoint {
final
double
?
longitude
;
/// Create a [GeoPoint] from native data.
GeoPoint
.
fromNative
(
Map
<
dynamic
,
dynamic
>
data
)
:
latitude
=
data
[
'latitude'
],
longitude
=
data
[
'longitude'
];
GeoPoint
.
fromNative
(
Map
data
)
:
latitude
=
data
[
'latitude'
]
as
double
?,
longitude
=
data
[
'longitude'
]
as
double
?;
}
/// Phone number info.
...
...
@@ -411,9 +419,9 @@ class Phone {
final
PhoneType
?
type
;
/// Create a [Phone] from native data.
Phone
.
fromNative
(
Map
<
dynamic
,
dynamic
>
data
)
:
number
=
data
[
'number'
],
type
=
PhoneType
.
values
[
data
[
'type'
]];
Phone
.
fromNative
(
Map
data
)
:
number
=
data
[
'number'
]
as
String
?,
type
=
PhoneType
.
values
[
data
[
'type'
]
as
int
];
}
/// A sms message from a 'SMS:' or similar QRCode type.
...
...
@@ -429,9 +437,9 @@ class SMS {
final
String
?
phoneNumber
;
/// Create a [SMS] from native data.
SMS
.
fromNative
(
Map
<
dynamic
,
dynamic
>
data
)
:
message
=
data
[
'message'
],
phoneNumber
=
data
[
'phoneNumber'
];
SMS
.
fromNative
(
Map
data
)
:
message
=
data
[
'message'
]
as
String
?,
phoneNumber
=
data
[
'phoneNumber'
]
as
String
?;
}
/// A URL and title from a 'MEBKM:' or similar QRCode type.
...
...
@@ -447,9 +455,9 @@ class UrlBookmark {
final
String
?
url
;
/// Create a [UrlBookmark] from native data.
UrlBookmark
.
fromNative
(
Map
<
dynamic
,
dynamic
>
data
)
:
title
=
data
[
'title'
],
url
=
data
[
'url'
];
UrlBookmark
.
fromNative
(
Map
data
)
:
title
=
data
[
'title'
]
as
String
?,
url
=
data
[
'url'
]
as
String
?;
}
/// A wifi network parameters from a 'WIFI:' or similar QRCode type.
...
...
@@ -470,10 +478,10 @@ class WiFi {
final
String
?
password
;
/// Create a [WiFi] from native data.
WiFi
.
fromNative
(
Map
<
dynamic
,
dynamic
>
data
)
:
encryptionType
=
EncryptionType
.
values
[
data
[
'encryptionType'
]],
ssid
=
data
[
'ssid'
],
password
=
data
[
'password'
];
WiFi
.
fromNative
(
Map
data
)
:
encryptionType
=
EncryptionType
.
values
[
data
[
'encryptionType'
]
as
int
],
ssid
=
data
[
'ssid'
]
as
String
?,
password
=
data
[
'password'
]
as
String
?;
}
enum
BarcodeFormat
{
...
...
lib/src/objects/barcode_utility.dart
View file @
325d393
import
'package:flutter/material.dart'
;
import
'package:mobile_scanner/mobile_scanner.dart'
;
import
'barcode.dart'
;
Size
toSize
(
Map
<
dynamic
,
dynamic
>
data
)
{
final
width
=
data
[
'width'
];
final
height
=
data
[
'height'
];
Size
toSize
(
Map
data
)
{
final
width
=
data
[
'width'
]
as
double
;
final
height
=
data
[
'height'
]
as
double
;
return
Size
(
width
,
height
);
}
List
<
Offset
>?
toCorners
(
List
<
dynamic
>
?
data
)
{
List
<
Offset
>?
toCorners
(
List
?
data
)
{
if
(
data
!=
null
)
{
return
List
.
unmodifiable
(
data
.
map
((
e
)
=>
Offset
(
e
[
'x'
],
e
[
'y'
])));
return
List
.
unmodifiable
(
data
.
map
((
e
)
=>
Offset
((
e
as
Map
)[
'x'
]
as
double
,
e
[
'y'
]
as
double
)),
);
}
else
{
return
null
;
}
...
...
@@ -51,7 +52,7 @@ BarcodeFormat toFormat(int value) {
}
}
CalendarEvent
?
toCalendarEvent
(
Map
<
dynamic
,
dynamic
>
?
data
)
{
CalendarEvent
?
toCalendarEvent
(
Map
?
data
)
{
if
(
data
!=
null
)
{
return
CalendarEvent
.
fromNative
(
data
);
}
else
{
...
...
@@ -59,15 +60,15 @@ CalendarEvent? toCalendarEvent(Map<dynamic, dynamic>? data) {
}
}
DateTime
?
toDateTime
(
Map
<
dynamic
,
dynamic
>?
data
)
{
DateTime
?
toDateTime
(
Map
<
String
,
dynamic
>?
data
)
{
if
(
data
!=
null
)
{
final
year
=
data
[
'year'
];
final
month
=
data
[
'month'
];
final
day
=
data
[
'day'
];
final
hour
=
data
[
'hours'
];
final
minute
=
data
[
'minutes'
];
final
second
=
data
[
'seconds'
];
return
data
[
'isUtc'
]
final
year
=
data
[
'year'
]
as
int
;
final
month
=
data
[
'month'
]
as
int
;
final
day
=
data
[
'day'
]
as
int
;
final
hour
=
data
[
'hours'
]
as
int
;
final
minute
=
data
[
'minutes'
]
as
int
;
final
second
=
data
[
'seconds'
]
as
int
;
return
data
[
'isUtc'
]
as
bool
?
DateTime
.
utc
(
year
,
month
,
day
,
hour
,
minute
,
second
)
:
DateTime
(
year
,
month
,
day
,
hour
,
minute
,
second
);
}
else
{
...
...
@@ -75,7 +76,7 @@ DateTime? toDateTime(Map<dynamic, dynamic>? data) {
}
}
ContactInfo
?
toContactInfo
(
Map
<
dynamic
,
dynamic
>
?
data
)
{
ContactInfo
?
toContactInfo
(
Map
?
data
)
{
if
(
data
!=
null
)
{
return
ContactInfo
.
fromNative
(
data
);
}
else
{
...
...
@@ -83,7 +84,7 @@ ContactInfo? toContactInfo(Map<dynamic, dynamic>? data) {
}
}
PersonName
?
toName
(
Map
<
dynamic
,
dynamic
>
?
data
)
{
PersonName
?
toName
(
Map
?
data
)
{
if
(
data
!=
null
)
{
return
PersonName
.
fromNative
(
data
);
}
else
{
...
...
@@ -91,7 +92,7 @@ PersonName? toName(Map<dynamic, dynamic>? data) {
}
}
DriverLicense
?
toDriverLicense
(
Map
<
dynamic
,
dynamic
>
?
data
)
{
DriverLicense
?
toDriverLicense
(
Map
?
data
)
{
if
(
data
!=
null
)
{
return
DriverLicense
.
fromNative
(
data
);
}
else
{
...
...
@@ -99,7 +100,7 @@ DriverLicense? toDriverLicense(Map<dynamic, dynamic>? data) {
}
}
Email
?
toEmail
(
Map
<
dynamic
,
dynamic
>
?
data
)
{
Email
?
toEmail
(
Map
?
data
)
{
if
(
data
!=
null
)
{
return
Email
.
fromNative
(
data
);
}
else
{
...
...
@@ -107,7 +108,7 @@ Email? toEmail(Map<dynamic, dynamic>? data) {
}
}
GeoPoint
?
toGeoPoint
(
Map
<
dynamic
,
dynamic
>
?
data
)
{
GeoPoint
?
toGeoPoint
(
Map
?
data
)
{
if
(
data
!=
null
)
{
return
GeoPoint
.
fromNative
(
data
);
}
else
{
...
...
@@ -115,7 +116,7 @@ GeoPoint? toGeoPoint(Map<dynamic, dynamic>? data) {
}
}
Phone
?
toPhone
(
Map
<
dynamic
,
dynamic
>
?
data
)
{
Phone
?
toPhone
(
Map
?
data
)
{
if
(
data
!=
null
)
{
return
Phone
.
fromNative
(
data
);
}
else
{
...
...
@@ -123,7 +124,7 @@ Phone? toPhone(Map<dynamic, dynamic>? data) {
}
}
SMS
?
toSMS
(
Map
<
dynamic
,
dynamic
>
?
data
)
{
SMS
?
toSMS
(
Map
?
data
)
{
if
(
data
!=
null
)
{
return
SMS
.
fromNative
(
data
);
}
else
{
...
...
@@ -131,7 +132,7 @@ SMS? toSMS(Map<dynamic, dynamic>? data) {
}
}
UrlBookmark
?
toUrl
(
Map
<
dynamic
,
dynamic
>
?
data
)
{
UrlBookmark
?
toUrl
(
Map
?
data
)
{
if
(
data
!=
null
)
{
return
UrlBookmark
.
fromNative
(
data
);
}
else
{
...
...
@@ -139,7 +140,7 @@ UrlBookmark? toUrl(Map<dynamic, dynamic>? data) {
}
}
WiFi
?
toWiFi
(
Map
<
dynamic
,
dynamic
>
?
data
)
{
WiFi
?
toWiFi
(
Map
?
data
)
{
if
(
data
!=
null
)
{
return
WiFi
.
fromNative
(
data
);
}
else
{
...
...
lib/src/web/jsqr.dart
View file @
325d393
...
...
@@ -4,7 +4,7 @@ library jsqr;
import
'package:js/js.dart'
;
@JS
(
'jsQR'
)
external
Code
?
jsQR
(
var
data
,
int
?
width
,
int
?
height
);
external
Code
?
jsQR
(
dynamic
data
,
int
?
width
,
int
?
height
);
@JS
()
class
Code
{
...
...
lib/src/web/media.dart
View file @
325d393
...
...
@@ -25,8 +25,12 @@ class VideoOptions {
external
Map
get
width
;
external
Map
get
height
;
external
factory
VideoOptions
(
{
String
?
facingMode
,
DeviceIdOptions
?
deviceId
,
Map
?
width
,
Map
?
height
});
external
factory
VideoOptions
({
String
?
facingMode
,
DeviceIdOptions
?
deviceId
,
Map
?
width
,
Map
?
height
,
});
}
@JS
()
...
...
lib/src/web/qr_scanner.dart
View file @
325d393
...
...
@@ -4,7 +4,7 @@ library qrscanner;
import
'package:js/js.dart'
;
@JS
(
'QrScanner'
)
external
String
scanImage
(
var
data
);
external
String
scanImage
(
dynamic
data
);
@JS
()
class
QrScanner
{
...
...
pubspec.yaml
View file @
325d393
...
...
@@ -8,16 +8,16 @@ environment:
flutter
:
"
>=1.10.0"
dependencies
:
js
:
^0.6.3
flutter
:
sdk
:
flutter
flutter_web_plugins
:
sdk
:
flutter
js
:
^0.6.3
dev_dependencies
:
flutter_test
:
sdk
:
flutter
flutter_lints
:
^1.0.4
lint
:
^1.8.2
flutter
:
plugin
:
...
...
Please
register
or
login
to post a comment