I tried to add a EXPO iOS StoreReview API but failed.
have any sample code?
import * as StoreReview from 'expo-store-review';
...
export default SettingPage() {
handleReview = () => {
if (StoreReview.isSupported()) {
StoreReview.requestReview();
}
};
render (
...
<TouchableOpacity onPress={handleReview}>
<Text>Click Review</Text>
</TouchableOpacity>
);
}
add ios-appStoreUrl android-playStoreUrl fields in app.json
Related
What is the best way of implementing the Apple App Transparency Tracker (ATT) feature on react native expo? My app keeps getting rejected by apple even after I add:
app.json file :
"infoPlist": {
"NSUserTrackingUsageDescription": "App requires permission...."
}
On iOS 14 Apple introduced the App Tracking Transparency permission to access IDFA.
You need to prompt the user whether it allows your app to use libraries that track them or not, adding it on infoPlist just allows you to use this API within your application.
Expo doesn't have this feature yet, but some libraries you can use to prompt the permission
Example: https://docs.expo.io/versions/v41.0.0/sdk/facebook/#facebookgetpermissionsasync
You can use other libraries , such as https://github.com/mrousavy/react-native-tracking-transparency
where you can request the App tracking like
import { getTrackingStatus } from 'react-native-tracking-transparency';
const trackingStatus = await getTrackingStatus();
if (trackingStatus === 'authorized' || trackingStatus === 'unavailable') {
// enable tracking features
}
import { requestTrackingPermission } from 'react-native-tracking-transparency';
const trackingStatus = await requestTrackingPermission();
if (trackingStatus === 'authorized' || trackingStatus === 'unavailable') {
// enable tracking features
}
This might need an update in a near future, as expo releases a new SDK version with a solution for that.
EDIT
From Expo 44+
Expo now have a library for TrackTransparency: (https://docs.expo.dev/versions/latest/sdk/tracking-transparency/)
expo install expo-tracking-transparency
For bare applications: https://github.com/expo/expo/tree/main/packages/expo-tracking-transparency#installation-in-bare-react-native-projects
You can add it as a plugin at your app.json
{
"expo": {
"plugins": [
[
"expo-tracking-transparency",
{
"userTrackingPermission": "This identifier will be used to deliver personalized ads to you."
}
]
]
}
}
And now you can use like this:
import React, { useEffect } from 'react';
import { Text, StyleSheet, View } from 'react-native';
import { requestTrackingPermissionsAsync } from 'expo-tracking-transparency';
export default function App() {
useEffect(() => {
(async () => {
const { status } = await requestTrackingPermissionsAsync();
if (status === 'granted') {
console.log('Yay! I have user permission to track data');
}
})();
}, []);
return (
<View style={styles.container}>
<Text>Tracking Transparency Module Example</Text>
</View>
);
}
You need to request Tracking permissions first (I used react-native-permissions):
import { request, RESULTS, PERMISSIONS } from 'react-native-permissions'
export const requestPermissionTransparency = async () => {
return await request(PERMISSIONS.IOS.APP_TRACKING_TRANSPARENCY)
}
useEffect(() => {
;(async () => {
const result = await requestPermissionTransparency()
if (result === RESULTS.GRANTED) {
//You need to enable analytics (fb,google,etc...)
await firebase.analytics().setAnalyticsCollectionEnabled(true)
console.log('Firebase Analytics: ENABLED')
}
})()
}, [])
Remember to add this file in the root project:
// <project-root>/firebase.json
{
"react-native": {
"analytics_auto_collection_enabled": false
}
}
References: https://rnfirebase.io/analytics/usage
The solution I ended up using from expo was using the Facebook.getPermissionsAsync()
https://expo.canny.io/feature-requests/p/expo-permissions-add-support-to-apptrackingtransparency-permission-on-ios
Expo 41+
TrackingTransparency:
https://docs.expo.io/versions/latest/sdk/tracking-transparency/
import { requestTrackingPermissionsAsync } from 'expo-tracking-transparency';
const { status } = await requestTrackingPermissionsAsync();
if (status === 'granted') // do something
Expo 40 and below
Admob: https://docs.expo.io/versions/latest/sdk/admob/
import { requestPermissionsAsync } from 'expo-ads-admob'
const { status } = await requestPermissionsAsync()
if (status === 'granted') // do something
My react native app was working just fine before I used expo eject. I ejected it because I now intend to build and release the app to the ios app store. As soon as I attempt to start the ejected app using react-native run-ios after it's been ejected I get the exception below.
Please could someone help to understand what's causing this issue and how to tackle it?
react Native versions as follows:
react-native-cli: 2.0.1
react-native: 0.61.5
TypeError: null is not an object (evaluating 'SplashScreen.preventAutoHide')
This error is located at:
in AppLoading (at AppLoading.js:52)
in AppLoading (at App.js:464)
in App (at renderApplication.js:40)
in RCTView (at AppContainer.js:101)
in RCTView (at AppContainer.js:119)
in AppContainer (at renderApplication.js:39)
preventAutoHide
SplashScreen.js:4:21
AppLoading#constructor
AppLoadingNativeWrapper.js:6:8
renderRoot
[native code]:0
runRootCallback
[native code]:0
renderApplication
renderApplication.js:52:52
runnables.appKey.run
AppRegistry.js:116:10
runApplication
AppRegistry.js:197:26
callFunctionReturnFlushedQueue
[native code]:0
The AppLoading component is not available in the bare workflow. As #gaurav-roy said you have to refactor your code.
Install the expo-splash-screen package with npm install expo-splash-screen
Add a splash-screen to your Android and iOS projects. Run npm run expo-splash-screen --help and follow the instructions of this CLI tool. (Because of a bug you might have to run the command again with the -p "ios" flag if it only adds the SplashScreen for Android after running it.
Change your code inside App.tsx in a similar way as in this example.
If you're working with hooks you probably want to add an useEffect
hook with an empty dependency list which runs an async function. Here an example of how it could be done:
const App = (props: Props) => {
const [isLoadingComplete, setLoadingComplete] = useState(false);
const init = async () => {
try {
// Keep on showing the SlashScreen
await SplashScreen.preventAutoHideAsync();
await loadResourcesAsync();
} catch (e) {
console.warn(e);
} finally {
setLoadingComplete(true);
// Hiding the SplashScreen
await SplashScreen.hideAsync();
}
useEffect(() => {
init();
}, []);
const renderApp = () => {
if (!isLoadingComplete && !props.skipLoadingScreen) {
return null;
}
return (
<Main />
);
};
return <StoreProvider>{renderApp()}</StoreProvider>;
}
As its evident from docs , SplashScreen is an inbuilt api for expo apps, and since you ejected it , it throws an error since it cant be used.
You can see this in the docs expo splashscreen .
First you should download npm i expo-splash-screen
And then change your import statement to :
import * as SplashScreen from 'expo-splash-screen';
Hope it helps. feel free for doubts
After looking through this SO page and then digging into some links, especially this expo page where they kind of provide a solution for this, I was able to get my app running after about 3 hours of struggle. They haven't added any functional component example, so I am sharing my code below in case someone came here looking for the solution.
import { Asset } from "expo-asset";
import * as Font from "expo-font";
import React, { useState, useEffect } from "react";
import { Platform, StatusBar, StyleSheet, View } from "react-native";
import { Ionicons } from "#expo/vector-icons";
import * as SplashScreen from 'expo-splash-screen';
import AppNavigator from "./navigation/AppNavigator";
export default props => {
const [isLoadingComplete, setLoadingComplete] = useState(false);
const theme = {
...DefaultTheme,
roundness: 2,
colors: {
...DefaultTheme.colors,
primary: "#E4002B",
accent: "#E4002B",
},
};
useEffect(() => {
async function asyncTasks() {
try {
await SplashScreen.preventAutoHideAsync();
} catch (e) {
console.warn(e);
}
await loadResourcesAsync()
setLoadingComplete(true);
}
asyncTasks()
}, []);
return (
!isLoadingComplete && !props.skipLoadingScreen ? null :
<View style={styles.container}>
{Platform.OS === "ios" && <StatusBar barStyle="default" />}
<AppNavigator />
</View>
);
}
async function loadResourcesAsync() {
await Promise.all([
Asset.loadAsync([
require("./assets/images/logo.png") // Load your resources here (if any)
]),
Font.loadAsync({
// You can remove this if you are not loading any fonts
"space-mono": require("./assets/fonts/SpaceMono-Regular.ttf"),
}),
]);
await SplashScreen.hideAsync();
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
},
});
This solved it for me for an ejected expo app. Looks like expo was referencing it wrongly.
https://github.com/expo/expo/issues/7718#issuecomment-610508510
What worked for me was updating node_modules/expo/build/launch/splashScreen.js to the following as suggested by adamsolomon1986 in the repo (issue #7718):
import { NativeModules } from 'react-native';
import* as SplashScreen from 'expo-splash-screen'
export function preventAutoHide() {
if (SplashScreen.preventAutoHide) {
SplashScreen.preventAutoHide();
}
}
export function hide() {
if (SplashScreen.hide) {
SplashScreen.hide();
}
}
//# sourceMappingURL=SplashScreen.js.map
I'm working on a React Native app, from Expo. I ejected the project to ExpoKit and added react-native-wkwebview-reborn. I'm facing some issues with this library as always appear this error:
Here is my code:
ContentWebView.ios.js
render() {
return (
<View style={styles.container}>
<WKWebView
ref={WEBVIEW_REF}
sendCookies={true}
style={styles.webview}
source={{uri: this.props.url}}
allowsLinkPreview={false}
onMessage={(e) => this._handleMessage(e)}
onNavigationStateChange={(e) => this._onNavigationStateChange(e)}
/>
and here is where my app crashes :
_onNavigationStateChange(e) {
this.refs[WEBVIEW_REF].evaluateJavaScript('window.postMessage({cookies: document.cookie}); clearInterval(window.myCartInterval); window.myCartInterval = setInterval(function(){window.postMessage({cookies: document.cookie});},5000);');
}
If you have any idea it would be so useful! Thanks
can you try change code??
Try it this way.
<WKWebView
ref={WEBVIEW_REF => {this.webview = WEBVIEW_REF;}}
sendCookies={true}
style={styles.webview}
source={{uri: this.props.url}}
allowsLinkPreview={false}
onMessage={(e) => this._handleMessage(e)}
onNavigationStateChange={(e) => this._onNavigationStateChange(e)}
/>
...
_onNavigationStateChange(e) {
this.webview.evaluateJavaScript('window.postMessage(e)');
}
The function is named injectJavaScript in React Native
I am trying to access iOS' share button where you can share content to all services, including messages etc...
Any idea how I could do this? Thanks
You now have a simple Share API in react-native.
import { Share } from "react-native"
Share.share(
{
title: "a title",
message: "some message",
// or
url: imageReference
},
(options)
);
See http://facebook.github.io/react-native/docs/share.html
You can achieve this out of the box in React Native - just use ActionSheetIOS.showShareActionSheetWithOptions. See the documentation here.
You might want to check out the react-native-share package, it should cover your usecase. You can also see more relevant packages on JS.Coach
It's much easier than you think. Adding to #MoOx answer further.
With the new share api available, you can easily share information with your React Native app by just using it with all variables and configuration. (see here)
import React from 'react';
import { Share, View, Button } from 'react-native';
const ShareExample = () => {
const onShare = async () => {
try {
const result = await Share.share({
message:
'React Native | A framework for building native apps using React',
});
if (result.action === Share.sharedAction) {
if (result.activityType) {
// shared with activity type of result.activityType
} else {
// shared
}
} else if (result.action === Share.dismissedAction) {
// dismissed
}
} catch (error) {
alert(error.message);
}
};
return (
<View style={{ marginTop: 50 }}>
<Button onPress={onShare} title="Share" />
</View>
);
};
export default ShareExample;
Trying to configure facebook connect in my app. newbie to xcode.
I should mention that i am using React-native.
I checked the configs 10 times
still getting this error:
Exception thrown while invoking newSession on target <FacebookLoginManager: 0x7c2579d0> with params (
5
): fb1413783292275789 is not registered as a URL scheme. Please add it in your Info.plist
React-native code :
var FacebookLoginManager = require('NativeModules').FacebookLoginManager;
login() {
FacebookLoginManager.newSession((error, info) => {
if (error) {
this.setState({result: error});
} else {
this.setState({result: info});
}
});
}
render() {
return (
<View style={styles.container}>
<TouchableHighlight onPress={this.login}>
<Text style={styles.welcome}>
Facebook Login
</Text>
</TouchableHighlight>
<Text style={styles.instructions}>
{this.state.result}
</Text>
</View>
);
}
I think the solution is
Replace URL types -> CFBundleURLTypes, URL Schemes -> CFBundleURLSchemes
even though it changes back automatically.
hit the play button and that’s it