Reputation: 4388
I am trying to implement deeplinking in my react native Android application. Link is sent through and SMS and when the link is clicked it opens the app and based on the url I am navigating to a perticular screen using android:launchMode="singleTop"
. The issue I was facing is when the link is clicked, a new instance of the app is opened and I did not want that so I changed to
android:launchMode="singleTask"
to my activity
in AndroidManifest.xml
and now there is only one instance.
But now when the link from the SMS is clicked it resumes the existing page and I cannot get the url clicked.
I implemented 'AppState' to know when a screen is resumed but that does not give me the url too.
What I want to be able to achieve is either
Splash activity
and I know I can get the URL and navigate from there on based on the URL. (android:launchMode="singleTop"
does not restart the app but opens a new instance)Manifest
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.abcdabcdapp">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<application
android:name=".MainApplication"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:allowBackup="false"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:launchMode="singleTop"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
//This is what is required to open from the link
<intent-filter android:label="ABCD App">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="http"
android:host="abcd"
android:pathPrefix="/createpassword" />
</intent-filter>
</activity>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
</application>
</manifest>
Link that is sent through as SMS - http://abcd/createpassword
Splash screen - Initial screen.
componentDidMount() {
setTimeout(() => {
this.whereShoulINavigateTo();
}, 2500);
}
whereShoulINavigateTo = async () => {
if (Platform.OS === 'android') {
Linking.getInitialURL().then( async (url) => {
//this.navigate(url);
if(url === 'http://abcd/createpassword')
{
this.props.navigation.navigate('CreatePasswordScreen');
}else{
//do something
}
});
} else {
alert('ios url -' + url );
//Linking.addEventListener('url', this.handleOpenURL);
}
}
Above setup works fine with android:launchMode="singleTop"
but only issue is I donot want a new instance of the app.
So I tried the following changes
Manifest
android:launchMode="singleTask"
With this there is only one instance and when the URL is clicked, app resumes.
So I added AppState to the page which resumes and tried to get the URL but that did not work.
componentDidMount(){
//this.whereShoulINavigateTo();
AppState.addEventListener('change', this._handleAppStateChange);
}
componentWillUnmount() {
AppState.removeEventListener('change', this._handleAppStateChange);
}
_handleAppStateChange = (nextAppState) => {
if (this.state.appState.match(/inactive|background/) && nextAppState === 'active') {
console.log('App has come to the foreground!')
this.whereShoulINavigateTo();
}
this.setState({appState: nextAppState});
}
whereShoulINavigateTo = async () => {
if (Platform.OS === 'android') {
Linking.getInitialURL().then( async (url) => {
alert('url - ' + url)
if(url === 'http://abcd/createpassword')
{
this.props.navigation.navigate('CreatePasswordScreen');
}
});
} else {
alert('ios url -' + url );
//Linking.addEventListener('url', this.handleOpenURL);
}
}
Please suggest.
Thanks R
Upvotes: 0
Views: 2476
Reputation: 43
Delete the /android folder and expo
run "expo prebuild" command and build it.
Upvotes: 0
Reputation: 4388
Here is the solution that works for me.
launch mode I have set it to singleTask
Manifest.xml
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:launchMode="singleTask"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:windowSoftInputMode="adjustResize">
The initial screen that opens in my app is Splash screen. Lets say you received the SMS and your app is closed we will reopen the app so it will always open the initial screen in my case splash screen.
Here is my splash screen code.
componentDidMount() {
setTimeout(() => {
this.whereShoulINavigateTo();
}, 2500);
}
whereShoulINavigateTo = async () => {
encryptString('abcd');
decryptString('abcd');
if (Platform.OS === 'android') {
Linking.getInitialURL().then( async (url) => {
if(url === 'http://abcd/1234')
{
//if the url is right do something
}else{
}
});
} else {
alert('ios url -' + url );
//Linking.addEventListener('url', this.handleOpenURL);
//Not implemented for iOS yet
}
}
And on the other screens when the app is open and a message is received. you click on the link and it open the same screen. So following logic is required on that screen.
componentDidMount(){
Linking.addEventListener('url', this.handleOpenURL);
}
componentWillUnmount() {
Linking.removeEventListener('url', this.handleOpenURL);
}
handleOpenURL = async (event) => {
consoleLog('url - ' + event.url);
if(event.url === 'http://abcd/1234')
{
//if the url is right do something
}
}
Hope it helps.
let me know if you need any further info
Thanks R
Upvotes: 3