Plugin cnkFileManager for Corona
SUPPORT WEBSITE
Updated 19 / September / 2017
v. 1.2
INFORMATION:
This plugin allow an easy access to the Android File system. it allows to get a file from the external Storage using the Android ACTION_OPEN_DOCUMENT or ACTION_GET_CONTENT as desired and copy it to an internal path.
Also it is possible to pass an Uri to this plugin and get the file if exist from the external Storage too.
v.1.1 Included the new function shareFile that allow to share simple data to other apps.
v.1.2 Include Copy File to External Storage, and get External Storage Path.
library.pickFile
USSAGE:
PICK A FILE USING THE ACTION_OPEN_DOCUMENT or ACTION_GET_CONTENT:
local library = require "plugin.cnkFileManager"
...
library.pickFile (path, listener, fileName, headerText, mimeType, onlyOpenable, onlyDocuments, dummyMode )
path: (Mandatory)
(String)
The destination path where we want the file be copy to.
example:
local path = system.pathForFile(nil, system.DocumentsDirectory)
local path = system.pathForFile(nil, system.TemporaryDirectory)
listener:
(Lua Function reference)
Listener function to be called at finish.
fileName:
(String)
Name we want to name to the copy. If none if provided, the original name will be used.
headerText:
(String)
The text to be shown at the dialog to pick the file. If none is provided, the default text will be used.
mimeType:
(String)
The mimeType we want to take. For example, if we only want to allow the user to pick from images, then the mimeType ought to be «image/*» to allow to get any image.
"image/jpeg"
"image/bmp"
"image/gif"
"image/jpg"
"image/png"
To allow to get any file use:
"*/*"
onlyOpenable:
(Boolean)
If set to ‘true’ the plugin will apply the filter:
apply the filter «CATEGORY_OPENABLE»
This only will show the files that are openable. (my conclussion is that the system will only manage the content providers)
onlyDocuments:
(Boolean).
If set to ‘true’ the plugin will use the action:
ACTION_OPEN_DOCUMENT
If set to ‘false’ or ‘nil’ the plugin will use the action:
ACTION_GET_CONTENT
dummyMode:
(Boolean)
The dummy mode is usefull to know the size of a file, or if the file exists and can be copied. The dummy mode works exactly in the very same way as the normal mode, except that, the file is not real copy, only simulate. The event.done will return the «dummy» value and not «ok».
For example, we can know or get the Uri for a file using the pickFile in dummy mode.
See the example at the following link for more details:
https://github.com/cnksoft/cnkFileManager-example-1
Another FULL EXAMPLE (Lua Corona Code):
Simple open the get file dialog and allow to the customer to get an image file.
local library = require "plugin.cnkFileManager"
local function listener (event) print ("Event Received froom Plugin", event.name) if event.done then --when event.done is not nil, the all went ok. print ("File copy correctly") print ("File Name", event.destFileName) print ("File Size", event.realSize) -- Here the code to manage the file... else print ("Error in copy ", event.error) if event.errorCode == 2 then print ("The customer didn't give permission to Read External Storage") --here we can explain again to the customer that need to allow this permission and the reassons to do it. end --handle other errors. The event.error is a description of the error. event.errorCode is a code for that error. end endlocal path =
system.pathForFile( nil, system.TemporaryDirectory ) local newFileName = "myImage.jpg" local mimeType = "image/*" library.pickFile (path, listener, newFileName, nil, mimeType, nil, nil, nil )
EVENT RESPONSE:
* event.name = name of the function "pickFileEvent" * event.error = Error Description if any. If no error happen, this value is nil. * event.errorCode = 0 ok; 1 no READ_EXTERNAL_STORAGE at permissions; (this need to be included at the build.settings for android section *see bellow for details) 2 User refused permission; 3 Error taking the file (not found or other); 4 Error copying the file; 5 Undefined Error taking the file (sometimes the file don't exist for example); 6 destination Path Required * event.origFileName = name of the Original file taken * event.origPath = path of the Original file taken (for some streams contents it is not available) * event.destFileName = name of the file at destination (if the user didn't provided one, the original will be used) * event.destPath = path of the destination file to be coied to * event.uri = Uri used (if one) * event.size = size of the file. * event.done = 'ok' if all ok. 'dummy' if the dummy option was activated. This value only exist if the result of the operation was fine and will be 'ok'. If an error happen, this value will be nil.
library.getFileFromUri
USSAGE:
GET A FILE FROM EXTERNAL STORAGE USING THE URI PROVIDED:
local library = require "plugin.cnkFileManager"
...
library.getFileFromUri (path, uri, listener, fileName )
path: (Mandatory)
(String)
The destination path where we want the file be copy to.
example:
local path = system.pathForFile(nil, system.DocumentsDirectory)
local path = system.pathForFile(nil, system.TemporaryDirectory)
Uri: (Mandatory)
(String)
Uri to be passed to the plugin.
Uri examples:
content://com.example.sample.provider/files/xyz/image/JPEG_2017.jpeg
file:///storage/emulated/0/Android/data/com.dropbox.android/files/u2678555/scratch/Public/text.txt
It is not needed to filter or change these uris. The plugin will manage the correct wat to take the file is possible, and if not possible will return an error explaining the reason.
listener:
(Corona Function)
Listener function to be called at finish.
fileName:
(String)
Name we want to name to the copy. If none if provided, the original name will be used.
dummyMode:
(Boolean)
The dummy mode is usefull to know the size of a file, or if the file exists and can be copied. The dummy mode works exactly in the very same way as the normal mode, except that, the file is not real copy, only simulate. The event.done will return the «dummy» value and not «ok».
FULL EXAMPLE (Lua Corona Code):
Simple copy a file to the internal documents path when a file is opened with our app. For example, open an email attachment.
The code for iOS can be found at Corona Forums and on some Google sites (for example : https://swipeware.com/ios-tutorial-using-email-attachments-in-corona-sdk/ )
This plugin allow to do the same for Android in a simple way.
local library = require "plugin.cnkFileManager" local launchArgs = ...
local function listener (event) print ("Event Received froom Plugin", event.name) if event.done then if event.done == "ok" then --when event.done is not nil, the all went ok. print ("File copy correctly") print ("File Name", event.destFileName) print ("File Size", event.realSize) -- Here the code to manage the file... elseif event.done == "dummy" then --manage a dummy answer. The dummy answer works in the very same way, except that the file is not copied. end else print ("Error in copy ", event.error) if event.errorCode == 2 then print ("The customer didn't give permission to Read External Storage") --here we can explain again to the customer that need to allow this permission and the reassons to do it. end --handle other errors. The event.error is a description of the error. event.errorCode is a code for that error. end endif (launchArgs and launchArgs.url) then
if
( system.getInfo(
"platform"
) == "android" then
local uri = launchArgs.url local path =
system.pathForFile( nil, system.DocumentsDirectory ) local newFileName = "myFile.txt" local dummyMode = falselibrary.getFileFromUri (path, uri, listener,
newFileName, dummyMode) else --manage the file for iOS.... end end
You can find another usefull example here:
https://github.com/cnksoft/cnkFileManager-example-1
EVENT RESPONSE:
* event.name = name of the function "getFileFromUri" * event.error = Error Description if any. If no error happen, this value is nil. * event.errorCode = 0 ok; 1 no READ_EXTERNAL_STORAGE at permissions (this need to be included at the build.settings for android section *see bellow for details) 2 User refused permission; 3 Error taking the file (not found or other); 4 Error copying the file; 5 Undefined Error taking the file (sometimes the file don't exist for example); 6 destination Path Required 7 Uri required * event.origFileName = name of the Original file taken * event.origPath = path of the Original file taken (for some streams contents it is not available) * event.destFileName = name of the file at destination (if the user didn't provided one, the original will be used) * event.destPath = path of the destination file to be coied to * event.uri = Uri. Return the same uri provided when calling the function. * event.size = size of the file. * event.done = 'ok' if all ok. 'dummy' if the dummy function was activated. This value only exist if the result of the operation was fine and will be 'ok'. If an error happen, this value will be nil.
IMPORTANT
This plugin needs the following permission and the activation to be included at build.settings:
settings = { --android permission... android = { "android.permission.READ_EXTERNAL_STORAGE" }, --plugin activation... plugins = { ['plugin.cnkFileManager'] = {publicherId = 'es.cnksoft'}, }, }
Remember to Activate the plugin at Corona MarketPlace here:
https://marketplace.coronalabs.com/plugin/android-file-and-uri-manager
The example code can be found at the following link:
https://github.com/cnksoft/cnkFileManager-example-1
https://github.com/cnksoft/cnkFileManager-example-2
library.shareFile
USSAGE:
Share a File (or some files) to external apps in a simple way:
local library = require "plugin.cnkFileManager"
...
local function listener (event)
if event.action == "sent" then
print ("file was sent ok")
elseif event.action == "cancelled" then
print ("file was not sent")
end
end
library.shareFile (
{
message = "Hi there",
listener = listener,
defaultMimeType = "application/octet-stream",
forceMimeType = "application/octet-stream",
defaultChooser = false,
header = "Export with...",
file =
{
{filename = "file.zip", baseDir=system.TemporaryDirectory},
{filename = "file2.zip", baseDir=system.TemporaryDirectory},
}
url =
{
"http://www.mywebpage.com",
"http://www.google.com"
}
})
listener:
(Corona Function)
Listener function to be called at finish. The listener will receive an event with the following keys:
EVENT RESPONSE:
* event.name = name of the function "shareFile" * event.action = "cancelled" if the user cancelled the action. "sent" if the file was sent.
message:
(String) (only available when only 1 file is sent)
Message to be attached to the action. For example, this will be included at the body message if the user choice to share by email.
url:
(array) (only available when only 1 file is sent)
Url list to be attached to the action. For example, this will be included at the body message if the user choice to share by email toghether with the message.
defaultMimeType:
(String)
The function will try to get the mimetype directly from each file. But if the mimetype can be retrieved, then, this field, if provided, will be the default to use. If this field is not provided, the function will use the «application/octet-strem» as default.
forceMimeType:
(String)
This causes that all files will be sent as they have this mimetype. The adventage of this is, if we have a custom file extension not detected by the system, then, we can use the correct mimetype to allow the share dialog to show the correct list of applications that can manage this file to the user.
defaultChooser:
(Boolean)
If we set this to false, the custom Chooser will be used, so, we can include the field header to customize the header of the share dialog.
This value is set to true by default, that causes the default Chooser will be shown to the user, with the default header text. If this field is true (default) the header field will be ignored.
header:
(String)
Text to customize the header of the share dialog shown to the user.
Read the defaultChooser details for this field.
file:
(Array of Arrays)
List of the files to be shared. We need to provide the filename and baseDir for each file.
filename (String) = name of the file. ej. «image.jpg»
baseDir = system base directory to be used. The options are:
system.TemporaryDirectory, system.DocumentsDirectory, system.ResourceDirectory
Read the corona documentation for more details about the base directories.
Remember to Activate the plugin at Corona MarketPlace here:
https://marketplace.coronalabs.com/plugin/android-file-and-uri-manager
The example code can be found at the following link:
https://github.com/cnksoft/cnkFileManager-example-1
https://github.com/cnksoft/cnkFileManager-example-2
library.copyFileToExternalStorage
USSAGE:
Copy a File to External Storage in a simple way:
local library = require "plugin.cnkFileManager" ... local function listener (event) if event.action == "sent" then print ("file was sent ok") elseif event.action == "cancelled" then print ("file was not sent") end end library.
copyFileToExternalStorage ( { listener = listener, mainFolder = "DIRECTORY_DOCUMENTS", subFolder = "BackUp", newFileName = "birds.jpg", isPublic = true, isRemovable = false, file = { { filename="myFile.jpg", baseDir=system.DocumentsDirectory }, }, })
listener:
(Corona Function)
Listener function to be called at finish. The listener will receive an event with the following keys:
EVENT RESPONSE:
* event.name = name of the function. * event.destFileName = String. Final Name of the file at the destination. * event.done = String. "ok" if all went ok. * event.error = String. Error Description if an error happen. * event.errorCode = int. Code of the error that happened. 0 ok; 1 no WRITE_EXTERNAL_STORAGE at permissions (this need to be included at the build.settings for android section *see bellow for details) 2 User refused permission; 3 and sucefull --> Error in Operation. * event.destPath = String. Destination path of the file at External Storage. (This can be used also with LFS) * event.size = int. Size of the file copied to the External Storage.
mainFolder:
(String)
The main Folder where to copy the file to. This can be one of the Android Folder Values as follow:
DIRECTORY_MUSIC, DIRECTORY_PODCASTS, DIRECTORY_RINGTONES, DIRECTORY_ALARMS, DIRECTORY_NOTIFICATIONS, DIRECTORY_PICTURES, DIRECTORY_MOVIES, DIRECTORY_DOWNLOADS, DIRECTORY_DCIM, DIRECTORY_DOCUMENTS
If one of the above default values are provided in the mainFolder as String (example: «DIRECTORY_MUSIC») the plugin will replace this value by the correct value of the system, copying the file to such correct directory.
If the value provided is not known, then an special folder will be created with that name.
Example: mainFolder = «miCarpeta» will create a folder named miCarpeta.
subFolder:
(String)
Additional Folder to be created (if provided) at the mainFolder destination.
For example: if we need to copy a file to the External Documents Directory into an special folder named «BackUp» we can use the following:
local library = require "plugin.cnkFileManager" ... local function listener (event) if event.done == "ok" then print ("ok") else print ("ERROR ", event.error) end
end library.
copyFileToExternalStorage ( { listener = listener, mainFolder = "DIRECTORY_DOCUMENTS", subFolder = "BackUp", newFileName = "birds.jpg", isPublic = true, isRemovable = false, file = { { filename="myFile.jpg", baseDir=system.DocumentsDirectory }, }, })
isPublic:
(Boolean)
We can select between External Storage Public Files (the one available to all the apps and for the user) and External Storage Private Files (into the app special folders). This value allow us to select one or other.
For example: The example above, use isPublic = true, so, the plugin will use external storage public documents directory available to the user.
isRemovable:
(Boolean)
If a removable media is present, (SD Card for example), this value will tell to the plugin to use the SD path.
If none removable media is available, and this value is set to true, the standard internal memory for the app will be used.
For example: We want to copy a file to a folder «miCarpeta» at External Storage Removable Media. We can use the following code:
library.
copyFileToExternalStorage ( { listener = listener, mainFolder = "miCarpeta", isPublic = false, isRemovable = true, file = { { filename="myFile.jpg", baseDir=system.DocumentsDirectory }, }, })
Note that, is the value isPublic is set to true, the isRemovable will be ignored. isRemovable only write to the SD, special subfolder created for the app folders.
Also, note that, if the user uninstall the app, the files at that special folder will be deleted too.
If we want to avoid to delete the files when the user uninstall the app, the correct way is to copy to Public directories.
The special folder created by Android for the app at SD card is as follow:
/myaplicaion.mycompany.com/
See Android details for the External Storage at
https://developer.android.com/guide/topics/data/data-storage.html
newFileName:
(String)
If provided, this value will be used for the final filename at the destination path. If not provided, the original filename will be used.
file:
(Array of Arrays)
File to be shared (only 1 at a time). We need to provide the filename and baseDir for it.
* If more than 1 file is provided, only the 1st one will be used.
filename (String) = name of the file. ej. «image.jpg»
baseDir = system base directory to be used. The options are:
system.TemporaryDirectory, system.DocumentsDirectory, system.ResourceDirectory
Read the corona documentation for more details about the base directories.
Remember to Activate the plugin at Corona MarketPlace here:
https://marketplace.coronalabs.com/plugin/android-file-and-uri-manager
The example code can be found at the following link:
https://github.com/cnksoft/cnkFileManager-example-1
https://github.com/cnksoft/cnkFileManager-example-2
library.getExternalPath
USSAGE:
Only get the external path and pass it to Corona. You then can use it with LFS to copy files from/to.
local library = require "plugin.cnkFileManager" ... local function listener (event) if event.done == "ok" then print ("ok") else print ("ERROR ", event.error) end end library.getExternalPath
( { listener = listener, mainFolder = "DIRECTORY_DOWNLOADS", subFolder = "miCarpeta", isPublic = true, isRemovable = false, file = { { filename="myFile.jpg", baseDir=system.DocumentsDirectory }, }, })
listener:
(Corona Function)
Listener function to be called at finish. The listener will receive an event with the following keys:
EVENT RESPONSE:
* event.name = name of the function. * event.done = String. "ok" if all went ok. * event.error = String. Error Description if an error happen. * event.errorCode = int. Code of the error that happened. 0 ok; 1 no WRITE_EXTERNAL_STORAGE at permissions (this need to be included at the build.settings for android section *see bellow for details) 2 User refused permission; 3 and sucefull --> Error in Operation. * event.path = String. The required path to the External Storage. (This can be used with LFS) * event.okToWrite = String. "ok" if the path can be write. * event.okToRead = String. "ok" if the path can be read.
mainFolder:
(String)
The main Folder where to copy the file to. This can be one of the Android Folder Values as follow:
DIRECTORY_MUSIC, DIRECTORY_PODCASTS, DIRECTORY_RINGTONES, DIRECTORY_ALARMS, DIRECTORY_NOTIFICATIONS, DIRECTORY_PICTURES, DIRECTORY_MOVIES, DIRECTORY_DOWNLOADS, DIRECTORY_DCIM, DIRECTORY_DOCUMENTS
If one of the above default values are provided in the mainFolder as String (example: «DIRECTORY_MUSIC») the plugin will replace this value by the correct value of the system, copying the file to such correct directory.
If the value provided is not known, then an special folder will be created with that name.
Example: mainFolder = «miCarpeta» will create a folder named miCarpeta.
subFolder:
(String)
Additional Folder to be created (if provided) at the mainFolder destination.
For example: if we need to copy a file to the External Documents Directory into an special folder named «BackUp» we can use the following:
library.
getExternalPath ( { listener = listener, mainFolder = "DIRECTORY_DOCUMENTS", subFolder = "BackUp", isPublic = true, isRemovable = false, mkDir = true, })
isPublic:
(Boolean)
We can select between External Storage Public Files (the one available to all the apps and for the user) and External Storage Private Files (into the app special folders). This value allow us to select one or other.
For example: The example above, use isPublic = true, so, the plugin will use external storage public documents directory available to the user.
isRemovable:
(Boolean)
If a removable media is present, (SD Card for example), this value will tell to the plugin to use the SD path.
If none removable media is available, and this value is set to true, the standard internal memory for the app will be used.
For example: We want to copy a file to a folder «miCarpeta» at External Storage Removable Media. We can use the following code:
library.
getExternalPath ( { listener = listener, mainFolder = "miCarpeta", isPublic = false, isRemovable = true })
Note that, is the value isPublic is set to true, the isRemovable will be ignored. isRemovable only write to the SD, special subfolder created for the app folders.
Also, note that, if the user uninstall the app, the files at that special folder will be deleted too.
If we want to avoid to delete the files when the user uninstall the app, the correct way is to copy to Public directories.
The special folder created by Android for the app at SD card is as follow:
/myaplicaion.mycompany.com/
See Android details for the External Storage at
https://developer.android.com/guide/topics/data/data-storage.html
mkDir:
(Boolean)
Tells to the plugin to create the full requester path if it not exists. By default is true.
Remember to Activate the plugin at Corona MarketPlace here:
https://marketplace.coronalabs.com/plugin/android-file-and-uri-manager
The example code can be found at the following link:
https://github.com/cnksoft/cnkFileManager-example-1
https://github.com/cnksoft/cnkFileManager-example-2
https://github.com/cnksoft/cnkFileManager-example-3