react native network lost check - react-native

how to check react-native network lost connection? I tried the below code and its throwing an error. I want to display and alert when app lost it's network connection?
CheckConnectivity = () => {
// For Android devices
if (Platform.OS === "android") {
NetInfo.isConnected.fetch().then(isConnected => {
console.log(isConnected,">>>")
if (isConnected) {
Alert.alert("You are online!");
} else {
Alert.alert("You are offline!");
}
});
} else {
// For iOS devices
NetInfo.isConnected.addEventListener(
"connectionChange",
this.handleFirstConnectivityChange
);
}
};
handleFirstConnectivityChange = isConnected => {
NetInfo.isConnected.removeEventListener(
"connectionChange",
this.handleFirstConnectivityChange
);
if (isConnected === false) {
Alert.alert("You are offline!");
} else {
Alert.alert("You are online!");
}
};

It looks like you are using the wrong API. For example, this is for WEB
NetInfo.isConnected.removeEventListener
If you check it here: https://github.com/react-native-netinfo/react-native-netinfo/blob/ba5c22cf2045b690243984a548ee25f4f6371e4a/src/internal/nativeModule.web.ts#L59
You need to follow this examples:
https://github.com/react-native-netinfo/react-native-netinfo/blob/master/example/IsConnected.tsx
https://github.com/react-native-netinfo/react-native-netinfo/blob/master/example/ConnectionInfoSubscription.tsx

Related

AppLink.fetchDeferredAppLink() always returns null in android and undefined in iOS

🐛 Bug Report
AppLink.fetchDeferredAppLink() always returns null in android and undefined in iOS.
To Reproduce
I use https://developers.facebook.com/tools/app-ads-helper to test the deep-link. Here i enter the uri-scheme of the app and checked both Send Notification & Send Deferred.
It shows two popup,
If i click on the notification which i received on the developer facebook account, it is opening the installed app, but the method AppLink.fetchDeferredAppLink() always returns null/undefined.
I tried uninstaling the app, then clicked on the deferred link, then installed and opened the app, still same.
Code Example
const fbsdkInit = (bool) => {
if (bool) {
Settings.setAdvertiserTrackingEnabled(bool).then(() => {
Settings.initializeSDK();
AppLink.fetchDeferredAppLink().then((link) =>
console.log("Link 1", link)
);
});
} else {
Settings.initializeSDK();
AppLink.fetchDeferredAppLink().then((link) => console.log("Link 2", link));
}
};
async function getATTPermissionForFbAppEvents() {
const ATT_CHECK = await check(PERMISSIONS.IOS.APP_TRACKING_TRANSPARENCY);
if (ATT_CHECK === RESULTS.DENIED) {
try {
const ATT = await request(PERMISSIONS.IOS.APP_TRACKING_TRANSPARENCY);
if (ATT === RESULTS.DENIED) {
getATTPermissionForFbAppEvents();
} else {
if (ATT === RESULTS.GRANTED) {
fbsdkInit(true);
} else {
fbsdkInit(false);
}
}
} catch (error) {
fbsdkInit(false);
}
} else if (ATT_CHECK === RESULTS.GRANTED) {
fbsdkInit(true);
} else {
fbsdkInit(false);
}
}
componentDidMount() {
if (Platform.OS === "ios" && Number(Platform.Version) > 14.4) {
getATTPermissionForFbAppEvents();
} else {
fbsdkInit(true);
}
}

Clear the app data if disconnected from internet for more then 5min in react native

I want to clear the react native app data if my app is disconnected from internet for more than 5 min.
I am using react native NetInfo to check network connectivity status.
Saving the time when app disconnected and checking when it will reconnect to internet.
If interval is more than 5 min then I want to clear the app data.
My Code is:
class OfflineMessage extends PureComponent {
constructor(props) {
super(props);
this.state = {
isConnected: true
};
}
componentDidMount() {
NetInfo.addEventListener((state) => {
this.handleConnection(state.isConnected);
});
}
componentWillUnmount() {
NetInfo.removeEventListener((state) => {
this.handleConnection(state.isConnected);
});
}
handleConnection = (isConnected) => {
this.setState({ isConnected });
if(!isConnected){
this.startTimer();
} else {
this.checkElapsed();
}
};
startTimer = async () => {
try {
console.log('Internet disconnected at: ');
await AsyncStorage.setItem('time', JSON.stringify(Date.now()));
} catch (error) {
// console.log('Something went wrong', error);
}
}
checkElapsed = async () => {
try {
let startTime = await AsyncStorage.getItem('time');
if(startTime){
let endTime = Date.now();
const elapsedTime = Math.floor((endTime -JSON.parse(startTime))/1000);
if(elapsedTime > 5){
alert("5 min is completed.");
// Clear app data
}
console.log('Time elapsed'+ elapsedTime);
}
} catch (error) {
// console.log('Something went wrong', error);
}
}
Problem:
Both the methods startTimer and checkElapsed called whenever connectivity status changes.
What is wrong with this code.
if I modify given code as :
state = {
isConnected: true
};
componentDidMount() {
this.unsubscribeFromNetInfo = NetInfo.addEventListener((state) => {
this.handleConnection(state.isConnected);
});
}
componentWillUnmount() {
this.unsubscribeFromNetInfo();
}
handleConnection = (isConnected) => {
console.log(isConnected);
this.setState({ isConnected });
};
EventListener called multiple times and status changes frequently true false,true,false .
Now, you are handling the NetInfo subscription wrong, according to https://github.com/react-native-community/react-native-netinfo#usage
You would have to do:
componentDidMount() {
this.unsubscribeFromNetInfo = NetInfo.addEventListener(state => {
this.handleConnection(state.isConnected);
});
}
componentWillUnmount() {
this.unsubscribeFromNetInfo();
}
Also, if you want to check for 5 minutes use:
if (elapsedTime > 5 * 60)
as your conversion
Math.floor((endTime - JSON.parse(startTime)) / 1000)
converts it to seconds not minutes.
In the current state, your app will trigger almost everything as the code only checks for 5 seconds.
Otherwise, the logic that you implemented itself should be working :)

React Native Linking Promise resolved reject not getting called

I am using react native linking component for opening call application.call suggestion dialog get opened but when I click on cancel it does not return me any promise
static makePhoneCall = (mobileNumber) =>
{
let phoneNumber = '';
if (Platform.OS === 'android') {
let userMobile = `tel:${mobileNumber}`
phoneNumber = userMobile;
}
else {
let userMobile = `tel://${mobileNumber}`
phoneNumber = userMobile;
}
Linking.openURL(phoneNumber).then(() => {
alert('success')
}).catch(() => {
alert('failure')
});
return 'default`
}
classname.makePhoneCall(this.state.item.mobileNumber)
I want to know how to handle openUrl Promise with some example, I have share code of what I have done. I am using react native version 0.59.9
You should check to see if theres an app available to handle the url first.
Linking.canOpenURL(phoneNumber)
.then((supported) => {
if (!supported) {
console.log("Can't handle url: " + url);
} else {
return Linking.openURL(url);
}
})
.catch((err) => console.error('An error occurred', err));

How to check the internet reachability in React-native?

I've tried #react-native-community/netinfo to check the internet reachability. But the scenario I want to implement is, suppose if my device is connected to a wifi hotspot from another device and if that device's mobile data is turned off I want to show an offline toast.
componentDidMount() {
NetInfo.addEventListener(status => {
this.props.checkOnlineStatus(
status.isConnected,
status.isInternetReachable
);
this.setState({
isConnected: status.isConnected,
isInternetReachable: status.isInternetReachable
});
});
}
render() {
if (!this.state.isInternetReachable && this.props.isOfflineNoticeVisible) {
return <MiniOfflineSign />;
}
return null;
}
But in this case, when the mobile data of the other device is turned off, it doesn't handle the change.
The non-deprecated way (using functional components) with the #react-native-community/netinfo package is now:
import React, { useEffect } from "react";
import NetInfo from "#react-native-community/netinfo";
useEffect(() => {
return NetInfo.addEventListener(state => {
// use state.isInternetReachable or some other field
// I used a useState hook to store the result for use elsewhere
});
}, []);
This will run the callback whenever the state changes, and unsubscribe when the component unmounts.
These connection types could help: https://github.com/react-native-community/react-native-netinfo#netinfostatetype
Otherwise:
Then to be sure, you are online just implement a fetch with timeout:
export default function(url, options, timeout = 5000) {
return Promise.race([
fetch(url, options),
new Promise((_, reject) => setTimeout(() => reject("timeout"), timeout)),
]);
}
Then use it like this:
fetchWithTimeout(url, options)
.then(resp => {
if (resp.status === 200) {
let json = resp.json().then(j => {
return j;
});
})
.catch(ex => {
// HANDLE offline usage
if (ex === "timeout") return true;
//ANY OTHER CASE RETURN FALSE
return false;
}
async function InternetCheck() {
const connectionInfo = await NetInfo.getConnectionInfo();
if (connectionInfo.type === 'none') {
alert('PLEASE CONNECT TO INTERNET');
} else {
//navigate to page or Call API
}
}

'Attempt to invoke virtual method \'android.content.Context android.app.Application.getApplicationContext()\' on a null object reference'

I'm using https://github.com/AppsFlyerSDK/react-native-appsflyer in our react-native app.
I managed to set up the iOS part of it and ran the integration tests successfully
but I'm struggling with the Android integration.
1st problem:
When I build the app on my device I get this error:
'Attempt to invoke virtual method \'android.content.Context android.app.Application.getApplicationContext()\' on a null object reference'
inside the appsFlyer.initSdk
2nd problem:
When I run the Android SDK Integration test:
I get this result (see screenshot)
Here's my code :
```
...
...
// appsFlyer options
const options = {
devKey: 'Bl9i45ho07lp43',
isDebug: true,
};
if (Platform.OS === 'ios') {
options.appId = '1165972436';
}
this.onInstallConversionDataCanceller = appsFlyer.onInstallConversionData(
(data) => {
console.log(data);
}
);
appsFlyer.initSdk(options,
(result) => {
console.log(result);
},
(error) => {
console.error('error inside appsFlyer.initSdk ==>', error);
}
);
.....
.....
class App extends React.PureComponent {
state = {
appState: AppState.currentState,
}
componentDidMount() {
AppState.addEventListener('change', this._handleAppStateChange);
}
componentWillUnmount() {
if (this.onInstallConversionDataCanceller) {
this.onInstallConversionDataCanceller();
}
AppState.removeEventListener('change', this._handleAppStateChange);
}
_handleAppStateChange = (nextAppState) => {
if (this.state.appState.match(/inactive|background/) && nextAppState === 'active') {
if (Platform.OS === 'ios') {
appsFlyer.trackAppLaunch();
}
}
if (this.state.appState.match(/active|foreground/) && nextAppState === 'background') {
if (this.onInstallConversionDataCanceller) {
this.onInstallConversionDataCanceller();
}
}
this.setState({ appState: nextAppState });
}
}
```
I found the solution:
Initially, I was following the documentation by adding
new RNAppsFlyerPackage(MainApplication.this) inside the getPackages() method in MainApplication.java but I kept having an error saying I couldn't use arguments with RNAppsFlyerPackage()
I had to remove the arguments so that I can build the project, but that didn't make the Android integration tests
1 - The solution was to clean the project
2 - delete the node_modules using :
rm -rf /node_modules
3- after doing that, I was prompted to use arguments inside the method
new RNAppsFlyerPackage(MainApplication.this)
and now the Android integration tests are passing