Closed retyui closed 3 years ago
Looks like the example implements it, how does the example app work for you?
Great! So it is easy to reproduce with code the maintainers have access to, since you didn't include a link to the repo
It's pretty easy to hack System.err.println("ReactNativeJS", "whatever you want to log here") lines into the Java implementation directly in node_modules and trace it through. What did you see as arguments and return values in logcat when you did that and attempted to access the underlying system APIs?
@mikehardy I don't understand what logcat values you want to see?
@mikehardy I don't understand what logcat values you want to see?
I think @mikehardy means the if you could debug the native side, testing the output on the logcat.
Also facing the same issue on android and working fine on IOS.
@MateusAndrade How can help you to show the problem? Given that this problem is reproduced on the example application
@MateusAndrade How can help you to show the problem? Given that this problem is reproduced on the example application
We would appreciate any help with that, you can try editing the native code directly on ios
and android
to see how it works.
Same issue..
` <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.android.test">
<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" />
<application
android:requestLegacyExternalStorage="true"
android:name="com.android.test.MainApplication"
android:label="@string/app_name"
android:largeHeap="true"
android:icon="@mipmap/show_launcher"
android:roundIcon="@mipmap/show_launcher_round"
android:allowBackup="false"
android:theme="@style/AppTheme">
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths" />
</provider>
<meta-data
android:name="com.google.android.gms.ads.AD_MANAGER_APP"
android:value="true"/>
<!-- Add this SplashActivity -->
<activity
android:name="com.android.test.SplashActivity"
android:theme="@style/SplashTheme"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.android.test.MainActivity"
android:label="@string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
</application>
`
filepaths.xml
`<?xml version="1.0" encoding="utf-8"?>
@mikehardy @MateusAndrade
During the sharing process (on Adnroid 10) you will see next exceptions:
java.lang.SecurityException: Permission Denial: opening provider cl.json.RNShareFileProvider from ProcessRecord{2fa6f3d 4918:com.instagram.android/u0a260} (pid=4918, uid=10260) that is not exported from UID 10268
java.lang.ClassNotFoundException: Didn't find class "androidx.core.app.CoreComponentFactory"
There is a full logcal output:
Click to expand a logcal output
Did you try setting access to the storage on your application or something similar to that?
@MateusAndrade
"your application"
I use an ./example app
Did you try setting access to the storage
And of course, I provided "Storage" access
ClassNotFoundException? How is that Android10 specific? That's an APK construction issue. Perhaps a dependency is missing on androidx.core? Not sure how but ClassNotFoundException means "you didn't have the right dependencies in your app" somehow.
Very strange.
https://developer.android.com/jetpack/androidx/releases/core
@retyui @alicaglayan
I found a workaround that seems to be working consistently.
global.Buffer = global.Buffer || require('buffer').Buffer // add this somewhere high in the app hierarchy
const backgroundImageRes = await axios.get(
'http://www.am570.com.br/images/posts/1119/1119.jpg',
{
responseType: 'arraybuffer',
},
)
const base64BackgroundImage = Buffer.from(
backgroundImageRes.data,
'binary',
).toString('base64')
const stickerImageRes = await axios.get('http://www.am570.com.br/images/posts/1119/1119.jpg', {
responseType: 'arraybuffer',
})
const base64StickerImage = Buffer.from(
stickerImageRes.data,
'binary',
).toString('base64')
const shareOptions = {
social: Share.Social.INSTAGRAM_STORIES,
method: Share.InstagramStories.SHARE_BACKGROUND_AND_STICKER_IMAGE,
stickerImage: `data:image/jpeg;base64,${base64StickerImage}`,
backgroundImage: `data:image/jpeg;base64,${base64BackgroundImage}`,
backgroundTopColor: Colors.BRAND_PRIMARY,
backgroundBottomColor: Colors.BRAND_SECONDARY,
attributionURL: shareLink, // beta
forceDialog: true, // necessary due to bug in node_modules/react-native-share/android/src/main/java/cl/json/social/SingleShareIntent.java
}
console.log(shareOptions)
const res = await Share.shareSingle(shareOptions)
ps. on IOS it works fine, except that the promise from shareSingle won't return.
const res = await Share.shareSingle(shareOptions)
@mikehardy @MateusAndrade , is this a known issue or should I open a new issue here on github? Are there any workarounds?
@leeeomaaax
java.lang.SecurityException: Permission Denial: opening provider cl.json.RNShareFileProvider from ProcessRecord{2fa6f3d 4918:com.instagram.android/u0a260} (pid=4918, uid=10260) that is not exported from UID 10268
Seems we need to grant URI permission all the time?
@retyui, I'm not sure what URI permission means on the android native side (is it the same as WRITE_EXTERNAL_STORAGE?)
On the react-native side, your app will need WRITE_EXTERNAL_STORAGE permission but will ask for it only once.
ps. I believe this is a temporary workaround since the native android code from this lib seems to be handling the permissions but it's not (for the shareSingle at least).
const writeGranted = Platform.OS === 'ios' || (await PermissionsAndroid.request( PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE, )) if (!writeGranted) return
WRITE_EXTERNAL_STORAGE permission won't even be granted in modern android if I understand correctly https://developer.android.com/preview/privacy/storage#permissions
So that solution should be discarded immediately for new solutions
It's my understanding from native android that granting URI access is the right way to do it basically at all times, along with a FileProvider configured in android resource XML paths, some example:
Hello, I am facing the same issue.
Anyone have any success to fix or bypass this error?
The behavior is the same as the gif provided by @retyui
@lcsvcn
To work for me on Andoird I did the next:
1) Add a permission in android/app/src/main/AndroidManifest.xml
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
2) Then I requested a persimmon:
const result = await PermissionsAndroid.request( PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE)
if(!isGranted(result)){
// show warning message
return;
}
3) The when permission was granted invoke .shareSingle(...)
with a forceDialog
flag and images as base64!
const shareOptions = {
title,
method: Share.InstagramStories.SHARE_BACKGROUND_AND_STICKER_IMAGE,
// use base64
backgroundImage: `data:image/jpeg;base64,...`,
stickerImage: `data:image/jpeg;base64,...`,,
social: Share.Social.INSTAGRAM_STORIES,
// necessary due to bug in node_modules/react-native-share/android/src/main/java/cl/json/social/SingleShareIntent.java
forceDialog: true,
};
await Share.shareSingle(shareOptions);
It appears only share background and sticker image works for Android.
For example:
Share sticker image works for iOS but not Android (android instagram opens for a brief second but then closes)
try {
const shareOptions = {
method: Share.InstagramStories.SHARE_STICKER_IMAGE,
stickerImage: SHARE_STAR_IMAGE_BASE64,
backgroundBottomColor: '#FEFEFE',
backgroundTopColor: '#FEFEFE',
social: Share.Social.INSTAGRAM_STORIES,
failOnCancel: false,
forceDialog: true
}
await Share.shareSingle(shareOptions);
}
catch (err) {
Alert.alert('Could not share to Instagram');
}
};
Share background and sticker image works for iOS and Android
try {
const shareOptions = {
method: Share.InstagramStories.SHARE_BACKGROUND_AND_STICKER_IMAGE,
stickerImage: SHARE_STAR_IMAGE_BASE64,
backgroundImage: SHARE_STAR_IMAGE_BASE64,
backgroundBottomColor: '#FEFEFE',
backgroundTopColor: '#FEFEFE',
social: Share.Social.INSTAGRAM_STORIES,
failOnCancel: false,
forceDialog: true
}
await Share.shareSingle(shareOptions);
}
catch (err) {
Alert.alert('Could not share to Instagram');
}
@dylan-westbury there is anything being shown in the logcat when sharing a sticker on Android?
@MateusAndrade nothing helpful to point out why it was crashing, I believe an exception within Instagram was triggering and it was attempting to write to instagram error logs.
@MateusAndrade I did note these errors from logcat, but they also show for when insta story share is working using background and sticker mode
07-28 14:18:30.505 5022 5035 E DatabaseUtils: java.lang.SecurityException: Permission Denial: reading androidx.core.content.FileProvider uri content://com.heyswysh.swysh.provider/myexternalimages/sticker.jpg from pid=4499, uid=10093 requires the provider be exported, or grantUriPermission()
07-28 14:18:30.505 5022 5035 E DatabaseUtils: at android.content.ContentProvider.enforceReadPermissionInner(ContentProvider.java:631)
07-28 14:18:30.505 5022 5035 E DatabaseUtils: at android.content.ContentProvider$Transport.enforceReadPermission(ContentProvider.java:501)
07-28 14:18:30.505 5022 5035 E DatabaseUtils: at android.content.ContentProvider$Transport.enforceFilePermission(ContentProvider.java:492)
07-28 14:18:30.505 5022 5035 E DatabaseUtils: at android.content.ContentProvider$Transport.openTypedAssetFile(ContentProvider.java:420)
07-28 14:18:30.505 5022 5035 E DatabaseUtils: at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:302)
07-28 14:18:30.505 5022 5035 E DatabaseUtils: at android.os.Binder.execTransact(Binder.java:697)
07-28 14:18:30.506 4499 4534 E StoryShareMediator: Exception in ExternalMediaImportCallable
07-28 14:18:30.506 4499 4534 E StoryShareMediator: java.lang.SecurityException: Permission Denial: reading androidx.core.content.FileProvider uri content://com.heyswysh.swysh.provider/myexternalimages/sticker.jpg from pid=4499, uid=10093 requires the provider be exported, or grantUriPermission()
07-28 14:18:30.506 4499 4534 E StoryShareMediator: at android.os.Parcel.readException(Parcel.java:2004)
07-28 14:18:30.506 4499 4534 E StoryShareMediator: at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:183)
07-28 14:18:30.506 4499 4534 E StoryShareMediator: at android.database.DatabaseUtils.readExceptionWithFileNotFoundExceptionFromParcel(DatabaseUtils.java:146)
07-28 14:18:30.506 4499 4534 E StoryShareMediator: at android.content.ContentProviderProxy.openTypedAssetFile(ContentProviderNative.java:698)
07-28 14:18:30.506 4499 4534 E StoryShareMediator: at android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:1410)
07-28 14:18:30.506 4499 4534 E StoryShareMediator: at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:1247)
07-28 14:18:30.506 4499 4534 E StoryShareMediator: at android.content.ContentResolver.openInputStream(ContentResolver.java:967)
07-28 14:18:30.505 5022 5035 E DatabaseUtils: java.lang.SecurityException: Permission Denial: reading androidx.core.content.FileProvider uri content://com.heyswysh.swysh.provider/myexternalimages/sticker.jpg from pid=4499, uid=10093 requires the provider be exported, or grantUriPermission()
I think this line is related to the permissions when sharing files, maybe you are missing some permission/implementation on the native side on Android?
Also, we might need to look at the code on Android here:
Maybe it helps to understand the problem(
I use a workaround with a local file and it works on Android without asking Storage permissions.
import Share from 'react-native-share';
import { DocumentDirectoryPath, writeFile } from 'react-native-fs';
const { INSTAGRAM_STORIES } = Share.Social;
const { SHARE_BACKGROUND_IMAGE } = Share.InstagramStories;
const normalisePath = (path) => Platform.select({ default: path, android: `file://${path}` });
export const base64ToLocalFile = async ({ base64, filename }) => {
const path = `${DocumentDirectoryPath}/${filename}`;
await writeFile(path, base64, 'base64');
return normalisePath(path);
};
export const shareToInstagramStory = async (base64Data) => {
const backgroundImage =
Platform.OS === 'ios'
? `data:image/jpeg;base64,${base64Data}`
: await base64ToLocalFile({ base64: base64Data, filename: 'tmp.jpg' });
const shareOptions = {
title: 'test',
method: SHARE_BACKGROUND_IMAGE,
backgroundImage,
social: INSTAGRAM_STORIES,
...Platform.select({
// Necessary due to bug in
// node_modules/react-native-share/android/src/main/java/cl/json/social/SingleShareIntent.java
android: {
forceDialog: true,
},
}),
};
await Share.shareSingle(shareOptions);
};
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. You may also mark this issue as a "discussion" and i will leave this open.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. You may also mark this issue as a "discussion" and i will leave this open.
Same issue here, it works on iOS and not android... If I use shareSingle, it doesn't work
captureRef(this.viewRef.current, {
format: "jpg",
quality: 1,
result: 'base64',
}).then(uri => {
let shareOptions = {
method: Share.InstagramStories.SHARE_STICKER_IMAGE,
stickerImage: `data:image/jpg;base64,${uri}`,
backgroundBottomColor: '#32323C',
backgroundTopColor: '#3D4C66',
social: Share.Social.INSTAGRAM_STORIES,
failOnCancel: false,
forceDialog: true
};
Share.shareSingle(shareOptions).then((res) => { console.log('res',res) })
.catch((err) => { console.log('err',err); });
},
).catch(err => console.log(err))
but, if I use Share.Open like this :
let shareOptions = {
url: `data:image/jpg;base64,${uri}`,
backgroundBottomColor: '#32323C',
backgroundTopColor: '#3D4C66',
failOnCancel: false,
forceDialog: true
};
Share.open(shareOptions).then((res) => { console.log('res',res) })
.catch((err) => { console.log('err',err); });
And then, going to instagram stories, it works...
Do you have an idea why ?
Also having this, Facebook stories work fine on both iOS and Android, but Insta only works on iOS. Android throws a native error of file permissions as above.
@RenatoSerra22
We use a workaround with base64 and it work for Android to
see: https://github.com/react-native-share/react-native-share/issues/808#issuecomment-668741231
@retyui thank you, i tried that but i think something was still failing native side, ill try to do some USB debugging.
Just tested it with logcat and still getting the same error on Android 11, even with your workaround unfortunately :(
Same issue, it is working well on android emulator, but not on real device, i tested on Oppo
If i try to pass down a uri to a file instead of base64, i get the following error instead
``` 04-01 12:23:18.154 23118 23180 E StoryShareMediator: Exception in ExternalMediaImportCallable 04-01 12:23:18.154 23118 23180 E StoryShareMediator: java.io.FileNotFoundException: open failed: EACCES (Permission denied) 04-01 12:23:18.154 23118 23180 E StoryShareMediator: at android.os.ParcelFileDescriptor.openInternal(ParcelFileDescriptor.java:315) 04-01 12:23:18.154 23118 23180 E StoryShareMediator: at android.os.ParcelFileDescriptor.open(ParcelFileDescriptor.java:220) 04-01 12:23:18.154 23118 23180 E StoryShareMediator: at X.2wi.A00(:11) 04-01 12:23:18.154 23118 23180 E StoryShareMediator: at X.2wi.A01(:14) 04-01 12:23:18.154 23118 23180 E StoryShareMediator: at X.Eto.A01(:8) 04-01 12:23:18.154 23118 23180 E StoryShareMediator: at X.DFo.A00(:8) 04-01 12:23:18.154 23118 23180 E StoryShareMediator: at X.4eP.A00(:12) 04-01 12:23:18.154 23118 23180 E StoryShareMediator: at X.Cup.run(:28) 04-01 12:23:18.154 23118 23180 E StoryShareMediator: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) 04-01 12:23:18.154 23118 23180 E StoryShareMediator: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) 04-01 12:23:18.154 23118 23180 E StoryShareMediator: at java.lang.Thread.run(Thread.java:919) 04-01 12:23:18.154 23118 23180 E StoryShareMediator: at X.0R5.run(:5) 04-01 12:23:18.155 23118 23118 E IgZeroNetworkChangeTrigger: Could not dispatch action since the SDK service is disabled 04-01 12:23:18.155 23118 23118 E IgZeroNetworkChangeTrigger: X.2LW: The Zero SDK service is not enabled 04-01 12:23:18.155 23118 23118 E IgZeroNetworkChangeTrigger: at X.1FB.A00(:9) 04-01 12:23:18.155 23118 23118 E IgZeroNetworkChangeTrigger: at X.1FK.BEC(:0) 04-01 12:23:18.155 23118 23118 E IgZeroNetworkChangeTrigger: at X.0cx.A01(:66) 04-01 12:23:18.155 23118 23118 E IgZeroNetworkChangeTrigger: at X.0cx.onAppForegrounded(:12) 04-01 12:23:18.155 23118 23118 E IgZeroNetworkChangeTrigger: at X.0ms.A01(:76) 04-01 12:23:18.155 23118 23118 E IgZeroNetworkChangeTrigger: at X.0ms.B69(:0) 04-01 12:23:18.155 23118 23118 E IgZeroNetworkChangeTrigger: at com.instagram.base.activity.IgActivity.onResume(:30) 04-01 12:23:18.155 23118 23118 E IgZeroNetworkChangeTrigger: at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1453) 04-01 12:23:18.155 23118 23118 E IgZeroNetworkChangeTrigger: at android.app.Activity.performResume(Activity.java:8050) 04-01 12:23:18.155 23118 23118 E IgZeroNetworkChangeTrigger: at android.app.ActivityThread.performResumeActivity(ActivityThread.java:4266) 04-01 12:23:18.155 23118 23118 E IgZeroNetworkChangeTrigger: at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:4308) 04-01 12:23:18.155 23118 23118 E IgZeroNetworkChangeTrigger: at android.app.servertransaction.ResumeActivityItem.execute(ResumeActivityItem.java:52) 04-01 12:23:18.155 23118 23118 E IgZeroNetworkChangeTrigger: at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:176) 04-01 12:23:18.155 23118 23118 E IgZeroNetworkChangeTrigger: at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97) 04-01 12:23:18.155 23118 23118 E IgZeroNetworkChangeTrigger: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2067) 04-01 12:23:18.155 23118 23118 E IgZeroNetworkChangeTrigger: at android.os.Handler.dispatchMessage(Handler.java:107) 04-01 12:23:18.155 23118 23118 E IgZeroNetworkChangeTrigger: at android.os.Looper.loop(Looper.java:224) 04-01 12:23:18.155 23118 23118 E IgZeroNetworkChangeTrigger: at android.app.ActivityThread.main(ActivityThread.java:7519) 04-01 12:23:18.155 23118 23118 E IgZeroNetworkChangeTrigger: at java.lang.reflect.Method.invoke(Native Method) 04-01 12:23:18.155 23118 23118 E IgZeroNetworkChangeTrigger: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539) 04-01 12:23:18.155 23118 23118 E IgZeroNetworkChangeTrigger: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:995) 04-01 12:23:18.160 23118 23118 E IgZeroAppLifecycleTrigger: Could not dispatch action since the SDK service is disabled 04-01 12:23:18.160 23118 23118 E IgZeroAppLifecycleTrigger: X.2LW: The Zero SDK service is not enabled 04-01 12:23:18.160 23118 23118 E IgZeroAppLifecycleTrigger: at X.1FB.A00(:9) 04-01 12:23:18.160 23118 23118 E IgZeroAppLifecycleTrigger: at X.1FA.onAppForegrounded(:7) 04-01 12:23:18.160 23118 23118 E IgZeroAppLifecycleTrigger: at X.0ms.A01(:76) 04-01 12:23:18.160 23118 23118 E IgZeroAppLifecycleTrigger: at X.0ms.B69(:0) 04-01 12:23:18.160 23118 23118 E IgZeroAppLifecycleTrigger: at com.instagram.base.activity.IgActivity.onResume(:30) 04-01 12:23:18.160 23118 23118 E IgZeroAppLifecycleTrigger: at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1453) 04-01 12:23:18.160 23118 23118 E IgZeroAppLifecycleTrigger: at android.app.Activity.performResume(Activity.java:8050) 04-01 12:23:18.160 23118 23118 E IgZeroAppLifecycleTrigger: at android.app.ActivityThread.performResumeActivity(ActivityThread.java:4266) 04-01 12:23:18.160 23118 23118 E IgZeroAppLifecycleTrigger: at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:4308) 04-01 12:23:18.160 23118 23118 E IgZeroAppLifecycleTrigger: at android.app.servertransaction.ResumeActivityItem.execute(ResumeActivityItem.java:52) 04-01 12:23:18.160 23118 23118 E IgZeroAppLifecycleTrigger: at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:176) 04-01 12:23:18.160 23118 23118 E IgZeroAppLifecycleTrigger: at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97) 04-01 12:23:18.160 23118 23118 E IgZeroAppLifecycleTrigger: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2067) 04-01 12:23:18.160 23118 23118 E IgZeroAppLifecycleTrigger: at android.os.Handler.dispatchMessage(Handler.java:107) 04-01 12:23:18.160 23118 23118 E IgZeroAppLifecycleTrigger: at android.os.Looper.loop(Looper.java:224) 04-01 12:23:18.160 23118 23118 E IgZeroAppLifecycleTrigger: at android.app.ActivityThread.main(ActivityThread.java:7519) 04-01 12:23:18.160 23118 23118 E IgZeroAppLifecycleTrigger: at java.lang.reflect.Method.invoke(Native Method) 04-01 12:23:18.160 23118 23118 E IgZeroAppLifecycleTrigger: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539) 04-01 12:23:18.160 23118 23118 E IgZeroAppLifecycleTrigger: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:995) ```
Ive been trying to debug this for a while on the native side with no success :/ i'd be happy to contribute with a PR but i cant find the root cause. @MateusAndrade any guidance would be awesome i'd really love to ship this feature and seems quite a few of us are stuck. 🙏
If i try to pass down a uri to a file instead of base64, i get the following error instead
Click for stack trace Ive been trying to debug this for a while on the native side with no success :/ i'd be happy to contribute with a PR but i cant find the root cause. @MateusAndrade any guidance would be awesome i'd really love to ship this feature and seems quite a few of us are stuck. 🙏
Hi @RenatoSerra22, you are welcome! Did you try debugging using the example application? Usually, this works for me, also I think this is related to this file as @retyui stated.
Btw, what do you think about updating the docs with @retyui work-around? It's not a fix for the problem, but at least it will let other users trespass this issue until a proper fix is sent!
Let me know if there is anything that I can help you with. 😄
Ok turns out in my case its because im stupid 😂 I installed instagram and logged in on my test phone, but never posted anything so i was never prompted for storage permissions by instagram. The error i was getting stopped once i gave instagram storage permissions, i was never using base64 but instead always passing a local file uri which is what @retyui is converting to in his workaround.
nothing is working, no instagram story , no facebook story
I have spent a couple on days on the problem by myself and with my colleagues, and tried every single solution I found. @retyui's solution also didn't work for me. Moreover, his solution worked on one half of the phones and didn't work on the other half, e.g. it didn't work on some high-end phones and didn't work on some mid-end phones. The was no relationship between the processor power and Android version. We came to the conclusion that the bug is in the react-native-share
library, but we were wrong, more on this later in the text.
I have also implemented a native module with the method that was wrote as on Instagram Platform documentation page. Still wasn't working. Then I dived into the logs trying out how to find the right combination of extras
and flags
for the Intent
on Android to mimic the Intent that is passed when sharing from the Share Menu and make it work.
The solution is working on all devices and Android versions that we have to test on. The key is to use Intent.EXTRA_STREAM
.
Here is the code:
@ReactMethod
fun shareToInstagramStories(encodedUri: String, promise: Promise) {
val fileUri = FileProvider.getUriForFile(
context,
"${BuildConfig.APPLICATION_ID}.provider",
encodedUri.toUri().toFile()
)
val intent = Intent(Intent.ACTION_SEND).apply {
component = ComponentName(
"com.instagram.android",
"com.instagram.share.handleractivity.StoryShareHandlerActivity"
)
flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
type = "image/png"
putExtra(Intent.EXTRA_STREAM, fileUri)
}
context.grantUriPermission("com.instagram.android", fileUri, Intent.FLAG_GRANT_READ_URI_PERMISSION)
context.addActivityEventListener(object : ActivityEventListener {
override fun onNewIntent(intent: Intent?) {
// Do nothing
}
override fun onActivityResult(
activity: Activity?,
requestCode: Int,
resultCode: Int,
data: Intent?
) {
if (requestCode == SHARE_REQUEST_CODE) {
promise.resolve("Shared to Instagram Stories.")
}
}
})
try {
context.startActivityForResult(intent, SHARE_REQUEST_CODE, null)
} catch (e: ActivityNotFoundException) {
promise.reject("-1001", "Instagram app not found.")
}
}
However, one problem persists: now we cannot pass in additional parameters such as "top_background_color"
and "bottom_background_color"
that you can also need. We needed them. Spent another day on this trying every combination of Intent actions
and extras
, data
and ClipData
. It worked only on the second call of the method where the first call only opened Instagram camera.
Some hours ago an update with the new version of Instagram arrived to the Play Store without any information of the update changes. I updated Instagram on the phone and it magically worked!
So I tried the initial implementation of the sharing to Instagram Stories in our app that uses react-native-share
and checked that it works now! The native implementation as described on Instagram Platform documentation page also works from now as it should have.
The conclusion of the story is that sharing to Instagram Stories is finally fixed in the Instagram app itself and works! There was a bug of their side. The version of Instagram app with the fix is 182.0.0.29.124
.
To cover every user of our app with the working solution we now use the implementation with react-native-share
and check the version of Instagram installed on the user's device with PackageManager
on Android to fallback to the native module implementation that I wrote above.
@artnest i will try this, thank you so much for you work, you and your team !
well done @artnest, yeah there was a bug on instagram side with a concurrency issue accessing preferences, it would cause stories to open but not load the picture into the story. I tested different apps that share stories to make sure it was the error i saw from insta in the logs and they had the same issue. I started saving my image to users library so i could launch, and they could then load it from there once stories open. But i can confirm you are right and insta fixed this in their latest update and it works consistently!
PackageManager
Thanks for your reply. I can confirm it works on the latest version of Instagram. But I didn't get how can I check the installed Instagram version from my react native app.
Yes its working with current IG version, but not with the sticker unfourtunetly, the image is loaded , but not the sticker
Yes its working with current IG version, but not with the sticker unfourtunetly, the image is loaded , but not the sticker
It is working for me for Share.InstagramStories.SHARE_STICKER_IMAGE
method. However, I didn't check if the others were also fixed by the Instagram update.
PackageManager
Thanks for your reply. I can confirm it works on the latest version of Instagram. But I didn't get how can I check the installed Instagram version from my react native app.
I didn't find a way to check the version of installed apps on Android from React Native side and implemented a method for myself in a native module.
Snippet from own InstagramShare
native module on Android side:
private const val INSTAGRAM_VERSION_SHARE_FIXED = "182.0.0.29.124"
@ReactMethod
fun isSharingToInstagramFixed(promise: Promise) {
val packageManager: PackageManager = context.packageManager
try {
val packageInfo: PackageInfo = packageManager.getPackageInfo("com.instagram.android", 0)
val version: String = packageInfo.versionName
if (Version(version).isAtLeast(INSTAGRAM_VERSION_SHARE_FIXED)) {
promise.resolve(true)
} else {
promise.resolve(false)
}
} catch (e: PackageManager.NameNotFoundException) {
promise.reject("-1001", "Instagram app not found.")
}
}
I took a library for proper version strings comparison here: https://github.com/G00fY2/version-compare
Snippet from own InstagramShare.js
on React Native side:
export const isSharingToInstagramFixed = async () => {
switch (Platform.OS) {
case 'ios':
return true;
case 'android':
return await InstagramShare.isSharingToInstagramFixed();
}
};
queries
tag in AndroidManifest.xml
for the PackageManager
usage on target API 30:
<queries>
<package android:name="com.instagram.android" />
</queries>
ps. on IOS it works fine, except that the promise from shareSingle won't return.
const res = await Share.shareSingle(shareOptions)
@mikehardy @MateusAndrade , is this a known issue or should I open a new issue here on github? Are there any workarounds?
Have you ever found if not resolving promise on iOS is intentional?
Anyone able to make it work for image from a URL as opposed to local file? Perhaps need to save as local file then share to Instagram to avoid permission error
Anyone able to make it work for image from a URL as opposed to local file? Perhaps need to save as local file then share to Instagram to avoid permission error
It's not possible. From the docs: "The Uri needs to be a content Uri to a local file on the device."
https://developers.facebook.com/docs/instagram/sharing-to-stories
Ok...so for those that may have not taken the most obvious step. I was using an emulator and installed Instagram but I never allowed device permissions WITHIN the Instagram app to access photos etc. So every time I was trying to generate an instagram story, the app would flash open for a second and then immediately close. After opening instagram, accepting THEIR permissions, and trying to generate a story. It worked.
Wasted a whole day on this.
So I hope this at least helps someone else :')
Anyone who cannot share a video to instagram , tries to put type
in share options
await Share.shareSingle({ social: Share.Social.INSTAGRAM, url: url, forceDialog: true, type: "video/mp4", })
Steps to reproduce
I tried to run the next code:
As a result I see next:
Expected behavior
Instagram story sharing should work properly
Actual behavior
After invoking
.shareSingle(...)
will be opened a new activity and very quickly closed and a result{ message: true, app: 'com.instagram.android' }
Instagram didn't openAlso, I tried to use example/App.js and the same problem:
{ message: true, app: 'com.instagram.android' }
Environment
react-native-share
Version: 3.5.0
Link to repo (highly encouraged)
https://github.com/