Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
com.ccwangluo.accelerator
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
sheteng
com.ccwangluo.accelerator
Commits
bbc635b1
Commit
bbc635b1
authored
Jun 26, 2020
by
Mygod
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Migrate to ML kit for scanning QR code
Fixes #2548.
parent
9d2bc2d6
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
94 additions
and
79 deletions
+94
-79
core/build.gradle.kts
core/build.gradle.kts
+1
-1
core/src/main/java/com/github/shadowsocks/utils/Utils.kt
core/src/main/java/com/github/shadowsocks/utils/Utils.kt
+1
-1
mobile/build.gradle.kts
mobile/build.gradle.kts
+6
-2
mobile/src/main/java/com/github/shadowsocks/ScannerActivity.kt
...e/src/main/java/com/github/shadowsocks/ScannerActivity.kt
+84
-70
mobile/src/main/res/layout/layout_scanner.xml
mobile/src/main/res/layout/layout_scanner.xml
+2
-5
No files found.
core/build.gradle.kts
View file @
bbc635b1
...
...
@@ -71,7 +71,7 @@ dependencies {
val
workVersion
=
"2.4.0-rc01"
api
(
project
(
":plugin"
))
api
(
"androidx.fragment:fragment-ktx:1.
2.5
"
)
api
(
"androidx.fragment:fragment-ktx:1.
3.0-alpha06
"
)
api
(
"androidx.lifecycle:lifecycle-common-java8:$lifecycleVersion"
)
api
(
"androidx.lifecycle:lifecycle-livedata-core-ktx:$lifecycleVersion"
)
api
(
"androidx.preference:preference:1.1.1"
)
...
...
core/src/main/java/com/github/shadowsocks/utils/Utils.kt
View file @
bbc635b1
...
...
@@ -44,7 +44,7 @@ import java.net.InetAddress
import
kotlin.coroutines.resume
import
kotlin.coroutines.resumeWithException
fun
<
T
>
Iterable
<
T
>.
forEachTry
(
action
:
(
T
)
->
Unit
)
{
inline
fun
<
T
>
Iterable
<
T
>.
forEachTry
(
action
:
(
T
)
->
Unit
)
{
var
result
:
Exception
?
=
null
for
(
element
in
this
)
try
{
action
(
element
)
...
...
mobile/build.gradle.kts
View file @
bbc635b1
...
...
@@ -12,14 +12,18 @@ setupApp()
android
.
defaultConfig
.
applicationId
=
"com.github.shadowsocks"
dependencies
{
val
cameraxVersion
=
"1.0.0-beta06"
implementation
(
"androidx.browser:browser:1.2.0"
)
implementation
(
"androidx.camera:camera-camera2:$cameraxVersion"
)
implementation
(
"androidx.camera:camera-lifecycle:$cameraxVersion"
)
implementation
(
"androidx.camera:camera-view:1.0.0-alpha13"
)
implementation
(
"androidx.constraintlayout:constraintlayout:2.0.0-beta7"
)
implementation
(
"androidx.lifecycle:lifecycle-runtime-ktx:$lifecycleVersion"
)
implementation
(
"com.google.android.gms:play-services-vision:20.1.0"
)
implementation
(
"com.google.firebase:firebase-ads:19.2.0"
)
implementation
(
"com.google.mlkit:barcode-scanning:16.0.0"
)
implementation
(
"com.google.zxing:core:3.4.0"
)
implementation
(
"com.takisoft.preferencex:preferencex-simplemenu:1.1.0"
)
implementation
(
"com.twofortyfouram:android-plugin-api-for-locale:1.0.4"
)
implementation
(
"me.zhanghai.android.fastscroll:library:1.1.4"
)
implementation
(
"xyz.belvi.mobilevision:barcodescanner:2.0.3"
)
}
mobile/src/main/java/com/github/shadowsocks/ScannerActivity.kt
View file @
bbc635b1
...
...
@@ -20,98 +20,108 @@
package
com.github.shadowsocks
import
android.Manifest
import
android.app.Activity
import
android.content.ActivityNotFoundException
import
android.content.Intent
import
android.content.pm.ShortcutManager
import
android.hardware.camera2.CameraAccessException
import
android.hardware.camera2.CameraManager
import
android.net.Uri
import
android.os.Build
import
android.os.Bundle
import
android.util.SparseArray
import
android.view.Menu
import
android.view.MenuItem
import
android.widget.Toast
import
androidx.activity.result.contract.ActivityResultContracts
import
androidx.appcompat.app.AppCompatActivity
import
androidx.camera.core.*
import
androidx.camera.lifecycle.ProcessCameraProvider
import
androidx.camera.view.PreviewView
import
androidx.core.content.getSystemService
import
androidx.core.util.forEach
import
androidx.lifecycle.lifecycleScope
import
androidx.work.await
import
com.github.shadowsocks.Core.app
import
com.github.shadowsocks.database.Profile
import
com.github.shadowsocks.database.ProfileManager
import
com.github.shadowsocks.utils.datas
import
com.github.shadowsocks.utils.forEachTry
import
com.github.shadowsocks.utils.openBitmap
import
com.github.shadowsocks.utils.readableMessage
import
com.google.
android.gms.common.GoogleApiAvailability
import
com.google.
android.gms.samples.vision.barcodereader.BarcodeCapture
import
com.google.
android.gms.samples.vision.barcodereader.BarcodeGraphic
import
com.google.
android.gms.vision.Fram
e
import
com.google.android.gms.vision.barcode.Barcode
import
com.google.android.gms.vision.barcode.BarcodeDetector
import
com.google.
mlkit.vision.barcode.Barcode
import
com.google.
mlkit.vision.barcode.BarcodeScannerOptions
import
com.google.
mlkit.vision.barcode.BarcodeScanning
import
com.google.
mlkit.vision.common.InputImag
e
import
kotlinx.coroutines.*
import
kotlinx.coroutines.tasks.await
import
timber.log.Timber
import
xyz.belvi.mobilevisionbarcodescanner.BarcodeRetriever
class
ScannerActivity
:
AppCompatActivity
(),
BarcodeRetriev
er
{
class
ScannerActivity
:
AppCompatActivity
(),
ImageAnalysis
.
Analyz
er
{
companion
object
{
private
const
val
REQUEST_IMPORT
=
2
private
const
val
REQUEST_IMPORT_OR_FINISH
=
3
private
const
val
REQUEST_GOOGLE_API
=
4
}
private
lateinit
var
detector
:
BarcodeDetector
private
val
scanner
=
BarcodeScanning
.
getClient
(
BarcodeScannerOptions
.
Builder
().
apply
{
setBarcodeFormats
(
Barcode
.
FORMAT_QR_CODE
)
}.
build
())
private
val
imageAnalysis
by
lazy
{
ImageAnalysis
.
Builder
().
apply
{
setBackpressureStrategy
(
ImageAnalysis
.
STRATEGY_KEEP_ONLY_LATEST
)
}.
build
().
also
{
it
.
setAnalyzer
(
Dispatchers
.
Main
.
immediate
.
asExecutor
(),
this
)
}
}
private
fun
fallback
()
{
try
{
startActivity
(
Intent
(
Intent
.
ACTION_VIEW
,
Uri
.
parse
(
"market://details?id=com.github.sumimakito.awesomeqrsample"
)))
}
catch
(
_
:
ActivityNotFoundException
)
{
}
finish
()
@ExperimentalGetImage
override
fun
analyze
(
image
:
ImageProxy
)
{
val
mediaImage
=
image
.
image
?:
return
lifecycleScope
.
launchWhenCreated
{
val
result
=
try
{
process
{
InputImage
.
fromMediaImage
(
mediaImage
,
image
.
imageInfo
.
rotationDegrees
)
}.
also
{
if
(
it
)
imageAnalysis
.
clearAnalyzer
()
}
}
catch
(
e
:
Exception
)
{
return
@launchWhenCreated
Timber
.
w
(
e
)
}
finally
{
image
.
close
()
}
if
(
result
)
onSupportNavigateUp
()
}
}
override
fun
onCreate
(
savedInstanceState
:
Bundle
?)
{
super
.
onCreate
(
savedInstanceState
)
detector
=
BarcodeDetector
.
Builder
(
this
)
.
setBarcodeFormats
(
Barcode
.
QR_CODE
)
.
build
()
if
(!
detector
.
isOperational
)
{
val
availability
=
GoogleApiAvailability
.
getInstance
()
val
dialog
=
availability
.
getErrorDialog
(
this
,
availability
.
isGooglePlayServicesAvailable
(
this
),
REQUEST_GOOGLE_API
)
if
(
dialog
==
null
)
{
Toast
.
makeText
(
this
,
R
.
string
.
common_google_play_services_notification_ticker
,
Toast
.
LENGTH_SHORT
)
.
show
()
fallback
()
}
else
{
dialog
.
setOnDismissListener
{
fallback
()
}
dialog
.
show
()
}
return
}
if
(
Build
.
VERSION
.
SDK_INT
<
23
)
return
startImport
()
// we show no love to lollipop
if
(
Build
.
VERSION
.
SDK_INT
>=
25
)
getSystemService
<
ShortcutManager
>()
!!
.
reportShortcutUsed
(
"scan"
)
if
(
try
{
getSystemService
<
CameraManager
>()
?.
cameraIdList
?.
isEmpty
()
}
catch
(
_
:
CameraAccessException
)
{
true
}
!=
false
)
{
startImport
()
return
}
}
!=
false
)
return
startImport
()
setContentView
(
R
.
layout
.
layout_scanner
)
setSupportActionBar
(
findViewById
(
R
.
id
.
toolbar
))
supportActionBar
!!
.
setDisplayHomeAsUpEnabled
(
true
)
val
capture
=
supportFragmentManager
.
findFragmentById
(
R
.
id
.
barcode
)
as
BarcodeCapture
capture
.
setCustomDetector
(
detector
)
capture
.
setRetrieval
(
this
)
requestCamera
.
launch
(
Manifest
.
permission
.
CAMERA
)
}
private
val
requestCamera
=
registerForActivityResult
(
ActivityResultContracts
.
RequestPermission
())
{
granted
->
if
(
granted
)
lifecycleScope
.
launchWhenCreated
{
val
cameraProvider
=
ProcessCameraProvider
.
getInstance
(
this
@ScannerActivity
).
await
()
val
preview
=
Preview
.
Builder
().
build
()
preview
.
setSurfaceProvider
(
findViewById
<
PreviewView
>(
R
.
id
.
barcode
).
createSurfaceProvider
())
cameraProvider
.
bindToLifecycle
(
this
@ScannerActivity
,
CameraSelector
.
Builder
().
apply
{
requireLensFacing
(
CameraSelector
.
LENS_FACING_BACK
)
}.
build
(),
preview
,
imageAnalysis
)
}
else
permissionMissing
()
}
override
fun
onRetrieved
(
barcode
:
Barcode
)
=
runOnUiThread
{
Profile
.
findAllUrls
(
barcode
.
rawValue
,
Core
.
currentProfile
?.
main
).
forEach
{
ProfileManager
.
createProfile
(
it
)
}
onSupportNavigateUp
()
private
suspend
inline
fun
process
(
feature
:
Profile
?
=
Core
.
currentProfile
?.
main
,
crossinline
image
:
()
->
InputImage
):
Boolean
{
val
barcodes
=
withContext
(
Dispatchers
.
Default
)
{
scanner
.
process
(
image
()).
await
()
}
var
result
=
false
for
(
profile
in
Profile
.
findAllUrls
(
barcodes
.
mapNotNull
{
it
.
rawValue
}.
joinToString
(
"\n"
),
feature
))
{
ProfileManager
.
createProfile
(
profile
)
result
=
true
}
override
fun
onRetrievedMultiple
(
closetToClick
:
Barcode
?,
barcode
:
MutableList
<
BarcodeGraphic
>?)
=
check
(
false
)
override
fun
onBitmapScanned
(
sparseArray
:
SparseArray
<
Barcode
>?)
{
}
override
fun
onRetrievedFailed
(
reason
:
String
?)
=
Timber
.
w
(
reason
)
override
fun
onPermissionRequestDenied
()
{
return
result
}
private
fun
permissionMissing
()
{
Toast
.
makeText
(
this
,
R
.
string
.
add_profile_scanner_permission_required
,
Toast
.
LENGTH_SHORT
).
show
()
startImport
()
}
...
...
@@ -133,6 +143,13 @@ class ScannerActivity : AppCompatActivity(), BarcodeRetriever {
*/
override
fun
shouldUpRecreateTask
(
targetIntent
:
Intent
?)
=
super
.
shouldUpRecreateTask
(
targetIntent
)
||
isTaskRoot
private
var
finished
=
false
override
fun
onSupportNavigateUp
():
Boolean
{
if
(
finished
)
return
false
finished
=
true
return
super
.
onSupportNavigateUp
()
}
private
fun
startImport
(
manual
:
Boolean
=
false
)
=
startActivityForResult
(
Intent
(
Intent
.
ACTION_GET_CONTENT
).
apply
{
addCategory
(
Intent
.
CATEGORY_OPENABLE
)
type
=
"image/*"
...
...
@@ -140,26 +157,23 @@ class ScannerActivity : AppCompatActivity(), BarcodeRetriever {
},
if
(
manual
)
REQUEST_IMPORT
else
REQUEST_IMPORT_OR_FINISH
)
override
fun
onActivityResult
(
requestCode
:
Int
,
resultCode
:
Int
,
data
:
Intent
?)
{
when
(
requestCode
)
{
REQUEST_IMPORT
,
REQUEST_IMPORT_OR_FINISH
->
if
(
resultCode
==
Activity
.
RESULT_OK
)
{
REQUEST_IMPORT
,
REQUEST_IMPORT_OR_FINISH
->
when
{
resultCode
==
Activity
.
RESULT_OK
->
GlobalScope
.
launch
(
Dispatchers
.
Main
.
immediate
)
{
onSupportNavigateUp
()
val
feature
=
Core
.
currentProfile
?.
main
try
{
var
success
=
false
data
!!
.
datas
.
forEachTry
{
uri
->
detector
.
detect
(
Frame
.
Builder
().
setBitmap
(
contentResolver
.
openBitmap
(
uri
)).
build
())
.
forEach
{
_
,
barcode
->
Profile
.
findAllUrls
(
barcode
.
rawValue
,
feature
).
forEach
{
ProfileManager
.
createProfile
(
it
)
success
=
true
if
(
process
(
feature
)
{
InputImage
.
fromFilePath
(
app
,
uri
)
})
success
=
true
}
}
}
Toast
.
makeText
(
this
,
if
(
success
)
R
.
string
.
action_import_msg
else
R
.
string
.
action_import_err
,
Toast
.
makeText
(
app
,
if
(
success
)
R
.
string
.
action_import_msg
else
R
.
string
.
action_import_err
,
Toast
.
LENGTH_SHORT
).
show
()
}
catch
(
e
:
Exception
)
{
Toast
.
makeText
(
this
,
e
.
readableMessage
,
Toast
.
LENGTH_LONG
).
show
()
Toast
.
makeText
(
app
,
e
.
readableMessage
,
Toast
.
LENGTH_LONG
).
show
()
}
}
requestCode
==
REQUEST_IMPORT_OR_FINISH
->
onSupportNavigateUp
()
}
onSupportNavigateUp
()
}
else
if
(
requestCode
==
REQUEST_IMPORT_OR_FINISH
)
onSupportNavigateUp
()
else
->
super
.
onActivityResult
(
requestCode
,
resultCode
,
data
)
}
}
...
...
mobile/src/main/res/layout/layout_scanner.xml
View file @
bbc635b1
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:orientation=
"vertical"
>
<include
layout=
"@layout/toolbar_light_dark"
/>
<
fragment
<
androidx.camera.view.PreviewView
android:id=
"@+id/barcode"
android:name=
"com.google.android.gms.samples.vision.barcodereader.BarcodeCapture"
android:layout_width=
"fill_parent"
android:layout_height=
"fill_parent"
app:gvb_auto_focus=
"true"
/>
android:layout_height=
"fill_parent"
/>
</LinearLayout>
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment