Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Invalid image path obtained from ShareExtension.data #89

Open
BigPun86 opened this issue Apr 3, 2018 · 28 comments
Open

Invalid image path obtained from ShareExtension.data #89

BigPun86 opened this issue Apr 3, 2018 · 28 comments

Comments

@BigPun86
Copy link

BigPun86 commented Apr 3, 2018

When i navigate to the Host Application and pass the image url which i have obtained from value of ShareExtension then in my real device the imgPath wont work! I actually cannot use the url which looks like this:

/private/var/mobile/Containers/Data/PluginKitPlugin/09BD2F36-975D-4DB4-80FD-2446799A48AE/tmp/RNSE_TEMP_IMG.png

I have tried to check if the imgPath is available. I did this with react-native-fs and there i get for the imgPath the error that the file is not there.

Everything works great on Android (Simulator & RealDevice) as well as on the iOS Simulator. But it fails on iOS RealDevice.

Receiving ShareData:

try {
    const { type, value } = await ShareExtension.data();
    let error;
    const url = `shareExtensionApp://shareImage/${value}`;
    ShareExtension.openURL(url);
    ShareExtension.close();
} catch (e) {
    Alert.alert(null, e);
}

Use value for my Image component:

<Image source={{uri: value}}/>

@isaachinman
Copy link
Collaborator

isaachinman commented Apr 30, 2018

I just ran into this issue myself when testing on a real iOS device. Functionality works perfectly on iOS simulator and Android, but not on a real iOS device (iPhone 6, iOS 11.3).

My received share path looks virtually identical to OP's (eg /private/var/mobile/Containers/...).

@BigPun86 Did you find a way to solve this?

From my limited understanding, this has to do with app containers/permissions.

@BigPun86
Copy link
Author

@isaachinman i forked this project and and dis some stuff in the iOS part, which finally works not. You can have a look here: https://github.com/BigPun86/react-native-share-extension/tree/master/ios

You will need to enable App Groups for both targets (MainApp and Share Extension)

@isaachinman
Copy link
Collaborator

isaachinman commented Apr 30, 2018

@BigPun86 Thanks! Lot of work getting this project to actually work cross-platform...

What was your methodology? Are you copying files to a temporary shared dir between the two apps (via App Group), or did you find a way to share the path by itself without copying?

It would be super helpful if you can open a PR, at least so people like myself can see the diff. I doubt it'll ever get merged, based on how this project is managed...

@BigPun86
Copy link
Author

@isaachinman well i am actually creating a directory related to the app group and then i combine the app group path/url together with my file path/url. I am not good in explaining, but you can have a look at the ShareMaster.h/m => Readme.md and this part https://github.com/BigPun86/react-native-share-extension/blob/master/ios/ReactNativeShareExtension.h#L7

I hope this helps you, it took me 2 weeks to completely integrate the share-extension for ios and android :D

@isaachinman
Copy link
Collaborator

isaachinman commented May 1, 2018

@BigPun86 With app groups in place, it's actually way easier to achieve this than the way you're doing it.

You only need app groups and react-native-fs to accomplish it:

const data = await ShareExtension.data()

if (Platform.OS === 'ios') {
    const appGroupPath = await RNFS.pathForGroup('group.com.myapp')

    await Promise.all(data.map(async (image) => {
        const filename = path.basename(image.value)
        const destination = `${appGroupPath}/${filename}`
        await RNFS.copyFile(image.value, destination)
    }))
}

For any future readers that might need help with this, just let me know.

@BigPun86
Copy link
Author

BigPun86 commented May 1, 2018

@isaachinman thanks a lot, i tried it with react-native-fs, maybe i have missed something. But thanks, i will update my code and test your snippet :)

@isaachinman
Copy link
Collaborator

Cool! The main takeaway here is that what we both want to do is fully possible with react-native-share-extension, no fork needed. (Although I'm actually using a different fork to allow multi-item sharing.)

By the way, I got this idea from #73, which should definitely be merged into master.

@ahmedjamshed
Copy link

ahmedjamshed commented Jul 1, 2018

@isaachinman my code is stuck at this line in share extension.
await RNFS.copyFile(image.value, destination)

I am able to show the image from path in share extenion but not in main app. So I decided to configure app group. I only configured the app group in share extension for now and I am able to get the app group path from this line.

const appGroupPath = await RNFS.pathForGroup('group.com.myapp')

My problem is that when i try to execute this line

await RNFS.copyFile(image.value, destination)

it never fullfills the promise and the lines below this line never get executed although the extension does not crash

Here is my full code

async componentDidMount() {
try {
  const { type, value } = await ShareExtension.data()
  const appGroupPath = await RNFS.pathForGroup('group.com.myapp')
  const filename = path.basename(value)
  const destination = `${appGroupPath}/${filename}`
  await RNFS.copyFile(value, destination) // even tried with seprate then/catch block
 // lines never get executed, promise never gets fulfilled
 ShareExtension.openUrl('myapp://${value}') // gets executed when remove this line
//await RNFS.copyFile(value, destination)
} catch(e) {
 console.log(e.message) // No error returned here because changing state here in actual code
}
}

More Info:

  • I am new to react native and iOS so there could be some odd reason.
  • Changed nothing in plist of share extenion except NSExtensionActivationRule key so could be permisson issue but I am not sure.
  • Enabled group from xcode for share extenison only.

What could be the problem? Can you guide me? BTW sorry for bad formatting.

@isaachinman
Copy link
Collaborator

@ahmedjamshed First, you should always format code when you write in a GitHub issue. Second, how could I possibly help without any error or any information whatsoever? If you post more information here in the proper way, I am happy to help you.

@ahmedjamshed
Copy link

@isaachinman Sorry for bad formatting. I have updated my previous comment,

@isaachinman
Copy link
Collaborator

The whole point of an app group in this case is that it creates a shared directory between your share extension and main app, where both processes can access (read/write).

Sounds like you need to add your main app to the app group, at the very least.

That being said, if copyFile is hanging - ie not throwing and not resolving - it actually sounds like a RNFS bug...

Can you print out image.value and destination?

@ahmedjamshed
Copy link

Can you print out image.value and destination?

Yes, I am able to show the value and destination on extenion UI by calling setState

@isaachinman
Copy link
Collaborator

I meant, can you write it here?

@ahmedjamshed
Copy link

@isaachinman Thanks for helping. My app groups weren't properly configured due to some Bundle Identifier issue. Changing bundle identifier and cleaning the code solved my problem.

@isaachinman
Copy link
Collaborator

Ah, good to hear.

@radreamer
Copy link

radreamer commented Nov 12, 2018

I'm facing with an error while copying a file to an app group destination from iOS Files app (/private/var/mobile/Library/Mobile%2520Documents/com~apple~CloudDocs/Documents/<fileName>):

Error: the file <fileName> couldn't be opened because there is no such file.

but everything works perfectly when I copying photos/videos from my gallery, which have the further path:
/private/var/mobile/Containers/Data/PluginKitPlugin/<uuid>/tmp/RNSE_TEMP_IMG.png

I`m using RNFetchBlob but experienced the same behavior when tried RNFS. My code snippet:

async componentDidMount() {
    try {
      const { value } = await ShareExtension.data()

      if (Platform.OS === 'ios') {
        const appGroupPath = await RNFetchBlob.fs.pathForAppGroup('<my-group-name>')
        const destination = `${appGroupPath}/${value.split('/').slice(-1)[0]}`

        await RNFetchBlob.fs.cp(value.split('file://').slice(-1)[0], destination)
        await ShareExtension.openURL(`<my-deep-link>/${destination}`)

        this.closeExtension()
      } else if (Platform.OS === 'android') {
        await Linking.openURL(`<my-deep-link>/${value}`)
        this.closeExtension()
      }
    } catch () {
      this.closeExtension()
    }
  }

Is it possible to manipulate (copy to app group dir) with files which are hosted under this path /private/var/mobile/Library/Mobile%2520Documents/com~apple~CloudDocs/?

@isaachinman
Copy link
Collaborator

Hi @radreamer, if you're having problems accessing a file when you know it definitely exists at that location, it's almost certainly related to permissions.

I have set up a share extension in the past that copies files to an app group dir and then passes the location onto the main app via query params - it's definitely possible.

Perhaps this also has something to do with the CloudDocs component? Not sure about that.

@oberlaender
Copy link

Could also be that the filetype is not handled by the native code on iOS, it seem only images, urls and 'text/plain' are supported.

#define URL_IDENTIFIER @"public.url"
#define IMAGE_IDENTIFIER @"public.image"
#define TEXT_IDENTIFIER (NSString *)kUTTypePlainText

see ReactNativeShareExtension.m

@radreamer
Copy link

@isaachinman @oberlaender thanks for responses, I tried to share an image from iCloud (through Files app) and the further code

const { type, value } = await ShareExtension.data()
console.log(type, value)

prints (!wrong type):

text/plain file:///private/var/mobile/Library/Mobile%20Documents/com~apple~CloudDocs/Photos/<filename>.jpg

and then copying failed with:

Error: the file <fileName>.jpg couldn't be opened because there is no such file.

so I think, that the problem isn't with file types

@radreamer
Copy link

@oberlaender and I don't get the difference between URL and text? both have almost similar handlers for providers in extractDataFromContext method (urlProvider and textProvider) and what is more important – returns same type on ShareExtension.data().

From the point of view of a react-native app there is no difference between them, am I right?

@oberlaender
Copy link

Both providers return a string and the type text/plain. The url part just makes sure the full url is returned.

@isaachinman
Copy link
Collaborator

@radreamer I don't fully understand your problem, but it seems like you're getting valid file paths without issue. Your issue is related to read permissions. Where are you getting the no such file error? In the share extension, or in your main app?

Can you provide a reproducible example so that we might be able to help you?

@radreamer
Copy link

@isaachinman yes, I'm getting valid file paths, but then I get no such file when try to copy files:

RNFS.copyFile(value.split('file://').slice(-1)[0], destination)

Can you try to share an image from iCloud (via Files app) through your share extension?

@isaachinman
Copy link
Collaborator

@radreamer I don't think your problem has anything to do with react-native-share-extension, if you're getting valid file paths. I'm not an iOS dev by trade, but have you done some Googling and read some docs?

@frenberg
Copy link

frenberg commented Nov 15, 2018

I see this as well... If you look closely att your file path
/private/var/mobile/Library/Mobile%2520Documents/com~apple~CloudDocs/Documents/<fileName>

That Mobile%2520Documents should actually be ...Mobile Documents... Just saw this myself so not sure where this problem arises yet.

@isaachinman
Copy link
Collaborator

@frenberg That's a great point. I've run into URI encoding issues before, but always on Android, not iOS.

This URI is encoded twice:

/private/var/mobile/Library/Mobile%2520Documents/com~apple~CloudDocs/Documents/<fileName>

If I run:

decodeURIComponent(decodeURIComponent('/private/var/mobile/Library/Mobile%2520Documents/com~apple~CloudDocs/Documents/<fileName>'))

I get:

"/private/var/mobile/Library/Mobile Documents/com~apple~CloudDocs/Documents/<fileName>"

@radreamer
Copy link

@frenberg @isaachinman now it works, thanks for your help!

@aryamanm
Copy link

@isaachinman The file “XXX.JPG” couldn’t be opened because you don’t have permission to view it.

Any idea how to fix this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants