Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
F
flutter_plugin
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
林生雨
flutter_plugin
Commits
50d38372
Commit
50d38372
authored
Sep 27, 2019
by
林生雨
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
commit
parent
fc876556
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
27 changed files
with
1653 additions
and
0 deletions
+1653
-0
GengmeiFlutterPlugin.kt
...om/example/gengmei_flutter_plugin/GengmeiFlutterPlugin.kt
+0
-0
ImageRespository.kt
...flutter_plugin/ImagePlugin/repository/ImageRespository.kt
+210
-0
MediaFile.kt
...i_flutter_plugin/ImagePlugin/repository/bean/MediaFile.kt
+19
-0
MediaFolder.kt
...flutter_plugin/ImagePlugin/repository/bean/MediaFolder.kt
+27
-0
ConfigManager.kt
...ter_plugin/ImagePlugin/repository/config/ConfigManager.kt
+58
-0
AbsMediaScanner.kt
...er_plugin/ImagePlugin/repository/local/AbsMediaScanner.kt
+93
-0
ImageScanner.kt
...utter_plugin/ImagePlugin/repository/local/ImageScanner.kt
+105
-0
MediaHandler.kt
...utter_plugin/ImagePlugin/repository/local/MediaHandler.kt
+108
-0
VideoScanner.kt
...utter_plugin/ImagePlugin/repository/local/VideoScanner.kt
+66
-0
Checker.java
..._flutter_plugin/ImagePlugin/repository/luban/Checker.java
+203
-0
CompressionPredicate.kt
...ugin/ImagePlugin/repository/luban/CompressionPredicate.kt
+16
-0
Engine.kt
...mei_flutter_plugin/ImagePlugin/repository/luban/Engine.kt
+117
-0
InputStreamAdapter.kt
...plugin/ImagePlugin/repository/luban/InputStreamAdapter.kt
+35
-0
InputStreamProvider.kt
...lugin/ImagePlugin/repository/luban/InputStreamProvider.kt
+18
-0
Luban.kt
...gmei_flutter_plugin/ImagePlugin/repository/luban/Luban.kt
+0
-0
OnCompressListener.kt
...plugin/ImagePlugin/repository/luban/OnCompressListener.kt
+25
-0
OnRenameListener.kt
...r_plugin/ImagePlugin/repository/luban/OnRenameListener.kt
+20
-0
a
android/src/main/java/com/example/gengmei_flutter_plugin/a
+0
-0
RxExpecition.kt
...ava/com/example/gengmei_flutter_plugin/ex/RxExpecition.kt
+10
-0
ResultManager.kt
...om/example/gengmei_flutter_plugin/result/ResultManager.kt
+50
-0
SharedManager.kt
.../gengmei_flutter_plugin/sharedPrefernces/SharedManager.kt
+115
-0
DebugUtil.java
...a/com/example/gengmei_flutter_plugin/utils/DebugUtil.java
+19
-0
DimensionUtils.java
.../example/gengmei_flutter_plugin/utils/DimensionUtils.java
+121
-0
FileUtil.java
...va/com/example/gengmei_flutter_plugin/utils/FileUtil.java
+83
-0
ImageLoader.kt
...a/com/example/gengmei_flutter_plugin/utils/ImageLoader.kt
+43
-0
KTUtil.kt
...n/java/com/example/gengmei_flutter_plugin/utils/KTUtil.kt
+40
-0
MyUtil.kt
...n/java/com/example/gengmei_flutter_plugin/utils/MyUtil.kt
+52
-0
No files found.
android/src/main/java/com/example/gengmei_flutter_plugin/GengmeiFlutterPlugin.kt
0 → 100644
View file @
50d38372
This diff is collapsed.
Click to expand it.
android/src/main/java/com/example/gengmei_flutter_plugin/ImagePlugin/repository/ImageRespository.kt
0 → 100644
View file @
50d38372
package
com.example.myimagepicker.repository
import
android.content.Context
import
android.graphics.BitmapFactory
import
android.util.Log
import
com.example.gengmei_flutter_plugin.utils.MyUtil.Companion.getFileFullName
import
com.example.gengmei_flutter_plugin.utils.MyUtil.Companion.getFileName
import
com.example.gengmei_flutter_plugin.utils.MyUtil.Companion.getImageCacheDir
import
com.example.myimagepicker.bean.MediaFile
import
com.example.myimagepicker.bean.MediaFolder
import
com.example.myimagepicker.luban.Luban
import
com.example.myimagepicker.repository.local.ImageScanner
import
io.reactivex.Observable
import
io.reactivex.ObservableOnSubscribe
import
io.reactivex.android.schedulers.AndroidSchedulers
import
io.reactivex.disposables.CompositeDisposable
import
io.reactivex.schedulers.Schedulers
import
java.io.File
import
java.util.*
import
java.util.concurrent.*
import
kotlin.collections.ArrayList
import
kotlin.collections.HashMap
/**
* Created by lsy
* on 2019/3/27
*/
class
ImageRespository
{
private
val
globalThreadPool
=
ThreadPoolExecutor
(
0
,
30
,
30
,
TimeUnit
.
SECONDS
,
LinkedBlockingDeque
());
val
recordImageListMap
=
ArrayList
<
HashMap
<
String
,
Any
>>()
var
finishOneTask
=
false
//: HashMap<String, ArrayList<HashMap<String, Any>>>
fun
scanPhoneImage
(
context
:
Context
):
Observable
<
HashMap
<
String
,
ArrayList
<
HashMap
<
String
,
Any
>>>>
{
if
(!
recordImageListMap
.
isEmpty
()
&&
finishOneTask
)
{
return
Observable
.
just
(
toMap
(
context
,
recordImageListMap
))
.
subscribeOn
(
Schedulers
.
computation
()).
observeOn
(
AndroidSchedulers
.
mainThread
())
}
return
Observable
.
create
(
ObservableOnSubscribe
<
HashMap
<
String
,
ArrayList
<
HashMap
<
String
,
Any
>>>>
{
it
.
onNext
(
getFinalMap
(
context
,
ImageScanner
(
context
).
queryMedia
()))
}).
subscribeOn
(
Schedulers
.
computation
()).
observeOn
(
AndroidSchedulers
.
mainThread
())
}
fun
savePreviewImg
(
context
:
Context
,
listener
:
savePreviewListener
)
{
val
needSize
=
recordImageListMap
.
size
;
var
currentSize
=
0
;
var
letSize
=
30
var
noPathSize
=
0
;
recordImageListMap
.
forEach
{
val
any
=
it
[
"path"
]
val
realPath
=
it
[
"realPath"
]
as
String
if
(
any
==
null
)
{
globalThreadPool
.
execute
{
val
get
=
Luban
.
with
(
context
).
setTargetDir
(
getImageCacheDir
(
context
,
Luban
.
DEFAULT_DISK_CACHE_DIR
)
!!
.
absolutePath
)
.
setName
(
getFileName
(
realPath
)
!!
)
.
get
(
realPath
);
it
[
"path"
]
=
get
.
absolutePath
;
synchronized
(
this
)
{
currentSize
++;
noPathSize
++;
Log
.
e
(
"lsy"
,
"${noPathSize} ${currentSize} ${needSize}"
)
if
(
currentSize
==
needSize
)
{
//FINISH
listener
.
onSuccess
(
toMap
(
context
,
recordImageListMap
))
}
else
{
if
(
noPathSize
>
letSize
)
{
letSize
+=
30
listener
.
onSuccess
(
toMap
(
context
,
recordImageListMap
))
}
}
}
}
}
else
{
synchronized
(
this
)
{
currentSize
++;
Log
.
e
(
"lsy"
,
"HAVE PATH ${noPathSize} ${currentSize} ${needSize}"
)
if
(
currentSize
==
needSize
)
{
//FINISH
listener
.
onSuccess
(
toMap
(
context
,
recordImageListMap
))
}
// else if (currentSize > letSize) {
// letSize += 100
// listener.onSuccess(toMap(context, recordImageListMap))
// }
}
}
}
}
interface
savePreviewListener
{
fun
onSuccess
(
data
:
HashMap
<
String
,
ArrayList
<
HashMap
<
String
,
Any
>>>)
}
// val currentTimeMillis = System.currentTimeMillis();
// Thread {
// val queryMedia = ImageScanner(context).queryMedia()
// val needSize = queryMedia.size
// val newList = ArrayList<MediaFile>();
// val dir = getImageCacheDir(context, Luban.DEFAULT_DISK_CACHE_DIR)!!.absolutePath;
// queryMedia.forEach {
// val path = it.realPath!!
// val tempFilePngExists = File(dir + "/" + getFileName(path)!! + ".png").exists()
// val tempFileJpgExists = File(dir + "/" + getFileName(path)!! + ".jpg").exists();
// val tempFileJpegExists = File(dir + "/" + getFileName(path)!! + ".jpeg").exists()
//
// if (it.size > 1024 * 1024 && !tempFilePngExists
// && !tempFileJpgExists && !tempFileJpegExists) {
// globalThreadPool.execute {
// val get = Luban.with(context).setTargetDir(getImageCacheDir(context, Luban.DEFAULT_DISK_CACHE_DIR)!!.absolutePath)
// .setName(getFileName(path)!!)
// .get(path);
// // Log.e("lsy"," ${getFileFullName(path)!!}");
// it.path = get.absolutePath
// Log.e("lsy", " ${get.absolutePath} ")
// synchronized(this) {
// newList.add(it);
// Log.e("lsy", " ${newList.size} ${needSize}")
// if (newList.size == needSize) {
// //OKK
// Log.e("lsy", " TIME ${System.currentTimeMillis() - currentTimeMillis}")
// }
// }
// }
// } else {
// synchronized(this) {
// newList.add(it);
// Log.e("lsy", " ${newList.size} ${needSize}")
// if (newList.size == needSize) {
// //OKK
// Log.e("lsy", " TIME ${System.currentTimeMillis() - currentTimeMillis}")
// }
// }
// }
// }
// }.start()
fun
getFinalMap
(
context
:
Context
,
imageList
:
ArrayList
<
MediaFile
>):
HashMap
<
String
,
ArrayList
<
HashMap
<
String
,
Any
>>>
{
val
imageListMap
=
ArrayList
<
HashMap
<
String
,
Any
>>();
imageList
.
forEach
{
val
itemMap
=
HashMap
<
String
,
Any
>()
it
.
folderName
?.
run
{
itemMap
.
put
(
"folderName"
,
this
)
}
it
.
path
?.
run
{
itemMap
.
put
(
"path"
,
this
)
}
it
.
size
?.
run
{
itemMap
.
put
(
"size"
,
this
)
}
it
.
realPath
?.
run
{
itemMap
.
put
(
"realPath"
,
this
)
}
imageListMap
.
add
(
itemMap
)
}
synchronized
(
this
)
{
recordImageListMap
.
clear
()
recordImageListMap
.
addAll
(
imageListMap
)
finishOneTask
=
true
}
// imageList.clear();
return
toMap
(
context
,
imageListMap
);
}
private
fun
toMap
(
context
:
Context
,
imageListMap
:
ArrayList
<
HashMap
<
String
,
Any
>>):
HashMap
<
String
,
ArrayList
<
HashMap
<
String
,
Any
>>>
{
val
finalList
=
HashMap
<
String
,
ArrayList
<
HashMap
<
String
,
Any
>>>()
imageListMap
.
forEach
{
it
[
"folderName"
]
?.
run
{
if
(
finalList
[
this
]
==
null
)
{
finalList
[
this
as
String
]
=
ArrayList
<
HashMap
<
String
,
Any
>>()
if
(
it
[
"path"
]
==
null
)
{
val
realPath
=
it
[
"realPath"
]
as
String
val
get
=
Luban
.
with
(
context
).
setTargetDir
(
getImageCacheDir
(
context
,
Luban
.
DEFAULT_DISK_CACHE_DIR
)
!!
.
absolutePath
)
.
setName
(
getFileName
(
realPath
)
!!
)
.
get
(
realPath
);
it
[
"path"
]
=
get
.
absolutePath
Log
.
e
(
"lsy"
,
"封面照片 ${get.absolutePath}"
);
}
finalList
[
this
]
!!
.
add
(
it
);
}
else
{
finalList
[
this
as
String
]
!!
.
add
(
it
);
}
}
}
finalList
[
"IsGengmeiAlbumAllImages"
]
=
imageListMap
;
return
finalList
;
}
companion
object
{
private
var
instance
:
ImageRespository
?
=
null
const
val
TAG
:
String
=
"Image_Picker"
fun
getInstance
():
ImageRespository
{
if
(
instance
==
null
)
{
synchronized
(
ImageRespository
::
class
.
java
)
{
if
(
instance
==
null
)
{
instance
=
ImageRespository
();
}
}
}
return
instance
!!
}
}
}
\ No newline at end of file
android/src/main/java/com/example/gengmei_flutter_plugin/ImagePlugin/repository/bean/MediaFile.kt
0 → 100644
View file @
50d38372
package
com.example.myimagepicker.bean
/**
* Created by lsy
* on 2019/3/27
*/
data class
MediaFile
(
var
path
:
String
?
=
null
,
var
mime
:
String
?
=
null
,
var
folderId
:
Int
?
=
null
,
var
folderName
:
String
?
=
null
,
var
duration
:
Long
=
0
,
var
dateToken
:
Long
=
0
,
var
size
:
Long
=
0
,
var
isBigIm
:
Boolean
=
false
,
var
bigScare
:
Float
=
0f
,
var
realPath
:
String
?
=
null
)
android/src/main/java/com/example/gengmei_flutter_plugin/ImagePlugin/repository/bean/MediaFolder.kt
0 → 100644
View file @
50d38372
package
com.example.myimagepicker.bean
import
java.util.ArrayList
/**
* Created by lsy
* on 2019/3/27
*/
class
MediaFolder
(
folderI
:
Int
,
folderName
:
String
,
folderCover
:
String
,
mediaFileList
:
ArrayList
<
MediaFile
>)
{
var
folderId
:
Int
=
0
var
folderName
:
String
?
=
null
var
folderCover
:
String
?
=
null
var
isCheck
:
Boolean
=
false
var
mediaFileList
:
ArrayList
<
MediaFile
>?
=
null
init
{
this
.
folderId
=
folderI
this
.
folderName
=
folderName
;
this
.
folderCover
=
folderCover
;
this
.
isCheck
=
isCheck
;
this
.
mediaFileList
=
mediaFileList
;
}
}
\ No newline at end of file
android/src/main/java/com/example/gengmei_flutter_plugin/ImagePlugin/repository/config/ConfigManager.kt
0 → 100644
View file @
50d38372
package
com.example.myimagepicker.config
import
android.text.TextUtils
import
com.example.gengmei_flutter_plugin.utils.ImageLoader
import
java.util.ArrayList
/**
* Created by lsy
* on 2019/3/27
*/
class
ConfigManager
private
constructor
()
{
var
title
:
String
?
=
null
//标题
var
selectColor
:
Int
?
=
0
var
isShowCamera
:
Boolean
=
false
//是否显示拍照Item,默认不显示
var
isShowImage
=
true
//是否显示图片,默认显示
var
isShowVideo
=
true
//是否显示视频,默认显示
var
selectionMode
=
SELECT_MODE_SINGLE
//选择模式,默认单选
var
maxCount
=
1
set
(
maxCount
)
{
if
(
maxCount
>
1
)
{
selectionMode
=
SELECT_MODE_MULTI
}
field
=
maxCount
}
//最大选择数量,默认为1
var
imageLoader
:
ImageLoader
?
=
null
@Throws
(
Exception
::
class
)
get
()
{
if
(
field
==
null
)
{
throw
Exception
(
"imageLoader is null"
)
}
return
field
}
companion
object
{
val
SELECT_MODE_SINGLE
=
0
val
SELECT_MODE_MULTI
=
1
@Volatile
private
var
mConfigManager
:
ConfigManager
?
=
null
val
instance
:
ConfigManager
get
()
{
if
(
mConfigManager
==
null
)
{
synchronized
(
ConfigManager
::
class
.
java
)
{
if
(
mConfigManager
==
null
)
{
mConfigManager
=
ConfigManager
()
}
}
}
return
mConfigManager
!!
}
}
}
\ No newline at end of file
android/src/main/java/com/example/gengmei_flutter_plugin/ImagePlugin/repository/local/AbsMediaScanner.kt
0 → 100644
View file @
50d38372
package
com.example.myimagepicker.repository.local
import
android.content.Context
import
android.database.Cursor
import
android.net.Uri
import
android.provider.MediaStore
import
android.util.Log
import
java.io.File
import
java.util.ArrayList
/**
* Created by lsy
* on 2019/3/27
*/
abstract
class
AbsMediaScanner
<
T
>(
private
val
mContext
:
Context
)
{
private
val
filter
:
Int
=
5000
/**
* 查询URI
*
* @return
*/
protected
abstract
val
scanUri
:
Uri
/**
* 查询列名
*
* @return
*/
protected
abstract
val
projection
:
Array
<
String
>
/**
* 查询条件
*
* @return
*/
protected
abstract
val
selection
:
String
/**
* 查询条件值
*
* @return
*/
protected
abstract
val
selectionArgs
:
Array
<
String
>?
/**
* 查询排序
*
* @return
*/
protected
abstract
val
order
:
String
/**
* 对外暴露游标,让开发者灵活构建对象
*
* @param cursor
* @return
*/
protected
abstract
fun
parse
(
cursor
:
Cursor
):
T
/**
* 根据查询条件进行媒体库查询,隐藏查询细节,让开发者更专注业务
*
* @return
*/
fun
queryMedia
():
ArrayList
<
T
>
{
val
list
=
ArrayList
<
T
>()
val
contentResolver
=
mContext
.
contentResolver
val
cursor
=
contentResolver
.
query
(
scanUri
,
projection
,
selection
,
selectionArgs
,
order
)
if
(
cursor
!=
null
&&
cursor
.
moveToFirst
())
{
if
(
cursor
.
getLong
(
cursor
.
getColumnIndex
(
MediaStore
.
Images
.
Media
.
SIZE
))
>=
filter
)
{
val
path
=
cursor
.
getString
(
cursor
.
getColumnIndex
(
MediaStore
.
Images
.
Media
.
DATA
))
if
(
File
(
path
).
exists
()){
val
t
=
parse
(
cursor
)
list
.
add
(
t
)
}
}
while
(
cursor
.
moveToNext
())
{
if
(
cursor
.
getLong
(
cursor
.
getColumnIndex
(
MediaStore
.
Images
.
Media
.
SIZE
))
>=
filter
)
{
val
path
=
cursor
.
getString
(
cursor
.
getColumnIndex
(
MediaStore
.
Images
.
Media
.
DATA
))
if
(
File
(
path
).
exists
()){
val
t
=
parse
(
cursor
)
list
.
add
(
t
)
}
}
}
cursor
.
close
()
}
return
list
}
}
\ No newline at end of file
android/src/main/java/com/example/gengmei_flutter_plugin/ImagePlugin/repository/local/ImageScanner.kt
0 → 100644
View file @
50d38372
package
com.example.myimagepicker.repository.local
import
android.content.Context
import
android.database.Cursor
import
android.graphics.BitmapFactory
import
android.net.Uri
import
android.provider.MediaStore
import
android.util.Log
import
com.example.gengmei_flutter_plugin.utils.MyUtil.Companion.getFileName
import
com.example.gengmei_flutter_plugin.utils.MyUtil.Companion.getImageCacheDir
import
com.example.myimagepicker.bean.MediaFile
import
com.example.myimagepicker.luban.Luban
import
java.io.File
/**
* Created by lsy
* on 2019/3/27
*/
class
ImageScanner
(
var
context
:
Context
)
:
AbsMediaScanner
<
MediaFile
>(
context
)
{
override
val
scanUri
:
Uri
get
()
=
MediaStore
.
Images
.
Media
.
EXTERNAL_CONTENT_URI
override
val
projection
:
Array
<
String
>
get
()
=
arrayOf
(
MediaStore
.
Images
.
Media
.
DATA
,
MediaStore
.
Images
.
Media
.
MIME_TYPE
,
MediaStore
.
Images
.
Media
.
BUCKET_ID
,
MediaStore
.
Images
.
Media
.
BUCKET_DISPLAY_NAME
,
MediaStore
.
Images
.
Media
.
DATE_TAKEN
,
MediaStore
.
Images
.
Media
.
SIZE
)
override
val
selection
:
String
get
()
=
MediaStore
.
Images
.
Media
.
MIME_TYPE
+
"=? or "
+
MediaStore
.
Images
.
Media
.
MIME_TYPE
+
"=?"
+
" or "
+
MediaStore
.
Images
.
Media
.
MIME_TYPE
+
"=?"
override
val
selectionArgs
:
Array
<
String
>
get
()
=
arrayOf
(
"image/jpeg"
,
"image/png"
,
"image/jpg"
// , "image/gif"
)
override
val
order
:
String
get
()
=
MediaStore
.
Images
.
Media
.
DATE_TAKEN
+
" DESC"
/**
* 构建媒体对象
*
* @param cursor
* @return
*/
override
fun
parse
(
cursor
:
Cursor
):
MediaFile
{
val
path
=
cursor
.
getString
(
cursor
.
getColumnIndex
(
MediaStore
.
Images
.
Media
.
DATA
))
val
mime
=
cursor
.
getString
(
cursor
.
getColumnIndex
(
MediaStore
.
Images
.
Media
.
MIME_TYPE
))
val
folderId
=
cursor
.
getInt
(
cursor
.
getColumnIndex
(
MediaStore
.
Images
.
Media
.
BUCKET_ID
))
val
folderName
=
cursor
.
getString
(
cursor
.
getColumnIndex
(
MediaStore
.
Images
.
Media
.
BUCKET_DISPLAY_NAME
))
val
dateToken
=
cursor
.
getLong
(
cursor
.
getColumnIndex
(
MediaStore
.
Images
.
Media
.
DATE_TAKEN
))
val
size
=
cursor
.
getLong
(
cursor
.
getColumnIndex
(
MediaStore
.
Images
.
Media
.
SIZE
))
val
mediaFile
=
MediaFile
()
mediaFile
.
mime
=
mime
mediaFile
.
folderId
=
folderId
mediaFile
.
folderName
=
folderName
mediaFile
.
dateToken
=
dateToken
mediaFile
.
size
=
size
mediaFile
.
realPath
=
path
val
dir
=
getImageCacheDir
(
context
,
Luban
.
DEFAULT_DISK_CACHE_DIR
)
!!
.
absolutePath
;
val
tempFilePngString
=
dir
+
"/"
+
getFileName
(
path
)
!!
+
".png"
;
val
tempFilePngExists
=
File
(
tempFilePngString
).
exists
()
if
(
tempFilePngExists
)
{
mediaFile
.
path
=
tempFilePngString
;
}
val
tempFileJpgString
=
dir
+
"/"
+
getFileName
(
path
)
!!
+
".jpg"
;
val
tempFileJpgExists
=
File
(
tempFileJpgString
).
exists
()
if
(
tempFileJpgExists
)
{
mediaFile
.
path
=
tempFileJpgString
;
}
val
tempFileJpegString
=
dir
+
"/"
+
getFileName
(
path
)
!!
+
".jpeg"
val
tempFileJpegExists
=
File
(
tempFileJpegString
).
exists
()
if
(
tempFileJpegExists
)
{
mediaFile
.
path
=
tempFileJpegString
;
}
if
(
size
<
1024
*
512
)
{
mediaFile
.
path
=
path
}
//
// if (it.size > 1024 * 1024 && !tempFilePngExists
// && !tempFileJpgExists && !tempFileJpegExists) {
// globalThreadPool.execute {
// val get = Luban.with(context).setTargetDir(getImageCacheDir(context, Luban.DEFAULT_DISK_CACHE_DIR)!!.absolutePath)
// .setName(getFileName(path)!!)
// .get(path);
// val options = BitmapFactory.Options();
// options.inJustDecodeBounds = true;
// BitmapFactory.decodeFile(path, options);
// if (options.outHeight >= MAX_SIZE || options.outHeight / options.outWidth > MAX_SCALE) {
// mediaFile.isBigIm = true
//// mediaFile.bigScare = Utils.getImageScale(context, path)
// }
return
mediaFile
}
companion
object
{
private
const
val
MAX_SIZE
=
4096
*
2
private
const
val
MAX_SCALE
=
8
}
}
android/src/main/java/com/example/gengmei_flutter_plugin/ImagePlugin/repository/local/MediaHandler.kt
0 → 100644
View file @
50d38372
package
com.example.myimagepicker.repository.local
import
android.content.Context
import
com.example.myimagepicker.bean.MediaFile
import
com.example.myimagepicker.bean.MediaFolder
import
java.util.*
/**
* Created by lsy
* on 2019/3/27
*/
object
MediaHandler
{
val
ALL_MEDIA_FOLDER
=
-
1
//全部媒体
val
ALL_VIDEO_FOLDER
=
-
2
//全部视频
/**
* 对查询到的图片进行聚类(相册分类)
*
* @param context
* @param imageFileList
* @return
*/
fun
getImageFolder
(
context
:
Context
,
imageFileList
:
ArrayList
<
MediaFile
>):
List
<
MediaFolder
>
{
return
getMediaFolder
(
context
,
imageFileList
,
null
)
}
/**
* 对查询到的视频进行聚类(相册分类)
*
* @param context
* @param imageFileList
* @return
*/
fun
getVideoFolder
(
context
:
Context
,
imageFileList
:
ArrayList
<
MediaFile
>):
List
<
MediaFolder
>
{
return
getMediaFolder
(
context
,
null
,
imageFileList
)
}
/**
* 对查询到的图片和视频进行聚类(相册分类)
*
* @param context
* @param imageFileList
* @param videoFileList
* @return
*/
fun
getMediaFolder
(
context
:
Context
,
imageFileList
:
ArrayList
<
MediaFile
>?,
videoFileList
:
ArrayList
<
MediaFile
>?):
List
<
MediaFolder
>
{
//根据媒体所在文件夹Id进行聚类(相册)
val
mediaFolderMap
=
HashMap
<
Int
,
MediaFolder
>()
//全部图片、视频文件
val
mediaFileList
=
ArrayList
<
MediaFile
>()
if
(
imageFileList
!=
null
)
{
mediaFileList
.
addAll
(
imageFileList
)
}
if
(
videoFileList
!=
null
)
{
mediaFileList
.
addAll
(
videoFileList
)
}
//对媒体数据进行排序
// mediaFileList.sortBy { it.dateToken }
//全部图片或视频
if
(!
mediaFileList
.
isEmpty
())
{
val
allMediaFolder
=
MediaFolder
(
ALL_MEDIA_FOLDER
,
"图片和视频"
,
mediaFileList
[
0
].
path
!!
,
mediaFileList
)
mediaFolderMap
[
ALL_MEDIA_FOLDER
]
=
allMediaFolder
}
//全部视频
if
(
videoFileList
!=
null
&&
!
videoFileList
.
isEmpty
())
{
val
allVideoFolder
=
MediaFolder
(
ALL_VIDEO_FOLDER
,
"所有视频"
,
videoFileList
[
0
].
path
!!
,
videoFileList
)
mediaFolderMap
[
ALL_VIDEO_FOLDER
]
=
allVideoFolder
}
//对图片进行文件夹分类
if
(
imageFileList
!=
null
&&
!
imageFileList
.
isEmpty
())
{
val
size
=
imageFileList
.
size
//添加其他的图片文件夹
for
(
i
in
0
until
size
)
{
val
mediaFile
=
imageFileList
[
i
]
val
imageFolderId
=
mediaFile
.
folderId
var
mediaFolder
:
MediaFolder
?
=
mediaFolderMap
[
imageFolderId
]
if
(
mediaFolder
==
null
)
{
mediaFolder
=
MediaFolder
(
imageFolderId
!!
,
mediaFile
.
folderName
!!
,
mediaFile
.
path
!!
,
ArrayList
<
MediaFile
>())
}
val
imageList
=
mediaFolder
.
mediaFileList
imageList
!!
.
add
(
mediaFile
)
mediaFolder
.
mediaFileList
=
imageList
mediaFolderMap
[
imageFolderId
!!
]
=
mediaFolder
}
}
//整理聚类数据
val
mediaFolderList
=
ArrayList
<
MediaFolder
>()
for
(
folderId
in
mediaFolderMap
.
keys
)
{
if
(
folderId
==
ALL_MEDIA_FOLDER
||
folderId
==
ALL_VIDEO_FOLDER
)
{
mediaFolderList
.
add
(
0
,
mediaFolderMap
[
folderId
]
!!
)
}
else
{
mediaFolderList
.
add
(
mediaFolderMap
[
folderId
]
!!
)
}
}
return
mediaFolderList
}
}
\ No newline at end of file
android/src/main/java/com/example/gengmei_flutter_plugin/ImagePlugin/repository/local/VideoScanner.kt
0 → 100644
View file @
50d38372
package
com.example.myimagepicker.repository.local
import
android.content.Context
import
android.database.Cursor
import
android.net.Uri
import
android.provider.MediaStore
import
com.example.myimagepicker.bean.MediaFile
/**
* Created by lsy
* on 2019/3/27
*/
class
VideoScanner
(
private
val
mContext
:
Context
)
:
AbsMediaScanner
<
MediaFile
>(
mContext
)
{
override
val
scanUri
:
Uri
get
()
=
MediaStore
.
Video
.
Media
.
EXTERNAL_CONTENT_URI
override
val
projection
:
Array
<
String
>
get
()
=
arrayOf
(
MediaStore
.
Video
.
Media
.
DATA
,
MediaStore
.
Video
.
Media
.
MIME_TYPE
,
MediaStore
.
Video
.
Media
.
BUCKET_ID
,
MediaStore
.
Video
.
Media
.
BUCKET_DISPLAY_NAME
,
MediaStore
.
Video
.
Media
.
DURATION
,
MediaStore
.
Video
.
Media
.
DATE_TAKEN
)
override
val
order
:
String
get
()
=
MediaStore
.
Video
.
Media
.
DATE_TAKEN
+
" desc"
override
val
selectionArgs
:
Array
<
String
>?
get
()
=
null
override
val
selection
:
String
get
()
=
""
/**
* 构建媒体对象
*
* @param cursor
* @return
*/
protected
override
fun
parse
(
cursor
:
Cursor
):
MediaFile
{
val
path
=
cursor
.
getString
(
cursor
.
getColumnIndex
(
MediaStore
.
Video
.
Media
.
DATA
))
val
mime
=
cursor
.
getString
(
cursor
.
getColumnIndex
(
MediaStore
.
Video
.
Media
.
MIME_TYPE
))
val
folderId
=
cursor
.
getInt
(
cursor
.
getColumnIndex
(
MediaStore
.
Video
.
Media
.
BUCKET_ID
))
val
folderName
=
cursor
.
getString
(
cursor
.
getColumnIndex
(
MediaStore
.
Video
.
Media
.
BUCKET_DISPLAY_NAME
))
val
duration
=
cursor
.
getLong
(
cursor
.
getColumnIndex
(
MediaStore
.
Video
.
Media
.
DURATION
))
val
dateToken
=
cursor
.
getLong
(
cursor
.
getColumnIndex
(
MediaStore
.
Video
.
Media
.
DATE_TAKEN
))
val
mediaFile
=
MediaFile
()
mediaFile
.
path
=
path
mediaFile
.
mime
=
mime
mediaFile
.
folderId
=
folderId
mediaFile
.
folderName
=
folderName
mediaFile
.
duration
=
duration
mediaFile
.
dateToken
=
dateToken
return
mediaFile
}
companion
object
{
val
ALL_IMAGES_FOLDER
=
-
1
//全部图片
}
}
\ No newline at end of file
android/src/main/java/com/example/gengmei_flutter_plugin/ImagePlugin/repository/luban/Checker.java
0 → 100644
View file @
50d38372
package
com
.
example
.
gengmei_flutter_plugin
.
ImagePlugin
.
repository
.
luban
;
import
android.graphics.BitmapFactory
;
import
android.util.Log
;
import
com.example.myimagepicker.luban.InputStreamProvider
;
import
java.io.ByteArrayOutputStream
;
import
java.io.File
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.util.Arrays
;
public
enum
Checker
{
SINGLE
;
private
static
final
String
TAG
=
"Luban"
;
private
static
final
String
JPG
=
".jpg"
;
private
final
byte
[]
JPEG_SIGNATURE
=
new
byte
[]{(
byte
)
0xFF
,
(
byte
)
0xD8
,
(
byte
)
0xFF
};
/**
* Determine if it is JPG.
*
* @param is image file input stream
*/
public
boolean
isJPG
(
InputStream
is
)
{
return
isJPG
(
toByteArray
(
is
));
}
/**
* Returns the degrees in clockwise. Values are 0, 90, 180, or 270.
*/
public
int
getOrientation
(
InputStream
is
)
{
return
getOrientation
(
toByteArray
(
is
));
}
private
boolean
isJPG
(
byte
[]
data
)
{
if
(
data
==
null
||
data
.
length
<
3
)
{
return
false
;
}
byte
[]
signatureB
=
new
byte
[]{
data
[
0
],
data
[
1
],
data
[
2
]};
return
Arrays
.
equals
(
JPEG_SIGNATURE
,
signatureB
);
}
private
int
getOrientation
(
byte
[]
jpeg
)
{
if
(
jpeg
==
null
)
{
return
0
;
}
int
offset
=
0
;
int
length
=
0
;
// ISO/IEC 10918-1:1993(E)
while
(
offset
+
3
<
jpeg
.
length
&&
(
jpeg
[
offset
++]
&
0xFF
)
==
0xFF
)
{
int
marker
=
jpeg
[
offset
]
&
0xFF
;
// Check if the marker is a padding.
if
(
marker
==
0xFF
)
{
continue
;
}
offset
++;
// Check if the marker is SOI or TEM.
if
(
marker
==
0xD8
||
marker
==
0x01
)
{
continue
;
}
// Check if the marker is EOI or SOS.
if
(
marker
==
0xD9
||
marker
==
0xDA
)
{
break
;
}
// Get the length and check if it is reasonable.
length
=
pack
(
jpeg
,
offset
,
2
,
false
);
if
(
length
<
2
||
offset
+
length
>
jpeg
.
length
)
{
Log
.
e
(
TAG
,
"Invalid length"
);
return
0
;
}
// Break if the marker is EXIF in APP1.
if
(
marker
==
0xE1
&&
length
>=
8
&&
pack
(
jpeg
,
offset
+
2
,
4
,
false
)
==
0x45786966
&&
pack
(
jpeg
,
offset
+
6
,
2
,
false
)
==
0
)
{
offset
+=
8
;
length
-=
8
;
break
;
}
// Skip other markers.
offset
+=
length
;
length
=
0
;
}
// JEITA CP-3451 Exif Version 2.2
if
(
length
>
8
)
{
// Identify the byte order.
int
tag
=
pack
(
jpeg
,
offset
,
4
,
false
);
if
(
tag
!=
0x49492A00
&&
tag
!=
0x4D4D002A
)
{
Log
.
e
(
TAG
,
"Invalid byte order"
);
return
0
;
}
boolean
littleEndian
=
(
tag
==
0x49492A00
);
// Get the offset and check if it is reasonable.
int
count
=
pack
(
jpeg
,
offset
+
4
,
4
,
littleEndian
)
+
2
;
if
(
count
<
10
||
count
>
length
)
{
Log
.
e
(
TAG
,
"Invalid offset"
);
return
0
;
}
offset
+=
count
;
length
-=
count
;
// Get the count and go through all the elements.
count
=
pack
(
jpeg
,
offset
-
2
,
2
,
littleEndian
);
while
(
count
--
>
0
&&
length
>=
12
)
{
// Get the tag and check if it is orientation.
tag
=
pack
(
jpeg
,
offset
,
2
,
littleEndian
);
if
(
tag
==
0x0112
)
{
int
orientation
=
pack
(
jpeg
,
offset
+
8
,
2
,
littleEndian
);
switch
(
orientation
)
{
case
1
:
return
0
;
case
3
:
return
180
;
case
6
:
return
90
;
case
8
:
return
270
;
}
Log
.
e
(
TAG
,
"Unsupported orientation"
);
return
0
;
}
offset
+=
12
;
length
-=
12
;
}
}
Log
.
e
(
TAG
,
"Orientation not found"
);
return
0
;
}
public
String
extSuffix
(
InputStreamProvider
input
)
{
try
{
BitmapFactory
.
Options
options
=
new
BitmapFactory
.
Options
();
options
.
inJustDecodeBounds
=
true
;
BitmapFactory
.
decodeStream
(
input
.
open
(),
null
,
options
);
return
options
.
outMimeType
.
replace
(
"image/"
,
"."
);
}
catch
(
Exception
e
)
{
return
JPG
;
}
}
public
boolean
needCompress
(
int
leastCompressSize
,
String
path
)
{
if
(
leastCompressSize
>
0
)
{
File
source
=
new
File
(
path
);
return
source
.
exists
()
&&
source
.
length
()
>
(
leastCompressSize
<<
10
);
}
return
true
;
}
private
int
pack
(
byte
[]
bytes
,
int
offset
,
int
length
,
boolean
littleEndian
)
{
int
step
=
1
;
if
(
littleEndian
)
{
offset
+=
length
-
1
;
step
=
-
1
;
}
int
value
=
0
;
while
(
length
--
>
0
)
{
value
=
(
value
<<
8
)
|
(
bytes
[
offset
]
&
0xFF
);
offset
+=
step
;
}
return
value
;
}
private
byte
[]
toByteArray
(
InputStream
is
)
{
if
(
is
==
null
)
{
return
new
byte
[
0
];
}
ByteArrayOutputStream
buffer
=
new
ByteArrayOutputStream
();
int
read
;
byte
[]
data
=
new
byte
[
4096
];
try
{
while
((
read
=
is
.
read
(
data
,
0
,
data
.
length
))
!=
-
1
)
{
buffer
.
write
(
data
,
0
,
read
);
}
}
catch
(
Exception
ignored
)
{
return
new
byte
[
0
];
}
finally
{
try
{
buffer
.
close
();
}
catch
(
IOException
ignored
)
{
}
}
return
buffer
.
toByteArray
();
}
}
android/src/main/java/com/example/gengmei_flutter_plugin/ImagePlugin/repository/luban/CompressionPredicate.kt
0 → 100644
View file @
50d38372
package
com.example.myimagepicker.luban
/**
* Created by lsy
* on 2019/3/29
*/
interface
CompressionPredicate
{
/**
* Determine the given input path should be compressed and return a boolean.
* @param path input path
* @return the boolean result
*/
fun
apply
(
path
:
String
):
Boolean
}
\ No newline at end of file
android/src/main/java/com/example/gengmei_flutter_plugin/ImagePlugin/repository/luban/Engine.kt
0 → 100644
View file @
50d38372
package
com.example.myimagepicker.luban
import
android.graphics.Bitmap
import
android.graphics.BitmapFactory
import
android.graphics.Matrix
import
android.util.Log
import
com.example.gengmei_flutter_plugin.ImagePlugin.repository.luban.Checker
import
java.io.ByteArrayOutputStream
import
java.io.File
import
java.io.FileOutputStream
import
java.io.IOException
/**
* Created by lsy
* on 2019/3/29
*/
internal
class
Engine
@Throws
(
IOException
::
class
)
constructor
(
private
val
srcImg
:
InputStreamProvider
,
private
val
tagImgPath
:
String
,
private
val
focusAlpha
:
Boolean
,
val
quality
:
Int
)
{
private
var
srcWidth
:
Int
=
0
private
var
srcHeight
:
Int
=
0
init
{
val
options
=
BitmapFactory
.
Options
()
options
.
inJustDecodeBounds
=
true
options
.
inSampleSize
=
1
BitmapFactory
.
decodeStream
(
srcImg
.
open
(),
null
,
options
)
this
.
srcWidth
=
options
.
outWidth
this
.
srcHeight
=
options
.
outHeight
}
private
fun
computeSize
():
Int
{
srcWidth
=
if
(
srcWidth
%
2
==
1
)
srcWidth
+
1
else
srcWidth
srcHeight
=
if
(
srcHeight
%
2
==
1
)
srcHeight
+
1
else
srcHeight
val
longSide
=
Math
.
max
(
srcWidth
,
srcHeight
)
val
shortSide
=
Math
.
min
(
srcWidth
,
srcHeight
)
val
scale
=
shortSide
.
toFloat
()
/
longSide
return
if
(
scale
<=
1
&&
scale
>
0.5625
)
{
if
(
longSide
<
1664
)
{
1
}
else
if
(
longSide
<
4990
)
{
2
}
else
if
(
longSide
>
4990
&&
longSide
<
10240
)
{
4
}
else
{
if
(
longSide
/
1280
==
0
)
1
else
longSide
/
1280
}
}
else
if
(
scale
<=
0.5625
&&
scale
>
0.5
)
{
if
(
longSide
/
1280
==
0
)
1
else
longSide
/
1280
}
else
{
Math
.
ceil
(
longSide
/
(
1280.0
/
scale
)).
toInt
()
}
}
private
fun
rotatingImage
(
bitmap
:
Bitmap
?,
angle
:
Int
):
Bitmap
{
val
matrix
=
Matrix
()
matrix
.
postRotate
(
angle
.
toFloat
())
return
Bitmap
.
createBitmap
(
bitmap
!!
,
0
,
0
,
bitmap
.
width
,
bitmap
.
height
,
matrix
,
true
)
}
@Throws
(
IOException
::
class
)
fun
compress
():
File
{
val
options
=
BitmapFactory
.
Options
()
if
(
quality
==
100
)
{
options
.
inSampleSize
=
computeSize
()
}
else
{
options
.
inSampleSize
=
(
srcWidth
/
240
).
toInt
();
}
// Log.e("lsy"," SAMPLE SIZE ${options.inSampleSize} ${srcWidth}")
var
tagBitmap
=
BitmapFactory
.
decodeStream
(
srcImg
.
open
(),
null
,
options
)
val
stream
=
ByteArrayOutputStream
()
if
(
Checker
.
SINGLE
.
isJPG
(
srcImg
.
open
()))
{
tagBitmap
=
rotatingImage
(
tagBitmap
,
Checker
.
SINGLE
.
getOrientation
(
srcImg
.
open
()))
}
// val tagBitmap1 = imageScale(tagBitmap, 480);
tagBitmap
!!
.
compress
(
if
(
focusAlpha
)
Bitmap
.
CompressFormat
.
PNG
else
Bitmap
.
CompressFormat
.
JPEG
,
if
(
quality
!=
0
)
quality
else
70
,
stream
)
// val width = tagBitmap.width
// val height = tagBitmap.height
tagBitmap
.
recycle
()
// val split = tagImgPath.split(".")
// var before: String
// var after: String
// after = split[split.size - 1]
// before = tagImgPath.replace("." + after, "")
val
file
=
File
(
tagImgPath
)
val
fos
=
FileOutputStream
(
file
)
fos
.
write
(
stream
.
toByteArray
())
fos
.
flush
()
fos
.
close
()
stream
.
close
()
return
file
}
private
val
matrix
by
lazy
{
Matrix
()
}
private
fun
imageScale
(
bitmap
:
Bitmap
,
targetSize
:
Int
):
Bitmap
{
val
scareSize
=
targetSize
/
bitmap
.
width
.
toFloat
()
// Log.e("lsy"," ${targetSize} ${srcWidth} ${srcWidth}")
val
width
=
bitmap
.
width
*
scareSize
val
height
=
bitmap
.
height
*
scareSize
;
matrix
.
reset
();
matrix
.
postScale
(
width
.
toFloat
(),
height
.
toFloat
());
val
dstbmp
=
Bitmap
.
createBitmap
(
bitmap
,
0
,
0
,
width
.
toInt
(),
height
.
toInt
(),
matrix
,
true
);
return
dstbmp
}
}
\ No newline at end of file
android/src/main/java/com/example/gengmei_flutter_plugin/ImagePlugin/repository/luban/InputStreamAdapter.kt
0 → 100644
View file @
50d38372
package
com.example.myimagepicker.luban
import
java.io.IOException
import
java.io.InputStream
/**
* Created by lsy
* on 2019/3/29
*/
abstract
class
InputStreamAdapter
:
InputStreamProvider
{
private
var
inputStream
:
InputStream
?
=
null
@Throws
(
IOException
::
class
)
override
fun
open
():
InputStream
?
{
close
()
inputStream
=
openInternal
()
return
inputStream
}
@Throws
(
IOException
::
class
)
abstract
fun
openInternal
():
InputStream
?
override
fun
close
()
{
if
(
inputStream
!=
null
)
{
try
{
inputStream
!!
.
close
()
}
catch
(
ignore
:
IOException
)
{
}
finally
{
inputStream
=
null
}
}
}
}
\ No newline at end of file
android/src/main/java/com/example/gengmei_flutter_plugin/ImagePlugin/repository/luban/InputStreamProvider.kt
0 → 100644
View file @
50d38372
package
com.example.myimagepicker.luban
import
java.io.IOException
import
java.io.InputStream
/**
* Created by lsy
* on 2019/3/29
*/
interface
InputStreamProvider
{
val
path
:
String
?
@Throws
(
IOException
::
class
)
fun
open
():
InputStream
?
fun
close
()
}
android/src/main/java/com/example/gengmei_flutter_plugin/ImagePlugin/repository/luban/Luban.kt
0 → 100644
View file @
50d38372
This diff is collapsed.
Click to expand it.
android/src/main/java/com/example/gengmei_flutter_plugin/ImagePlugin/repository/luban/OnCompressListener.kt
0 → 100644
View file @
50d38372
package
com.example.myimagepicker.luban
import
java.io.File
/**
* Created by lsy
* on 2019/3/29
*/
interface
OnCompressListener
{
/**
* Fired when the compression is started, override to handle in your own code
*/
fun
onStart
()
/**
* Fired when a compression returns successfully, override to handle in your own code
*/
fun
onSuccess
(
file
:
File
)
/**
* Fired when a compression fails to complete, override to handle in your own code
*/
fun
onError
(
e
:
Throwable
)
}
android/src/main/java/com/example/gengmei_flutter_plugin/ImagePlugin/repository/luban/OnRenameListener.kt
0 → 100644
View file @
50d38372
package
com.example.myimagepicker.luban
/**
* Created by lsy
* on 2019/3/29
*/
interface
OnRenameListener
{
/**
* 压缩前调用该方法用于修改压缩后文件名
*
*
* Call before compression begins.
*
* @param filePath 传入文件路径/ file path
* @return 返回重命名后的字符串/ file name
*/
fun
rename
(
filePath
:
String
):
String
}
\ No newline at end of file
android/src/main/java/com/example/gengmei_flutter_plugin/a
0 → 100644
View file @
50d38372
android/src/main/java/com/example/gengmei_flutter_plugin/ex/RxExpecition.kt
0 → 100644
View file @
50d38372
package
com.example.gengmei_flutter_plugin.ex
/**
* @author lsy
* @date 2019-09-26
*/
class
RxExpecition
(
message
:
String
?)
:
Exception
(
message
)
{
}
\ No newline at end of file
android/src/main/java/com/example/gengmei_flutter_plugin/result/ResultManager.kt
0 → 100644
View file @
50d38372
package
com.example.gengmei_flutter_plugin.result
import
android.util.Log
import
android.util.SparseArray
import
io.flutter.plugin.common.MethodChannel
/**
* @author lsy
* @date 2019-09-25
*/
class
ResultManager
private
constructor
()
{
val
map
=
HashMap
<
Long
,
MethodChannel
.
Result
>();
init
{
}
fun
addResult
(
key
:
Long
,
result
:
MethodChannel
.
Result
)
{
map
.
put
(
key
,
result
)
}
fun
resultSuccess
(
key
:
Long
,
value
:
Any
)
{
Log
.
e
(
"lsy"
,
"KEYYY $key "
)
map
.
get
(
key
)
?.
run
{
this
.
success
(
value
);
}
map
.
remove
(
key
)
Log
.
e
(
"lsy"
,
" ${map.size}"
)
}
fun
resultError
(
key
:
Long
,
message
:
String
,
ob
:
Any
)
{
map
.
get
(
key
)
?.
run
{
this
.
error
(
message
,
message
,
ob
)
}
map
.
remove
(
key
)
Log
.
e
(
"lsy"
,
" ${map.size}"
)
}
companion
object
{
private
val
instance
=
ResultManager
();
@JvmStatic
fun
getInstance
():
ResultManager
{
return
instance
;
}
}
}
\ No newline at end of file
android/src/main/java/com/example/gengmei_flutter_plugin/sharedPrefernces/SharedManager.kt
0 → 100644
View file @
50d38372
package
com.example.gengmei_flutter_plugin.sharedPrefernces
import
android.app.Application
import
android.content.Context
import
android.content.SharedPreferences
import
com.example.gengmei_flutter_plugin.ex.RxExpecition
import
io.reactivex.Observable
import
io.reactivex.ObservableOnSubscribe
import
io.reactivex.android.schedulers.AndroidSchedulers
import
io.reactivex.schedulers.Schedulers
/**
* @author lsy
* @date 2019-09-25
*/
class
SharedManager
private
constructor
(
app
:
Context
)
{
private
val
preferences
:
SharedPreferences
init
{
preferences
=
app
.
getSharedPreferences
(
SHARED_PREFERENCES_NAME
,
Context
.
MODE_PRIVATE
);
}
companion
object
{
const
val
SHARED_PREFERENCES_NAME
=
"FlutterSharedPreferences"
@Volatile
private
var
instance
:
SharedManager
?=
null
;
@JvmStatic
fun
getInstance
(
app
:
Context
):
SharedManager
{
if
(
instance
==
null
)
{
synchronized
(
this
)
{
if
(
instance
==
null
)
{
instance
=
SharedManager
(
app
);
}
}
}
return
instance
!!
}
}
fun
saveInt
(
key
:
String
,
value
:
Int
):
Observable
<
Boolean
>
{
return
Observable
.
create
(
ObservableOnSubscribe
<
Boolean
>
{
it
.
onNext
(
preferences
.
edit
().
putInt
(
key
,
value
).
commit
())
}).
subscribeOn
(
Schedulers
.
io
()).
observeOn
(
AndroidSchedulers
.
mainThread
());
}
fun
saveString
(
key
:
String
,
value
:
String
):
Observable
<
Boolean
>
{
return
Observable
.
create
(
ObservableOnSubscribe
<
Boolean
>
{
it
.
onNext
(
preferences
.
edit
().
putString
(
key
,
value
).
commit
())
}).
subscribeOn
(
Schedulers
.
io
()).
observeOn
(
AndroidSchedulers
.
mainThread
());
}
fun
saveBoolean
(
key
:
String
,
value
:
Boolean
):
Observable
<
Boolean
>
{
return
Observable
.
create
(
ObservableOnSubscribe
<
Boolean
>
{
it
.
onNext
(
preferences
.
edit
().
putBoolean
(
key
,
value
).
commit
())
}).
subscribeOn
(
Schedulers
.
io
()).
observeOn
(
AndroidSchedulers
.
mainThread
());
}
fun
saveFloat
(
key
:
String
,
value
:
Float
):
Observable
<
Boolean
>
{
return
Observable
.
create
(
ObservableOnSubscribe
<
Boolean
>
{
it
.
onNext
(
preferences
.
edit
().
putFloat
(
key
,
value
).
commit
())
}).
subscribeOn
(
Schedulers
.
io
()).
observeOn
(
AndroidSchedulers
.
mainThread
());
}
fun
saveStringList
(
key
:
String
,
value
:
Set
<
String
>):
Observable
<
Boolean
>
{
return
Observable
.
create
(
ObservableOnSubscribe
<
Boolean
>
{
it
.
onNext
(
preferences
.
edit
().
putStringSet
(
key
,
value
).
commit
())
}).
subscribeOn
(
Schedulers
.
io
()).
observeOn
(
AndroidSchedulers
.
mainThread
());
}
fun
getInt
(
key
:
String
,
value
:
Int
):
Observable
<
Int
>
{
return
Observable
.
create
(
ObservableOnSubscribe
<
Int
>
{
it
.
onNext
(
preferences
.
getInt
(
key
,
value
))
}).
subscribeOn
(
Schedulers
.
io
()).
observeOn
(
AndroidSchedulers
.
mainThread
());
}
fun
getString
(
key
:
String
,
value
:
String
?):
Observable
<
String
?>
{
return
Observable
.
create
(
ObservableOnSubscribe
<
String
>
{
val
string
=
preferences
.
getString
(
key
,
value
)
if
(
string
==
null
){
it
.
onNext
(
""
)
}
else
{
it
.
onNext
(
string
)
}
}).
subscribeOn
(
Schedulers
.
io
()).
observeOn
(
AndroidSchedulers
.
mainThread
());
}
fun
getFloat
(
key
:
String
,
value
:
Float
):
Observable
<
Float
>
{
return
Observable
.
create
(
ObservableOnSubscribe
<
Float
>
{
it
.
onNext
(
preferences
.
getFloat
(
key
,
value
))
}).
subscribeOn
(
Schedulers
.
io
()).
observeOn
(
AndroidSchedulers
.
mainThread
());
}
fun
getBoolean
(
key
:
String
,
value
:
Boolean
):
Observable
<
Boolean
>
{
return
Observable
.
create
(
ObservableOnSubscribe
<
Boolean
>
{
it
.
onNext
(
preferences
.
getBoolean
(
key
,
value
))
}).
subscribeOn
(
Schedulers
.
io
()).
observeOn
(
AndroidSchedulers
.
mainThread
());
}
fun
getStringList
(
key
:
String
,
value
:
Set
<
String
>?):
Observable
<
ArrayList
<
String
>>
{
return
Observable
.
create
(
ObservableOnSubscribe
<
ArrayList
<
String
>>
{
val
stringSet
=
preferences
.
getStringSet
(
key
,
value
)
if
(
stringSet
==
null
){
throw
RxExpecition
(
"NULL!!"
)
}
val
temp
=
ArrayList
<
String
>()
temp
.
addAll
(
stringSet
)
it
.
onNext
(
temp
)
}).
subscribeOn
(
Schedulers
.
io
()).
observeOn
(
AndroidSchedulers
.
mainThread
());
}
}
\ No newline at end of file
android/src/main/java/com/example/gengmei_flutter_plugin/utils/DebugUtil.java
0 → 100644
View file @
50d38372
package
com
.
example
.
gengmei_flutter_plugin
.
utils
;
import
android.util.Log
;
import
com.example.gengmei_flutter_plugin.BuildConfig
;
public
class
DebugUtil
{
private
static
final
String
TAG
=
"GENGMEI_FLUTTER_PLUGIN"
;
private
static
boolean
DBG
=
BuildConfig
.
DEBUG
;
public
static
void
printStackTrace
(
Throwable
throwable
)
{
if
(
DBG
)
{
throwable
.
printStackTrace
();
}
Log
.
e
(
TAG
,
throwable
.
getMessage
());
}
}
android/src/main/java/com/example/gengmei_flutter_plugin/utils/DimensionUtils.java
0 → 100644
View file @
50d38372
package
com
.
example
.
gengmei_flutter_plugin
.
utils
;
import
android.annotation.SuppressLint
;
import
android.content.Context
;
import
android.util.DisplayMetrics
;
import
android.util.Size
;
import
android.util.TypedValue
;
import
android.view.WindowManager
;
import
java.util.Arrays
;
import
java.util.Collections
;
import
java.util.Comparator
;
import
java.util.List
;
public
class
DimensionUtils
{
public
static
final
int
KB
=
1024
;
public
static
final
int
MB
=
1024
*
1024
;
public
static
final
int
RECORD_PHOTO_MAX_SIZE
=
4
*
MB
;
public
static
int
dp2Px
(
Context
context
,
float
dp
)
{
final
float
scale
=
context
.
getResources
().
getDisplayMetrics
().
density
;
return
(
int
)
(
dp
*
scale
+
0.5f
);
}
public
static
float
cm2Feet
(
float
cm
)
{
return
Math
.
round
((
cm
/
2.54
F
)
*
100
)
/
100
F
;
}
public
static
float
feetToCm
(
int
feet
,
int
second
)
{
int
feet2Inch
=
feet
*
12
;
return
(
feet2Inch
+
second
)
*
2.54
F
;
}
public
static
float
feetToCm
(
int
[]
feet
)
{
return
feetToCm
(
feet
[
0
],
feet
[
1
]);
}
public
static
boolean
twoFloatEqual
(
float
a
,
float
b
)
{
return
Math
.
abs
(
a
-
b
)
<
10
e
-
6
;
}
public
static
boolean
twoDoubleEqual
(
double
a
,
double
b
)
{
return
Math
.
abs
(
a
-
b
)
<
10
e
-
6
;
}
@SuppressLint
(
"NewApi"
)
public
static
Size
getOptimalCameraSize
(
Size
[]
sizes
,
boolean
swappedDimension
,
int
viewWidth
)
{
boolean
found
=
false
;
int
index
=
0
;
int
largestArea
=
Integer
.
MIN_VALUE
;
// found the w/h is 3:4 size
for
(
int
i
=
0
;
i
<
sizes
.
length
;
i
++)
{
int
realW
=
swappedDimension
?
sizes
[
i
].
getHeight
()
:
sizes
[
i
].
getWidth
();
int
realH
=
swappedDimension
?
sizes
[
i
].
getWidth
()
:
sizes
[
i
].
getHeight
();
float
ratio
=
(
float
)
realW
/
realH
;
int
area
=
realH
*
realW
;
if
(
realW
>=
viewWidth
&&
twoFloatEqual
(
ratio
,
0.75
F
))
{
found
=
true
;
if
(
largestArea
<
area
)
{
index
=
i
;
largestArea
=
area
;
}
}
}
if
(
found
)
{
return
sizes
[
index
];
}
index
=
0
;
largestArea
=
Integer
.
MIN_VALUE
;
// if not found, found the w/h close and bigger than 3:4
for
(
int
i
=
0
;
i
<
sizes
.
length
;
i
++)
{
int
realW
=
swappedDimension
?
sizes
[
i
].
getHeight
()
:
sizes
[
i
].
getWidth
();
int
realH
=
swappedDimension
?
sizes
[
i
].
getWidth
()
:
sizes
[
i
].
getHeight
();
float
ratio
=
(
float
)
realW
/
realH
;
int
area
=
realH
*
realW
;
if
(
realW
>=
viewWidth
&&
ratio
>
0.75
)
{
if
(
largestArea
<
area
)
{
largestArea
=
area
;
index
=
i
;
}
}
}
return
sizes
[
index
];
}
public
static
List
<
Size
>
sortSizes
(
Size
[]
sizes
)
{
List
list
=
Arrays
.
asList
(
sizes
);
Collections
.
sort
(
list
,
new
CompareSizesByArea
());
return
list
;
}
/**
* Compares two {@code Size}s based on their areas.
*/
@SuppressLint
(
"NewApi"
)
static
class
CompareSizesByArea
implements
Comparator
<
Size
>
{
@Override
public
int
compare
(
Size
lhs
,
Size
rhs
)
{
// We cast here to ensure the multiplications won't overflow
return
Long
.
signum
((
long
)
lhs
.
getWidth
()
*
lhs
.
getHeight
()
-
(
long
)
rhs
.
getWidth
()
*
rhs
.
getHeight
());
}
}
public
static
int
getScreenWidth
(
Context
context
){
DisplayMetrics
displayMetrics
=
new
DisplayMetrics
();
((
WindowManager
)
(
context
.
getSystemService
(
Context
.
WINDOW_SERVICE
))).
getDefaultDisplay
().
getMetrics
(
displayMetrics
);
return
displayMetrics
.
widthPixels
;
}
public
static
int
getScreenHeight
(
Context
context
){
DisplayMetrics
displayMetrics
=
new
DisplayMetrics
();
((
WindowManager
)
(
context
.
getSystemService
(
Context
.
WINDOW_SERVICE
))).
getDefaultDisplay
().
getMetrics
(
displayMetrics
);
return
displayMetrics
.
heightPixels
;
}
}
android/src/main/java/com/example/gengmei_flutter_plugin/utils/FileUtil.java
0 → 100644
View file @
50d38372
package
com
.
example
.
gengmei_flutter_plugin
.
utils
;
import
android.content.Context
;
import
android.util.Log
;
import
java.io.File
;
import
java.io.FileNotFoundException
;
import
java.io.FileOutputStream
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.OutputStream
;
public
class
FileUtil
{
public
static
void
copyFilesFromAssets
(
Context
context
,
String
oldPath
,
String
newPath
)
{
try
{
String
[]
fileNames
=
context
.
getAssets
().
list
(
oldPath
);
if
(
fileNames
.
length
>
0
)
{
// directory
File
file
=
new
File
(
newPath
);
if
(!
file
.
mkdirs
())
{
Log
.
d
(
"mkdir"
,
"can't make folder"
);
}
for
(
String
fileName
:
fileNames
)
{
copyFilesFromAssets
(
context
,
oldPath
+
"/"
+
fileName
,
newPath
+
"/"
+
fileName
);
}
}
else
{
// file
InputStream
is
=
context
.
getAssets
().
open
(
oldPath
);
FileOutputStream
fos
=
new
FileOutputStream
(
new
File
(
newPath
));
byte
[]
buffer
=
new
byte
[
1024
];
int
byteCount
;
while
((
byteCount
=
is
.
read
(
buffer
))
!=
-
1
)
{
fos
.
write
(
buffer
,
0
,
byteCount
);
}
fos
.
flush
();
is
.
close
();
fos
.
close
();
}
}
catch
(
Exception
e
)
{
// TODO Auto-generated catch block
e
.
printStackTrace
();
}
}
public
static
void
copyAssetsFileToSD
(
Context
context
,
String
name
,
String
predictorPath
)
{
// File file = new File(predictorPath);
// if (file.exists()) {
// return;
// }
InputStream
myInput
=
null
;
OutputStream
myOutput
=
null
;
try
{
myOutput
=
new
FileOutputStream
(
predictorPath
);
myInput
=
context
.
getAssets
().
open
(
name
);
byte
[]
buffer
=
new
byte
[
1024
];
int
length
=
myInput
.
read
(
buffer
);
while
(
length
>
0
)
{
myOutput
.
write
(
buffer
,
0
,
length
);
length
=
myInput
.
read
(
buffer
);
}
}
catch
(
FileNotFoundException
e
)
{
e
.
printStackTrace
();
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
finally
{
try
{
myOutput
.
flush
();
myInput
.
close
();
myOutput
.
close
();
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
catch
(
NullPointerException
e
)
{
e
.
printStackTrace
();
}
}
}
}
android/src/main/java/com/example/gengmei_flutter_plugin/utils/ImageLoader.kt
0 → 100644
View file @
50d38372
package
com.example.gengmei_flutter_plugin.utils
import
android.widget.ImageView
import
java.io.Serializable
/**
* Created by lsy
* on 2019/3/27
*/
interface
ImageLoader
:
Serializable
{
/**
* 缩略图加载方案
*
* @param imageView
* @param imagePath
*/
fun
loadImage
(
imageView
:
ImageView
,
imagePath
:
String
)
/**
* 大图加载方案
*
* @param imageView
* @param imagePath
*/
fun
loadPreImage
(
imageView
:
ImageView
,
imagePath
:
String
)
/**
* 视频播放方案
*
* @param imageView
* @param path
*/
// void loadVideoPlay(ImageView imageView, String path);
/**
* 缓存管理
*/
fun
clearMemoryCache
()
}
\ No newline at end of file
android/src/main/java/com/example/gengmei_flutter_plugin/utils/KTUtil.kt
0 → 100644
View file @
50d38372
package
com.example.gengmei_flutter_plugin.utils
import
android.graphics.Paint
import
android.os.Handler
import
android.text.TextUtils
import
android.util.Log
import
android.view.View
import
io.reactivex.disposables.CompositeDisposable
import
io.reactivex.disposables.Disposable
import
java.io.File
import
java.text.SimpleDateFormat
/**
* Created by lsy
* on 2019/4/18
*/
fun
Any
?.
isNull
():
Boolean
{
return
this
==
null
}
fun
String
.
splitU
(
s
:
String
):
List
<
String
>?
{
if
(
this
.
contains
(
s
))
{
return
this
.
split
(
s
)
}
return
null
}
fun
Disposable
?.
addTo
(
disposable
:
CompositeDisposable
?)
{
if
(
disposable
!=
null
&&
this
!=
null
)
{
disposable
.
add
(
this
)
}
}
fun
String
?.
empty
():
Boolean
{
return
TextUtils
.
isEmpty
(
this
)
}
android/src/main/java/com/example/gengmei_flutter_plugin/utils/MyUtil.kt
0 → 100644
View file @
50d38372
package
com.example.gengmei_flutter_plugin.utils
import
android.content.Context
import
android.util.Log
import
com.example.myimagepicker.luban.Luban
import
java.io.File
/**
* @author lsy
* @date 2019-09-10
*/
class
MyUtil
{
companion
object
{
fun
getImageCacheDir
(
context
:
Context
,
cacheName
:
String
):
File
?
{
val
cacheDir
=
context
.
externalCacheDir
if
(
cacheDir
!=
null
)
{
val
result
=
File
(
cacheDir
,
cacheName
)
return
if
(!
result
.
mkdirs
()
&&
(!
result
.
exists
()
||
!
result
.
isDirectory
))
{
// File wasn't able to create a directory, or the result exists but not a directory
null
}
else
result
}
if
(
Log
.
isLoggable
(
Luban
.
TAG
,
Log
.
ERROR
))
{
Log
.
e
(
Luban
.
TAG
,
"default disk cache dir is null"
)
}
return
null
}
fun
getFileName
(
pathandname
:
String
):
String
?
{
val
start
=
pathandname
.
lastIndexOf
(
"/"
)
val
end
=
pathandname
.
lastIndexOf
(
"."
)
return
if
(
start
!=
-
1
&&
end
!=
-
1
)
{
pathandname
.
substring
(
start
+
1
,
end
)
}
else
{
null
}
}
fun
getFileFullName
(
pathandname
:
String
):
String
?
{
val
start
=
pathandname
.
lastIndexOf
(
"/"
)
val
end
=
pathandname
.
lastIndexOf
(
"."
)
return
if
(
start
!=
-
1
&&
end
!=
-
1
)
{
pathandname
.
substring
(
start
+
1
,
pathandname
.
length
)
}
else
{
null
}
}
}
}
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