Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
S
ShareExtend
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
李增强
ShareExtend
Commits
2904f3db
Commit
2904f3db
authored
Mar 30, 2020
by
zhouteng
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
rebuild provider code
parent
6f87f891
Changes
8
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
297 additions
and
128 deletions
+297
-128
android/src/main/AndroidManifest.xml
android/src/main/AndroidManifest.xml
+0
-3
android/src/main/java/com/zt/shareextend/MimeUtils.java
android/src/main/java/com/zt/shareextend/MimeUtils.java
+129
-0
android/src/main/java/com/zt/shareextend/ShareExtendPlugin.java
...d/src/main/java/com/zt/shareextend/ShareExtendPlugin.java
+1
-1
android/src/main/java/com/zt/shareextend/ShareExtendProvider.java
...src/main/java/com/zt/shareextend/ShareExtendProvider.java
+156
-2
android/src/main/java/com/zt/shareextend/ShareUtils.java
android/src/main/java/com/zt/shareextend/ShareUtils.java
+7
-113
android/src/main/res/xml/share_extend_provider_path.xml
android/src/main/res/xml/share_extend_provider_path.xml
+0
-8
example/android/app/src/main/AndroidManifest.xml
example/android/app/src/main/AndroidManifest.xml
+1
-0
example/lib/main.dart
example/lib/main.dart
+3
-1
No files found.
android/src/main/AndroidManifest.xml
View file @
2904f3db
...
...
@@ -8,9 +8,6 @@
android:authorities=
"${applicationId}.shareextend.fileprovider"
android:exported=
"false"
android:grantUriPermissions=
"true"
>
<meta-data
android:name=
"android.support.FILE_PROVIDER_PATHS"
android:resource=
"@xml/share_extend_provider_path"
/>
</provider>
</application>
...
...
android/src/main/java/com/zt/shareextend/MimeUtils.java
0 → 100644
View file @
2904f3db
package
com.zt.shareextend
;
import
android.text.TextUtils
;
import
android.webkit.MimeTypeMap
;
import
java.io.File
;
import
java.util.HashMap
;
import
java.util.Map
;
/**
* Created by zhouteng on 2020-03-29
*/
public
class
MimeUtils
{
private
static
final
String
DEFAULT_MINE_TYPE
=
"application/octet-stream"
;
private
static
final
Map
<
String
,
String
>
extensionToMimeTypeMap
=
new
HashMap
<>();
static
{
add
(
"epub"
,
"application/epub+zip"
);
add
(
"ogx"
,
"application/ogg"
);
add
(
"odp"
,
"application/vnd.oasis.opendocument.presentation"
);
add
(
"otp"
,
"application/vnd.oasis.opendocument.presentation-template"
);
add
(
"yt"
,
"application/vnd.youtube.yt"
);
add
(
"hwp"
,
"application/x-hwp"
);
add
(
"3gpp"
,
"video/3gpp"
);
add
(
"3gp"
,
"video/3gpp"
);
add
(
"3gpp2"
,
"video/3gpp2"
);
add
(
"3g2"
,
"video/3gpp2"
);
add
(
"oga"
,
"audio/ogg"
);
add
(
"ogg"
,
"audio/ogg"
);
add
(
"spx"
,
"audio/ogg"
);
add
(
"dng"
,
"image/x-adobe-dng"
);
add
(
"cr2"
,
"image/x-canon-cr2"
);
add
(
"raf"
,
"image/x-fuji-raf"
);
add
(
"nef"
,
"image/x-nikon-nef"
);
add
(
"nrw"
,
"image/x-nikon-nrw"
);
add
(
"orf"
,
"image/x-olympus-orf"
);
add
(
"rw2"
,
"image/x-panasonic-rw2"
);
add
(
"pef"
,
"image/x-pentax-pef"
);
add
(
"srw"
,
"image/x-samsung-srw"
);
add
(
"arw"
,
"image/x-sony-arw"
);
add
(
"ogv"
,
"video/ogg"
);
add
(
"tgz"
,
"application/x-gtar-compressed"
);
add
(
"taz"
,
"application/x-gtar-compressed"
);
add
(
"csv"
,
"text/csv"
);
add
(
"gz"
,
"application/gzip"
);
add
(
"cab"
,
"application/vnd.ms-cab-compressed"
);
add
(
"7z"
,
"application/x-7z-compressed"
);
add
(
"bz"
,
"application/x-bzip"
);
add
(
"bz2"
,
"application/x-bzip2"
);
add
(
"z"
,
"application/x-compress"
);
add
(
"jar"
,
"application/x-java-archive"
);
add
(
"lzma"
,
"application/x-lzma"
);
add
(
"xz"
,
"application/x-xz"
);
add
(
"m3u"
,
"audio/x-mpegurl"
);
add
(
"m3u8"
,
"audio/x-mpegurl"
);
add
(
"p7b"
,
"application/x-pkcs7-certificates"
);
add
(
"spc"
,
"application/x-pkcs7-certificates"
);
add
(
"p7c"
,
"application/pkcs7-mime"
);
add
(
"p7s"
,
"application/pkcs7-signature"
);
add
(
"es"
,
"application/ecmascript"
);
add
(
"js"
,
"application/javascript"
);
add
(
"json"
,
"application/json"
);
add
(
"ts"
,
"application/typescript"
);
add
(
"perl"
,
"text/x-perl"
);
add
(
"pl"
,
"text/x-perl"
);
add
(
"pm"
,
"text/x-perl"
);
add
(
"py"
,
"text/x-python"
);
add
(
"py3"
,
"text/x-python"
);
add
(
"py3x"
,
"text/x-python"
);
add
(
"pyx"
,
"text/x-python"
);
add
(
"wsgi"
,
"text/x-python"
);
add
(
"rb"
,
"text/ruby"
);
add
(
"sh"
,
"application/x-sh"
);
add
(
"yaml"
,
"text/x-yaml"
);
add
(
"yml"
,
"text/x-yaml"
);
add
(
"asm"
,
"text/x-asm"
);
add
(
"s"
,
"text/x-asm"
);
add
(
"cs"
,
"text/x-csharp"
);
add
(
"azw"
,
"application/vnd.amazon.ebook"
);
add
(
"ibooks"
,
"application/x-ibooks+zip"
);
add
(
"mobi"
,
"application/x-mobipocket-ebook"
);
add
(
"woff"
,
"font/woff"
);
add
(
"woff2"
,
"font/woff2"
);
add
(
"msg"
,
"application/vnd.ms-outlook"
);
add
(
"eml"
,
"message/rfc822"
);
add
(
"eot"
,
"application/vnd.ms-fontobject"
);
add
(
"ttf"
,
"font/ttf"
);
add
(
"otf"
,
"font/otf"
);
add
(
"ttc"
,
"font/collection"
);
add
(
"markdown"
,
"text/markdown"
);
add
(
"md"
,
"text/markdown"
);
add
(
"mkd"
,
"text/markdown"
);
add
(
"conf"
,
"text/plain"
);
add
(
"ini"
,
"text/plain"
);
add
(
"list"
,
"text/plain"
);
add
(
"log"
,
"text/plain"
);
add
(
"prop"
,
"text/plain"
);
add
(
"properties"
,
"text/plain"
);
add
(
"rc"
,
"text/plain"
);
add
(
"flv"
,
"video/x-flv"
);
}
private
static
void
add
(
String
extension
,
String
mimeType
)
{
if
(!
extensionToMimeTypeMap
.
containsKey
(
extension
))
{
extensionToMimeTypeMap
.
put
(
extension
,
mimeType
);
}
}
public
static
String
getMineType
(
File
file
)
{
final
int
lastDot
=
file
.
getName
().
lastIndexOf
(
'.'
);
if
(
lastDot
<
0
)
{
return
DEFAULT_MINE_TYPE
;
}
final
String
extension
=
file
.
getName
().
substring
(
lastDot
+
1
).
toLowerCase
();
String
mineType
=
extensionToMimeTypeMap
.
get
(
extension
);
if
(!
TextUtils
.
isEmpty
(
mineType
))
{
return
mineType
;
}
mineType
=
MimeTypeMap
.
getSingleton
().
getMimeTypeFromExtension
(
extension
);
if
(!
TextUtils
.
isEmpty
(
mineType
))
{
return
mineType
;
}
return
DEFAULT_MINE_TYPE
;
}
}
android/src/main/java/com/zt/shareextend/ShareExtendPlugin.java
View file @
2904f3db
...
...
@@ -86,7 +86,7 @@ public class ShareExtendPlugin implements MethodChannel.MethodCallHandler, Plugi
ArrayList
<
Uri
>
uriList
=
new
ArrayList
<>();
for
(
String
path
:
list
)
{
File
f
=
new
File
(
path
);
Uri
uri
=
ShareUtils
.
getUriForFile
(
mRegistrar
.
activity
(),
f
,
type
);
Uri
uri
=
ShareUtils
.
getUriForFile
(
mRegistrar
.
activity
(),
f
);
uriList
.
add
(
uri
);
}
...
...
android/src/main/java/com/zt/shareextend/ShareExtendProvider.java
View file @
2904f3db
package
com.zt.shareextend
;
import
androidx.core.content.FileProvider
;
import
android.content.ContentProvider
;
import
android.content.ContentResolver
;
import
android.content.ContentValues
;
import
android.content.Context
;
import
android.content.pm.ProviderInfo
;
import
android.database.Cursor
;
import
android.database.MatrixCursor
;
import
android.net.Uri
;
import
android.os.ParcelFileDescriptor
;
import
android.provider.MediaStore
;
import
android.provider.OpenableColumns
;
public
class
ShareExtendProvider
extends
FileProvider
{
import
androidx.annotation.NonNull
;
import
androidx.annotation.Nullable
;
import
java.io.File
;
import
java.io.FileNotFoundException
;
public
class
ShareExtendProvider
extends
ContentProvider
{
private
static
final
String
[]
COLUMNS
=
{
OpenableColumns
.
DISPLAY_NAME
,
OpenableColumns
.
SIZE
,
MediaStore
.
MediaColumns
.
DATA
};
@Override
public
void
attachInfo
(
Context
context
,
ProviderInfo
info
)
{
super
.
attachInfo
(
context
,
info
);
// Sanity check our security
if
(
info
.
exported
)
{
throw
new
SecurityException
(
"Provider must not be exported"
);
}
if
(!
info
.
grantUriPermissions
)
{
throw
new
SecurityException
(
"Provider must grant uri permissions"
);
}
}
@Override
public
boolean
onCreate
()
{
return
false
;
}
@Nullable
@Override
public
ParcelFileDescriptor
openFile
(
@NonNull
Uri
uri
,
@NonNull
String
mode
)
throws
FileNotFoundException
{
final
File
file
=
getFileForUri
(
uri
);
final
int
fileMode
=
modeToMode
(
mode
);
return
ParcelFileDescriptor
.
open
(
file
,
fileMode
);
}
private
static
int
modeToMode
(
String
mode
)
{
int
modeBits
;
if
(
"r"
.
equals
(
mode
))
{
modeBits
=
ParcelFileDescriptor
.
MODE_READ_ONLY
;
}
else
if
(
"w"
.
equals
(
mode
)
||
"wt"
.
equals
(
mode
))
{
modeBits
=
ParcelFileDescriptor
.
MODE_WRITE_ONLY
|
ParcelFileDescriptor
.
MODE_CREATE
|
ParcelFileDescriptor
.
MODE_TRUNCATE
;
}
else
if
(
"wa"
.
equals
(
mode
))
{
modeBits
=
ParcelFileDescriptor
.
MODE_WRITE_ONLY
|
ParcelFileDescriptor
.
MODE_CREATE
|
ParcelFileDescriptor
.
MODE_APPEND
;
}
else
if
(
"rw"
.
equals
(
mode
))
{
modeBits
=
ParcelFileDescriptor
.
MODE_READ_WRITE
|
ParcelFileDescriptor
.
MODE_CREATE
;
}
else
if
(
"rwt"
.
equals
(
mode
))
{
modeBits
=
ParcelFileDescriptor
.
MODE_READ_WRITE
|
ParcelFileDescriptor
.
MODE_CREATE
|
ParcelFileDescriptor
.
MODE_TRUNCATE
;
}
else
{
throw
new
IllegalArgumentException
(
"Invalid mode: "
+
mode
);
}
return
modeBits
;
}
@Nullable
@Override
public
Cursor
query
(
@NonNull
Uri
uri
,
@Nullable
String
[]
projection
,
@Nullable
String
selection
,
@Nullable
String
[]
selectionArgs
,
@Nullable
String
sortOrder
)
{
File
file
=
getFileForUri
(
uri
);
if
(
projection
==
null
)
{
projection
=
COLUMNS
;
}
String
[]
cols
=
new
String
[
projection
.
length
];
Object
[]
values
=
new
Object
[
projection
.
length
];
int
i
=
0
;
for
(
String
col
:
projection
)
{
if
(
OpenableColumns
.
DISPLAY_NAME
.
equals
(
col
))
{
cols
[
i
]
=
OpenableColumns
.
DISPLAY_NAME
;
values
[
i
++]
=
file
.
getName
();
}
else
if
(
OpenableColumns
.
SIZE
.
equals
(
col
))
{
cols
[
i
]
=
OpenableColumns
.
SIZE
;
values
[
i
++]
=
file
.
length
();
}
else
if
(
MediaStore
.
MediaColumns
.
DATA
.
equals
(
col
))
{
cols
[
i
]
=
MediaStore
.
MediaColumns
.
DATA
;
values
[
i
++]
=
file
.
getAbsolutePath
();
}
}
cols
=
copyOf
(
cols
,
i
);
values
=
copyOf
(
values
,
i
);
final
MatrixCursor
cursor
=
new
MatrixCursor
(
cols
,
1
);
cursor
.
addRow
(
values
);
return
cursor
;
}
private
static
String
[]
copyOf
(
String
[]
original
,
int
newLength
)
{
final
String
[]
result
=
new
String
[
newLength
];
System
.
arraycopy
(
original
,
0
,
result
,
0
,
newLength
);
return
result
;
}
private
static
Object
[]
copyOf
(
Object
[]
original
,
int
newLength
)
{
final
Object
[]
result
=
new
Object
[
newLength
];
System
.
arraycopy
(
original
,
0
,
result
,
0
,
newLength
);
return
result
;
}
@Nullable
@Override
public
String
getType
(
@NonNull
Uri
uri
)
{
return
MimeUtils
.
getMineType
(
getFileForUri
(
uri
));
}
public
static
Uri
getUriForPath
(
String
authority
,
String
path
)
{
return
new
Uri
.
Builder
()
.
scheme
(
ContentResolver
.
SCHEME_CONTENT
)
.
authority
(
authority
)
.
path
(
Uri
.
encode
(
path
))
.
build
();
}
private
File
getFileForUri
(
Uri
uri
)
{
String
path
=
Uri
.
decode
(
uri
.
getPath
()).
substring
(
1
);
return
new
File
(
path
);
}
@Nullable
@Override
public
Uri
insert
(
@NonNull
Uri
uri
,
@Nullable
ContentValues
values
)
{
throw
new
UnsupportedOperationException
(
"No external inserts"
);
}
@Override
public
int
delete
(
@NonNull
Uri
uri
,
@Nullable
String
selection
,
@Nullable
String
[]
selectionArgs
)
{
throw
new
UnsupportedOperationException
(
"No external deletes"
);
}
@Override
public
int
update
(
@NonNull
Uri
uri
,
@Nullable
ContentValues
values
,
@Nullable
String
selection
,
@Nullable
String
[]
selectionArgs
)
{
throw
new
UnsupportedOperationException
(
"No external updates"
);
}
}
android/src/main/java/com/zt/shareextend/ShareUtils.java
View file @
2904f3db
package
com.zt.shareextend
;
import
android.content.ContentResolver
;
import
android.content.ContentValues
;
import
android.content.Context
;
import
android.database.Cursor
;
import
android.net.Uri
;
import
android.os.Build
;
import
android.os.Environment
;
import
android.provider.MediaStore
;
import
android.text.TextUtils
;
import
java.io.File
;
import
java.util.List
;
import
androidx.core.content.FileProvider
;
public
class
ShareUtils
{
class
ShareUtils
{
/// get the uri for file
static
Uri
getUriForFile
(
Context
context
,
File
file
,
String
type
)
{
static
Uri
getUriForFile
(
Context
context
,
File
file
)
{
String
authorities
=
context
.
getPackageName
()
+
".shareextend.fileprovider"
;
Uri
uri
;
// 低版本直接用 Uri.fromFile
if
(
Build
.
VERSION
.
SDK_INT
<
Build
.
VERSION_CODES
.
N
)
{
uri
=
Uri
.
fromFile
(
file
);
}
else
{
// 使用 FileProvider 会在某些 app 下不支持(在使用FileProvider 方式情况下QQ不能支持图片、视频分享,微信不支持视频分享)
uri
=
FileProvider
.
getUriForFile
(
context
,
authorities
,
file
);
if
(!
isPathInExternalStorage
(
file
.
getAbsolutePath
())
||
"file"
.
equals
(
type
))
{
return
uri
;
uri
=
ShareExtendProvider
.
getUriForPath
(
authorities
,
file
.
getAbsolutePath
());
}
ContentResolver
cR
=
context
.
getContentResolver
();
if
(
uri
!=
null
&&
!
TextUtils
.
isEmpty
(
uri
.
toString
()))
{
String
fileType
=
cR
.
getType
(
uri
);
// 使用 MediaStore 的 content:// 而不是自己 FileProvider 提供的uri,不然有些app无法适配
if
(!
TextUtils
.
isEmpty
(
fileType
))
{
if
(
fileType
.
contains
(
"video/"
))
{
uri
=
getVideoContentUri
(
context
,
file
);
}
else
if
(
fileType
.
contains
(
"image/"
))
{
uri
=
getImageContentUri
(
context
,
file
);
}
else
if
(
fileType
.
contains
(
"audio/"
))
{
uri
=
getAudioContentUri
(
context
,
file
);
}
}
}
}
return
uri
;
}
static
boolean
shouldRequestPermission
(
List
<
String
>
pathList
)
{
for
(
String
path
:
pathList
)
{
if
(
shouldRequestPermission
(
path
))
{
...
...
@@ -61,7 +36,7 @@ public class ShareUtils {
return
false
;
}
static
boolean
shouldRequestPermission
(
String
path
)
{
private
static
boolean
shouldRequestPermission
(
String
path
)
{
return
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
M
&&
isPathInExternalStorage
(
path
);
}
...
...
@@ -69,85 +44,4 @@ public class ShareUtils {
File
storagePath
=
Environment
.
getExternalStorageDirectory
();
return
path
.
startsWith
(
storagePath
.
getAbsolutePath
());
}
/**
* Gets the content:// URI from the given corresponding path to a file
*
* @param context
* @param imageFile
* @return content Uri
*/
public
static
Uri
getImageContentUri
(
Context
context
,
File
imageFile
)
{
String
filePath
=
imageFile
.
getAbsolutePath
();
Cursor
cursor
=
context
.
getContentResolver
().
query
(
MediaStore
.
Images
.
Media
.
EXTERNAL_CONTENT_URI
,
new
String
[]{
MediaStore
.
Images
.
Media
.
_ID
},
MediaStore
.
Images
.
Media
.
DATA
+
"=? "
,
new
String
[]{
filePath
},
null
);
if
(
cursor
!=
null
&&
cursor
.
moveToFirst
())
{
int
id
=
cursor
.
getInt
(
cursor
.
getColumnIndex
(
MediaStore
.
MediaColumns
.
_ID
));
Uri
baseUri
=
Uri
.
parse
(
"content://media/external/images/media"
);
return
Uri
.
withAppendedPath
(
baseUri
,
""
+
id
);
}
else
{
if
(
imageFile
.
exists
())
{
ContentValues
values
=
new
ContentValues
();
values
.
put
(
MediaStore
.
Images
.
Media
.
DATA
,
filePath
);
return
context
.
getContentResolver
().
insert
(
MediaStore
.
Images
.
Media
.
EXTERNAL_CONTENT_URI
,
values
);
}
else
{
return
null
;
}
}
}
/**
* Gets the content:// URI from the given corresponding path to a file
*
* @param context
* @param videoFile
* @return content Uri
*/
public
static
Uri
getVideoContentUri
(
Context
context
,
File
videoFile
)
{
String
filePath
=
videoFile
.
getAbsolutePath
();
Cursor
cursor
=
context
.
getContentResolver
().
query
(
MediaStore
.
Video
.
Media
.
EXTERNAL_CONTENT_URI
,
new
String
[]{
MediaStore
.
Video
.
Media
.
_ID
},
MediaStore
.
Video
.
Media
.
DATA
+
"=? "
,
new
String
[]{
filePath
},
null
);
if
(
cursor
!=
null
&&
cursor
.
moveToFirst
())
{
int
id
=
cursor
.
getInt
(
cursor
.
getColumnIndex
(
MediaStore
.
MediaColumns
.
_ID
));
Uri
baseUri
=
Uri
.
parse
(
"content://media/external/video/media"
);
return
Uri
.
withAppendedPath
(
baseUri
,
""
+
id
);
}
else
{
if
(
videoFile
.
exists
())
{
ContentValues
values
=
new
ContentValues
();
values
.
put
(
MediaStore
.
Video
.
Media
.
DATA
,
filePath
);
return
context
.
getContentResolver
().
insert
(
MediaStore
.
Video
.
Media
.
EXTERNAL_CONTENT_URI
,
values
);
}
else
{
return
null
;
}
}
}
/**
* Gets the content:// URI from the given corresponding path to a file
*
* @param context
* @param audioFile
* @return content Uri
*/
private
static
Uri
getAudioContentUri
(
Context
context
,
File
audioFile
)
{
String
filePath
=
audioFile
.
getAbsolutePath
();
Cursor
cursor
=
context
.
getContentResolver
().
query
(
MediaStore
.
Audio
.
Media
.
EXTERNAL_CONTENT_URI
,
new
String
[]{
MediaStore
.
Audio
.
Media
.
_ID
},
MediaStore
.
Audio
.
Media
.
DATA
+
"=? "
,
new
String
[]{
filePath
},
null
);
if
(
cursor
!=
null
&&
cursor
.
moveToFirst
())
{
int
id
=
cursor
.
getInt
(
cursor
.
getColumnIndex
(
MediaStore
.
MediaColumns
.
_ID
));
Uri
baseUri
=
Uri
.
parse
(
"content://media/external/audio/media"
);
return
Uri
.
withAppendedPath
(
baseUri
,
""
+
id
);
}
else
{
if
(
audioFile
.
exists
())
{
ContentValues
values
=
new
ContentValues
();
values
.
put
(
MediaStore
.
Audio
.
Media
.
DATA
,
filePath
);
return
context
.
getContentResolver
().
insert
(
MediaStore
.
Audio
.
Media
.
EXTERNAL_CONTENT_URI
,
values
);
}
else
{
return
null
;
}
}
}
}
android/src/main/res/xml/share_extend_provider_path.xml
deleted
100644 → 0
View file @
6f87f891
<?xml version="1.0" encoding="utf-8"?>
<resources>
<paths>
<root-path
name=
"root_path"
path=
"/"
/>
</paths>
</resources>
\ No newline at end of file
example/android/app/src/main/AndroidManifest.xml
View file @
2904f3db
...
...
@@ -6,6 +6,7 @@
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission
android:name=
"android.permission.INTERNET"
/>
<uses-permission
android:name=
"android.permission.READ_EXTERNAL_STORAGE"
/>
<uses-permission
android:name=
"android.permission.WRITE_EXTERNAL_STORAGE"
/>
<uses-permission
android:name=
"android.permission.CAMERA"
/>
...
...
example/lib/main.dart
View file @
2904f3db
...
...
@@ -96,7 +96,9 @@ class _MyAppState extends State<MyApp> {
}
Future
<
String
>
_writeByteToImageFile
(
ByteData
byteData
)
async
{
Directory
dir
=
await
getApplicationDocumentsDirectory
();
Directory
dir
=
Platform
.
isAndroid
?
await
getExternalStorageDirectory
()
:
await
getApplicationDocumentsDirectory
();
File
imageFile
=
new
File
(
"
${dir.path}
/flutter/
${DateTime.now().millisecondsSinceEpoch}
.png"
);
imageFile
.
createSync
(
recursive:
true
);
...
...
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