Open hippogamesunity opened 2 years ago
For the first point, can you explain in what sort of UI you're planning to display the file sizes? If you are planning to display them in NativeFilePicker's file picker UI, I'd like to warn you that NativeFilePicker uses UIDocumentPickerViewController and AFAIK its native UI can't be customized.
Can you test UISupportsDocumentBrowser case as follows:
#import <Foundation/Foundation.h>
extern "C" int _PixelStudio_StartAccessFile( const char* filePath )
{
NSString *filePathStr = [NSString stringWithUTF8String:filePath];
if( ![[NSURL fileURLWithPath:filePathStr] startAccessingSecurityScopedResource] )
{
NSLog( @"Couldn't start accessing file: %@", filePathStr );
return 0;
}
return 1;
}
extern "C" void _PixelStudio_StopAccessFile( const char* filePath )
{
[[NSURL fileURLWithPath:[NSString stringWithUTF8String:filePath]] stopAccessingSecurityScopedResource];
}
#if !UNITY_EDITOR && UNITY_IOS
[System.Runtime.InteropServices.DllImport( "__Internal" )]
private static extern int _PixelStudio_StartAccessFile( string filePath );
[System.Runtime.InteropServices.DllImport( "__Internal" )]
private static extern void _PixelStudio_StopAccessFile( string filePath );
#endif
#if !UNITY_EDITOR && UNITY_IOS
if( _PixelStudio_StartAccessFile( filePath ) == 0 )
{
// Couldn't grant access to the file, reading it will probably fail
}
#endif
#if !UNITY_EDITOR && UNITY_IOS
_PixelStudio_StopAccessFile( filePath );
#endif
Thanks for replying! It doesn't matter, you can just print this to Console. It's just to confirm that you can access and read files by all possible input URLs.
It would be perfect to get a working demo project with NativeColorPicker that works as expected. There are some blank spaces in the asset.
For example, NativeColorPicker have a feature to declare custom types, but they don't work without some manual fixes in info.plist (need to add CFBundleDocumentTypes and UTExportedTypeDeclarations as orangeagain suggested here https://github.com/yasirkula/UnityNativeFilePicker/issues/7).
I can't create a demo project, I don't have iOS hardware to test it on. I can only give instructions.
Ah, I understand. I'll try your suggestions and will reply soon. Thanks.
I'm trying to open a PSP file from Files app using "Open with" feature. The file is located outside of Pixel Studio persistentDataPath.
Application.absoluteURL=file:///private/var/mobile/Containers/Shared/AppGroup/867471D1-2921-42A5-B986-A6247986BEBA/File%20Provider%20Storage/256_2.psp
Assuming path="file:///private/var/mobile/Containers/Shared/AppGroup/867471D1-2921-42A5-B986-A6247986BEBA/File%20Provider%20Storage/256_2.psp" and passing this to _PixelStudio_StartAccessFile gives 0 and File.Exists returns False
Assuming path="/private/var/mobile/Containers/Shared/AppGroup/867471D1-2921-42A5-B986-A6247986BEBA/File Provider Storage/256_2.psp" and passing this to _PixelStudio_StartAccessFile gives 0 and File.Exists returns False
Assuming path="/var/mobile/Containers/Shared/AppGroup/867471D1-2921-42A5-B986-A6247986BEBA/File Provider Storage/256_2.psp" and passing this to _PixelStudio_StartAccessFile gives 0 and File.Exists returns False
At the same time I can open files located inside persistentDataPath, I just need to remove "file:///private/" from Application.absoluteURL plus Replace("%20", " ") to get a valid path.
Can you try the last 2 paths without removing %20s? 🤞
P.S. In addition, can you change the native function as follows and see what it prints for each path variant:
extern "C" int _PixelStudio_StartAccessFile( const char* filePath )
{
NSString *filePathStr = [NSString stringWithUTF8String:filePath];
if( [[NSFileManager defaultManager] isReadableFileAtPath:filePathStr] )
NSLog( @"File was accessible before" );
else
NSLog( @"File wasn't accessible before" );
if( ![[NSURL fileURLWithPath:filePathStr] startAccessingSecurityScopedResource] )
{
NSLog( @"Couldn't start accessing file: %@", filePathStr );
if( [[NSFileManager defaultManager] isReadableFileAtPath:filePathStr] )
NSLog( @"File is now accessible before" );
else
NSLog( @"File still isn't accessible before" );
return 0;
}
if( [[NSFileManager defaultManager] isReadableFileAtPath:filePathStr] )
NSLog( @"File is accessible" );
else
NSLog( @"File isn't accessible" );
return 1;
}
Hello! I've tried this with no luck. Application.absoluteURL=file:///private/var/mobile/Containers/Shared/AppGroup/867471D1-2921-42A5-B986-A6247986BEBA/File%20Provider%20Storage/256_2.psp
_PixelStudio_StartAccessFile = 0
path=/private/var/mobile/Containers/Shared/AppGroup/867471D1-2921-42A5-B986-A6247986BEBA/File%20Provider%20Storage/256_2.psp
File.Exists=False
_PixelStudio_StartAccessFile = 0
path=var/mobile/Containers/Shared/AppGroup/867471D1-2921-42A5-B986-A6247986BEBA/File%20Provider%20Storage/256_2.psp
File.Exists=False
Here is my code:
Which NSLogs are printed to Xcode console?
I've noticed that the second path starts with "var" instead of "/var". Checking it again...
2021-10-30 13:24:05.122074+0300 PixelStudio[9337:1007047] [connection] nw_read_request_report [C1] Receive failed with error "Software caused connection abort" 2021-10-30 13:24:05.126054+0300 PixelStudio[9337:1007047] [connection] nw_read_request_report [C3] Receive failed with error "Software caused connection abort" 2021-10-30 13:24:05.127445+0300 PixelStudio[9337:1007047] [connection] nw_read_request_report [C4] Receive failed with error "Software caused connection abort" -> applicationWillEnterForeground() -> applicationDidBecomeActive() OpenByPath: Application.absoluteURL=file:///private/var/mobile/Containers/Shared/AppGroup/867471D1-2921-42A5-B986-A6247986BEBA/File%20Provider%20Storage/256_2.psp Assets.Scripts.Engine:OpenByPath() Assets.Scripts.Engine:OnApplicationPause(Boolean)
2021-10-30 13:24:05.603006+0300 PixelStudio[9337:1006852] File wasn't accessible before 2021-10-30 13:24:05.603081+0300 PixelStudio[9337:1006852] Couldn't start accessing file: /private/var/mobile/Containers/Shared/AppGroup/867471D1-2921-42A5-B986-A6247986BEBA/File%20Provider%20Storage/256_2.psp 2021-10-30 13:24:05.603127+0300 PixelStudio[9337:1006852] File still isn't accessible before _PixelStudio_StartAccessFile = 0 Assets.Scripts.Engine:OpenByPath() Assets.Scripts.Engine:OnApplicationPause(Boolean)
path=/private/var/mobile/Containers/Shared/AppGroup/867471D1-2921-42A5-B986-A6247986BEBA/File%20Provider%20Storage/256_2.psp Assets.Scripts.Engine:OpenByPath() Assets.Scripts.Engine:OnApplicationPause(Boolean)
File.Exists=False Assets.Scripts.Engine:OpenByPath() Assets.Scripts.Engine:OnApplicationPause(Boolean)
2021-10-30 13:24:05.605561+0300 PixelStudio[9337:1006852] File wasn't accessible before 2021-10-30 13:24:05.605616+0300 PixelStudio[9337:1006852] Couldn't start accessing file: /var/mobile/Containers/Shared/AppGroup/867471D1-2921-42A5-B986-A6247986BEBA/File%20Provider%20Storage/256_2.psp 2021-10-30 13:24:05.605660+0300 PixelStudio[9337:1006852] File still isn't accessible before _PixelStudio_StartAccessFile = 0 Assets.Scripts.Engine:OpenByPath() Assets.Scripts.Engine:OnApplicationPause(Boolean)
path=/var/mobile/Containers/Shared/AppGroup/867471D1-2921-42A5-B986-A6247986BEBA/File%20Provider%20Storage/256_2.psp Assets.Scripts.Engine:OpenByPath() Assets.Scripts.Engine:OnApplicationPause(Boolean)
File.Exists=False Assets.Scripts.Engine:OpenByPath() Assets.Scripts.Engine:OnApplicationPause(Boolean)
2021-10-30 13:24:06.089745+0300 PixelStudio[9337:1008496] [connection] nw_endpoint_handler_set_adaptive_read_handler [C8.1 87.250.250.207:443 ready channel-flow (satisfied (Path is satisfied), viable, interface: en0, ipv4, dns)] unregister notification for read_timeout failed 2021-10-30 13:24:06.089865+0300 PixelStudio[9337:1008496] [connection] nw_endpoint_handler_set_adaptive_write_handler [C8.1 87.250.250.207:443 ready channel-flow (satisfied (Path is satisfied), viable, interface: en0, ipv4, dns)] unregister notification for write_timeout failed 2021-10-30 13:24:06.109387+0300 PixelStudio[9337:1007047] [connection] nw_endpoint_handler_set_adaptive_read_handler [C9.1 35.241.52.229:443 ready channel-flow (satisfied (Path is satisfied), viable, interface: en0, ipv4, dns)] unregister notification for read_timeout failed 2021-10-30 13:24:06.109432+0300 PixelStudio[9337:1007047] [connection] nw_endpoint_handler_set_adaptive_write_handler [C9.1 35.241.52.229:443 ready channel-flow (satisfied (Path is satisfied), viable, interface: en0, ipv4, dns)] unregister notification for write_timeout failed 2021-10-30 13:24:06.154683+0300 PixelStudio[9337:1007036] [YandexMobileMetrica] Client event is sent: AppStart. (apiKey: c076437d-xxxx-xxxx-xxxx-xxxxxxxx1efc). 2021-10-30 13:24:06.154715+0300 PixelStudio[9337:1007036] [YandexMobileMetrica] Profile event is sent. (apiKey: c076437d-xxxx-xxxx-xxxx-xxxxxxxx1efc). 2021-10-30 13:24:06.154729+0300 PixelStudio[9337:1007036] [YandexMobileMetrica] Client event is sent: OpenWindow. (apiKey: c076437d-xxxx-xxxx-xxxx-xxxxxxxx1efc). 2021-10-30 13:24:06.154742+0300 PixelStudio[9337:1007036] [YandexMobileMetrica] Client event is sent: OpenWindow. (apiKey: c076437d-xxxx-xxxx-xxxx-xxxxxxxx1efc). 2021-10-30 13:24:06.154755+0300 PixelStudio[9337:1007036] [YandexMobileMetrica] Client event is sent: OpenWindow. (apiKey: c076437d-xxxx-xxxx-xxxx-xxxxxxxx1efc). 2021-10-30 13:24:06.155747+0300 PixelStudio[9337:1007036] [YandexMobileMetrica] Client event is removed from db: AppStart. (apiKey: c076437d-xxxx-xxxx-xxxx-xxxxxxxx1efc). 2021-10-30 13:24:06.155766+0300 PixelStudio[9337:1007036] [YandexMobileMetrica] Profile event is removed from db. (apiKey: c076437d-xxxx-xxxx-xxxx-xxxxxxxx1efc). 2021-10-30 13:24:06.155782+0300 PixelStudio[9337:1007036] [YandexMobileMetrica] Client event is removed from db: OpenWindow. (apiKey: c076437d-xxxx-xxxx-xxxx-xxxxxxxx1efc). 2021-10-30 13:24:06.155794+0300 PixelStudio[9337:1007036] [YandexMobileMetrica] Client event is removed from db: OpenWindow. (apiKey: c076437d-xxxx-xxxx-xxxx-xxxxxxxx1efc). 2021-10-30 13:24:06.155806+0300 PixelStudio[9337:1007036] [YandexMobileMetrica] Client event is removed from db: OpenWindow. (apiKey: c076437d-xxxx-xxxx-xxxx-xxxxxxxx1efc).
Please note that application.persistentpath is like /var/mobile/Containers/Data/Application/GUID, but the path I can't access has "/Shared/AppGroup/" insted of "/Data/Application/" (which is accessible).
None of the solutions I've initially suggested here seem to work for these paths.
When I google "Containers/Shared/AppGroup", I usually see answers mentioning "enabling App Groups capability". I have no idea what it is or if it's related to this issue, though 😄
I think I've found the reason behind this issue: https://developer.apple.com/documentation/foundation/nsurl
Security-Scoped URLs and String Paths
In a macOS app, when you copy a security-scoped URL, the copy has the security scope of the original. You gain access to the file-system resource (that the URL points to) just as you would with the original URL: by calling the startAccessingSecurityScopedResource method (or its Core Foundation equivalent).
If you need a security-scoped URL’s path as a string value (as provided by the path method), such as to provide to an API that requires a string value, obtain the path from the URL as needed. Note, however, that a string-based path obtained from a security-scoped URL does not have security scope and you cannot use that string to obtain access to a security-scoped resource.
Unity returns us the file path as a string and the security scope is lost in the process. You need the original security-scoped NSURL which I'm skeptical that Unity provides. Retrieving that NSURL will probably require modifying Unity's own native classes like AppDelegate and it's beyond my expertise. Your best bet would be to contact Unity team for support in this case.
Possibly related reading: https://developer.apple.com/documentation/uikit/view_controllers/adding_a_document_browser_to_your_app/setting_up_a_document_browser_app
One trick you can try beforehand is, setting LSSupportsOpeningDocumentsInPlace to false in Info.plist. I don't know if it will affect your files' visibility in Files app.
Unrelated but, you've previously mentioned iCloud support which might be achievable by setting UIFileSharingEnabled to true in Info.plist.
Many thanks for your suggestions. I'll try them.
Found some related info: https://stackoverflow.com/a/57632194/5513493 "startAccessingSecurityScopedResource" is also mentioned there.
I'm assuming disabling "Supports opening documents in place" didn't work for you.
Yes, LSSupportsOpeningDocumentsInPlace=NO doesn't work if UISupportsDocumentBrowser is enabled. Files are not copied to Inbox folders (that are always accessible for reading).
I see. As I said, startAccessingSecurityScopedResource is impossible without the original NSURL which Unity doesn't provide (AFAIK).
Are you sure Application.absoluteURL=file:///private/var/mobile/Containers/Shared/AppGroup/867471D1-2921-42A5-B986-A6247986BEBA/File%20Provider%20Storage/256_2.psp is not NSURL?
Ah, you may mean this https://forum.unity.com/threads/5-4b11-ios-url-schemes.393478/#post-2583564
I'm not sure about this forum thread. They never mention NSURL.
Application.absoluteURL is definitely a string, Unity doesn't have an NSURL type. Think of NSURL as a data type that happens to have a string field as well as some fields that store security credentials (which are required for startAccessingSecurityScopedResource). Application.absoluteURL is only the string field of that data type. Since you only have the string and not the NSURL, you simply don't have access to the security credentials. You absolutely have to retrieve the original NSURL and it'll require modifying Unity's native source code in Xcode. There's no way around it to my knowledge but if there is, I'd like to know that, as well.
Ok, I'll create a thread on Unity forums and will let you know about further progress. Thanks for your time!
Thanks for letting me know about the progress! Please post the forum thread link here, as well.
Make a demo Unity app for iOS/Android with NativeFilePicker plugin imported. The app should have the following features: