'On React-native, on Android, canOpenURL fails & OpenURL throw an error: Could not open URL

On a React-Native mobile app Linking.canOpenURL and Linking.openURL fail if the URL refers to an app screen, while it works when referring to an HTTPS URL. I suspect it is a problem with Android permissions. I have not tried it on iOS. Any idea what I am missing?

My Code:

// const url = "https://google.com"; // works 
const url = "casualjob://"; // does NOT work 

Linking.canOpenURL(url)
.then( (supported) => {
    // execution reaches this point -> supported: false 
    console.log("canOpenURL - ", "supported:", supported, ); 
});

Linking.openURL(url) 
    .then(() => { 
        console.log("openURL -URL was opened successfully");
    })
    .catch((err) => {
        // execution reaches this point -> Error: Could not open URL 'casualjob://': No Activity found to handle Intent { act=android.intent.action.VIEW dat=casualjob:// flg=0x10000000 
        console.error("openURL - failed - err:", err, ) 
    }); 

AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.casualjob">
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.READ_CONTACTS" />
    <uses-permission android:name="android.permission.READ_PROFILE" />
    <uses-permission android:name="android.permission.READ_SMS" />
    <uses-permission android:name="android.permission.WRITE_SMS" />
    <uses-permission android:name="android.permission.SEND_SMS" />
    <uses-permission android:name="android.permission.CAMERA"/>
    <uses-feature android:name="android.hardware.camera" android:required="false" />
    <uses-feature android:name="android.hardware.camera.front" android:required="false" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

    <application 
      android:name=".MainApplication" android:label="@string/app_name" android:icon="@mipmap/ic_launcher" 
      android:roundIcon="@mipmap/ic_launcher_round" android:allowBackup="false" android:theme="@style/AppTheme" 
      android:requestLegacyExternalStorage="true" 
  >
        <meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/facebook_app_id"/>
        <meta-data android:name="com.facebook.sdk.ClientToken" android:value="@string/facebook_client_token"/>

        <activity 
            android:name=".MainActivity" 
            android:label="@string/app_name" 
            android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode" 
            android:launchMode="singleTask" 
            android:windowSoftInputMode="adjustResize" 
        >
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>

            <intent-filter>
                <action android:name="android.intent.action.VIEW"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <category android:name="android.intent.category.BROWSABLE"/>
                <data android:scheme="casualjob"/>
                
                <data android:scheme="http"  android:host="buildwebsitepro.com.au/casualjob"/>
                <data android:scheme="https" android:host="buildwebsitepro.com.au/casualjob"/>
            </intent-filter>
        </activity>
    </application>

   <queries>
      <intent>
         <action android:name="android.intent.action.VIEW" />
            <data android:scheme="casualjob"/>
      </intent>
   </queries>
</manifest>


Solution 1:[1]

For Deeplink integration refer this plugin react-native-deep-linking

Your URL should be like this

const url = "https://buildwebsitepro.com.au" 

after that you need to first initialise event for Dee-link For Android

Linking.getInitialURL()
    .then(ev => {
      if (ev && ev !== '') {
        handleUrl({url: ev});
      }
    })
    .catch(err => console.log('An error occurred', err));

  function handleUrl({url}: {url: string | null}) {
  const deepLinkURL = url;
  if (deepLinkURL) {
   Linking.canOpenURL(deepLinkURL).then(supported => {
     if (supported) {
       DeepLinking.evaluateUrl(deepLinkURL);
     }
   });
 }

}

You need to change MenifestFile like below

    <data android:host="casualjob" android:scheme="buildwebsitepro" />

Finally Register Routes

DeepLinking.addRoute('/test/:id', (response) => {
 // example://test/23
 console.log(response.id); // 23
});

Solution 2:[2]

I discovered that the problem was a conflict between the <data> definitions. Following is an extract showing the required modifications.

AndroidManifest.xml:

<manifest ...>
...

    <application ...>
...
        <activity ...>
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>

            <intent-filter>
                <action android:name="android.intent.action.VIEW"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <category android:name="android.intent.category.BROWSABLE"/>
                <data android:scheme="casualjob"/>
                
                <!-- It seems that the following 2 data statements are conflicting with the one above. So, I removed them. --> 
                <!-- <data android:scheme="http"  android:host="buildwebsitepro.com.au/casualjob"/>
                <data android:scheme="https" android:host="buildwebsitepro.com.au/casualjob"/> --> 
            </intent-filter>
        </activity>
    </application>
</manifest>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Mobile Team iOS-RN
Solution 2 Bilal Abdeen