Scott Harrison Plugins iOS 11 changes

As of today the Document Picker plugin now uses file sheet pop-up. Why? Because Apple got rid of the menu from before in iOS 11. Now the file system now ties all file into one place (including 3rd parties like Dropbox). There are a couple tweaks, check out the new docs here

https://scotth.tech/plugin-docPicker

on device > iOS 11 an icloud sheet will pop up instead of the source menu

Also as of today my Store kit plugin is no longer supported. It will not be supported in iOS 11+. Please use Corona’s store api instead which supports iOS, tvOS, and macOS.

Thanks,

Scott

Dear Scott,

Thanks again for your support.

Then, we can understand that you have modify the plugin to use the working file sheet pop-up?

I just tried again, and persists the issue as following:

[Device] *** Assertion failure in -[UIDocumentPickerViewController _commonInitWithCompletion:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit/UIKit-3600.9.1/UIDocumentPickerViewController.m:91

I just using your example code as follow:

local docPicker = require("plugin.docPicker") docPicker.init() local widget = require("widget") local bg = display.newRect( display.contentCenterX, display.contentCenterY, display.actualContentWidth, display.actualContentHeight ) bg:setFillColor(.5) local title = display.newText( "Doc Picker Plugin", display.contentCenterX, 20 , native.systemFontBold, 20 ) local exportButton = widget.newButton( { onRelease = function (e) print ("button pressed") docPicker.export(system.pathForFile("test.txt"), function(ev) if (ev.status == "document picked") then native.showAlert( "File Exported", {"Ok"} ) end end) end, label = "Export Doc", x = display.contentCenterX, y = display.contentCenterY-30, }) local exportButton = widget.newButton( { onRelease = function (e) --docPicker.import({"public.image"}, system.pathForFile( "test.png", system.TemporaryDirectory ), function(ev) print ("button pressed") docPicker.import({"public.data"}, system.pathForFile( "test.zip", system.TemporaryDirectory ), function(ev) if (ev.status == "document picked") then local testImage = display.newImage( "test.png", system.TemporaryDirectory, display.contentCenterX, display.contentCenterY+80 ) native.showAlert( "File Imported", "File Imported",{"Ok"} ) end end) end, label = "Import Doc", x = display.contentCenterX, y = display.contentCenterY+30, })

Dear, please, please, forgive me…

I must be silly!

I was using a non activated iCloud profile…

Dear, all is fine… Please, forget this.

Good job dear, and sorry for my mistake

:frowning: So sorry dear.

All works fine. Was my mistake  :unsure:  :frowning:

At the moment to select the profile for building options, I selected the non iCloud one activated, so, that’s was the problem.

Thanks so much again and forgive me please,

Cesar

It will be supported

Dear Scott,

If I need to use the origin file name when importing the file with:

docPicker.import(documentTypes, pathForImport, listener) 

What should I use as pathForImport ?

I have used the following:

docPicker.import({"public.data"}, system.pathForFile( nil, system.DocumentsDirectory ), function(ev) if (ev.status == "document picked") then --All done. native.showAlert( "File Imported OK", {"Ok"} ) else --Error or Cancelled by user end end)

But the nil at the fileName appear to not keep the original fileName.

Can you help me ?

Thanks again !!

I am removing pathForImport because it is not longer used anyways. Please try again in an hour.

Ok dear. I will do.

Perhaps if pathForImport no longer necessary, it is due, the UIDocumentPickerViewController will move get a copy of the external file to the “Inbox” subfolder at DocumentsDirectory., and send an Url with the full path and name for it… isn’t it ?

I will test and let you know.

Thanks so much again,

Dear Scott,

Fantastic. It works fine.

Only I need the way to copy the file from the URL your plugin provide to known folder into the app.

I have an URL like this:

file:///private/var/mobile/Containers/Data/Application/9BC87323-B20C-4754-8DEB-5AE986EBD4C7/tmp/es.cnksoftware.myapplication-Inbox/ImportedFile%202.zip

I have no subfolder into Documents… Must I get the file using LFS for example?

I will continue testing and let you all know.

thanks so much dear Scott,

Yes there is a good example here,

https://docs.coronalabs.com/guide/data/readWriteFiles/index.html#copying-files-to-subfolders

Dear Scott,

Only 1 little doubt.

For iOS 11, the uri need to be encoded ?

The sample code is as follow:

 if( iOSVersion \>= 11 and system.getInfo("platform") == "ios" ) then local json = require ('json') native.showAlert( "File Imported", json.encode( ev.urls ),{"Ok"} ) else native.showAlert( "File Imported", ev.url,{"Ok"} ) end

I suppose from iOS 11, more than 1 uri can be returned and it is returned in event.urls.

My question is: why to use json.encode and not json.decode to decode the uri ?

Thanks again dear,

event.urls returns an array of strings. In order to display the array I convert it to json. I have not done full tests with iOS 11, I am still waiting for the full launch.

Ok dear. Thanks again.

I’m using this code to get the file. It works fine for the iOS 10…

-- Sample code for the usage of Scott Harrison plugin docPicker -- https://marketplace.coronalabs.com/plugin/doc-picker -- -- This code use the docPicker plugin and copy the file to DocumentsDirectory baseDir. -- -- CopyFiles routines from Corona Docs -- https://docs.coronalabs.com/guide/data/readWriteFiles/index.html#copying-files-to-subfolders -- -- local lfs = require( "lfs" ) local iosDocPicker = require "plugin.docPicker" --init the DocPicker iosDocPicker.init() --check if a file exists in a given fullPath local function doesFileExistFromFullPath( fullPath ) local results = false local filePath = fullPath -- filePath will be nil if file doesn't exist and the path is ResourceDirectory if filePath then filePath = io.open( filePath, "r" ) end if filePath then print( "File found -\> " .. fname ) -- Clean up our file handles filePath:close() results = true else print( "File does not exist -\> " .. fname ) end return results end --copy a file from a full srcPath to a dstPath with dstName local function copyFileFromFullPath( srcFullPath, dstName, dstPath, callback, overwrite ) local \_srcPath = doesFileExistFromFullPath ( srcFullPath ) if \_srcPath == false then -- Source file doesn't exist pcall (callback, false, "Source file doesn't exist !") --call callback with false end -- Check to see if destination file already exists if not overwrite then if doesFileExist( dstName, dstPath ) then -- Don't overwrite the file pcall (callback, false, "the file already exists.") end end -- Copy the source file to the destination file -- local rfilePath = srcFullPath local wfilePath = system.pathForFile( dstName, dstPath ) local rfh = io.open( rfilePath, "rb" ) local wfh = io.open( wfilePath, "wb" ) if (not wfh) then pcall (callback, false, "error creating destination file !") elseif (not rfh) then pcall (callback, false, "error opening origin file !") else -- Read the file local data = rfh:read( "\*a" ) if not data then pcall (callback, false, "read error !") --call callback with false else if not wfh:write( data ) then pcall (callback, false, "write error !") --call callback with false else --all ok --Clean up our file handles rfh:close() wfh:close() pcall (callback, true, "OK") --call callback with true. All ok. end end end end --decode URI (quit %20 for example) local function decodeURI(s) if(s) then s = string.gsub(s, '%%(%x%x)', function (hex) return string.char(tonumber(hex,16)) end ) end return s end --principal call to the doc Picker iosDocPicker.import({"public.data"}, function(ev) if (ev.status == "document picked") then --copy the file to DocumentsDirectory from the given URL local platformVersion = system.getInfo( "platformVersion" ) or 0 local iOSVersion = tonumber(string.sub( platformVersion, 1, 4 )) local \_uri = "" if( iOSVersion \>= 11 and system.getInfo("platform") == "ios" ) then local json = require ('json') local \_jsonUri = json.encode (ev.urls) \_uri = decodeURI (\_jsonUri) else \_uri = decodeURI (ev.url) end if string.len (\_uri) \> 7 and (string.sub(\_uri, 1, 7) == "file://") then local getDocPath = function(fName) local f = fName or ""; local docStart, docEnd = f:find("Inbox/"); --find the name of the file. if docEnd then f = f:sub(docEnd+1); else f = "" end return f; end --collect filename local fName = getDocPath(\_uri) print ("File NAME :", fName) --copy the file to DocumentsDirectory local \_srcFullPath = string.sub(\_uri, 8) --cut the beginning "file://" 7 chars local myDstName = fName local baseDir = system.DocumentsDirectory local overwrite = true local function listener3 (done, errorMsg) if done then print ("File copied to Documents Directory with the name: " .. dstName ) else print ("ERROR at copy the file", errorMsg) end end copyFileFromFullPath ( \_srcFullPath, myDstName, baseDir, listener3, overwrite ) else print ("Error Using iOS Doc Picker. Uri Not Valid.") end else print ("Error Using iOS Doc Picker. User cancelled or other Issue.") end end)

I needed to use decode URI function to decode URL type like %20 for spaces… If not use it, the file like “documents merged.txt” will be “documents%20merged.txt” …

Best regards,

Dear Scott,

Thanks again for your support.

Then, we can understand that you have modify the plugin to use the working file sheet pop-up?

I just tried again, and persists the issue as following:

[Device] *** Assertion failure in -[UIDocumentPickerViewController _commonInitWithCompletion:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit/UIKit-3600.9.1/UIDocumentPickerViewController.m:91

I just using your example code as follow:

local docPicker = require("plugin.docPicker") docPicker.init() local widget = require("widget") local bg = display.newRect( display.contentCenterX, display.contentCenterY, display.actualContentWidth, display.actualContentHeight ) bg:setFillColor(.5) local title = display.newText( "Doc Picker Plugin", display.contentCenterX, 20 , native.systemFontBold, 20 ) local exportButton = widget.newButton( { onRelease = function (e) print ("button pressed") docPicker.export(system.pathForFile("test.txt"), function(ev) if (ev.status == "document picked") then native.showAlert( "File Exported", {"Ok"} ) end end) end, label = "Export Doc", x = display.contentCenterX, y = display.contentCenterY-30, }) local exportButton = widget.newButton( { onRelease = function (e) --docPicker.import({"public.image"}, system.pathForFile( "test.png", system.TemporaryDirectory ), function(ev) print ("button pressed") docPicker.import({"public.data"}, system.pathForFile( "test.zip", system.TemporaryDirectory ), function(ev) if (ev.status == "document picked") then local testImage = display.newImage( "test.png", system.TemporaryDirectory, display.contentCenterX, display.contentCenterY+80 ) native.showAlert( "File Imported", "File Imported",{"Ok"} ) end end) end, label = "Import Doc", x = display.contentCenterX, y = display.contentCenterY+30, })

Dear, please, please, forgive me…

I must be silly!

I was using a non activated iCloud profile…

Dear, all is fine… Please, forget this.

Good job dear, and sorry for my mistake

:frowning: So sorry dear.

All works fine. Was my mistake  :unsure:  :frowning:

At the moment to select the profile for building options, I selected the non iCloud one activated, so, that’s was the problem.

Thanks so much again and forgive me please,

Cesar

It will be supported

Dear Scott,

If I need to use the origin file name when importing the file with:

docPicker.import(documentTypes, pathForImport, listener) 

What should I use as pathForImport ?

I have used the following:

docPicker.import({"public.data"}, system.pathForFile( nil, system.DocumentsDirectory ), function(ev) if (ev.status == "document picked") then --All done. native.showAlert( "File Imported OK", {"Ok"} ) else --Error or Cancelled by user end end)

But the nil at the fileName appear to not keep the original fileName.

Can you help me ?

Thanks again !!

I am removing pathForImport because it is not longer used anyways. Please try again in an hour.

Ok dear. I will do.

Perhaps if pathForImport no longer necessary, it is due, the UIDocumentPickerViewController will move get a copy of the external file to the “Inbox” subfolder at DocumentsDirectory., and send an Url with the full path and name for it… isn’t it ?

I will test and let you know.

Thanks so much again,