React Native Deep Linking Android - android

I am making an App that allows user to login with Instagram. Now the login procedure that I've understood is as follows:
Register the App at Instagram Developer as a client to acquire client_id etc.
Call the Instagram URL along with your client_id with get the grant_code
Send the grant_code back to Instagram (I'm going to do this from back-end) to get the access token.
This StackOverFlow Question has the same problem I do. I understand from the answer that I need deep linking so that I can provide it as a redirect_uri to Instagram so that It redirects back to my app after login.
Now I can't get the Deep Linking to work. Below is the component where the app is listening for the URL.
Top Most Component in The App
import React, { Component } from 'react';
import { Linking } from 'react-native';
import Router from './Router';
class App extends Component {
componentDidMount() {
Linking.getInitialURL().then(url => {
if (url) {
console.log(`Initial url is ${url}`);
}
})
.catch(err => {
console.error(err);
});
Linking.addEventListener('url', this.handleOpenURL);
}
componentWillUnmount() {
Linking.removeEventListener('url', this.handleOpenURL);
}
handleOpenURL(event) {
console.log(event.url);
}
render() {
return <Router />;
}
}
export default App;
Android Manifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.numu"
android:versionCode="1"
android:versionName="1.0">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="22" />
<application
android:name=".MainApplication"
android:allowBackup="true"
android:label="#string/app_name"
android:icon="#mipmap/ic_launcher"
android:theme="#style/AppTheme">
<activity
android:name=".MainActivity"
android:label="#string/app_name"
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>
<intent-filter android:label="filter_react_native">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- Accepts URIs that begin with "http://www.numu.com/app” -->
<data android:scheme="http"
android:host="www.numu.com"
android:pathPrefix="/app" />
<!-- Accepts URIs that begin with "numu://app” -->
<data android:scheme="numu"
android:host="app" />
</intent-filter>
</activity>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
</application>
This is my Router Component
import { StackNavigator } from 'react-navigation';
import LoginPage from './components/LoginPage';
import IntroText from './components/IntroText';
const RouterComponent = StackNavigator({
LoginPage: { screen: LoginPage, path: 'login' },
IntroText: { screen: IntroText, path: 'intro },
});
export default RouterComponent;
This is my progress so far. I have been testing by entering http://www.numu.com/app/intro and numu://app/intro into my chrome browser (mobile), but the app doesn'r open.
I would also appreciate if anyone could tell me an alternative to this method. I have tried a package for this purpose. It also requires that I give a redirect_uri
Thanks

Related

Android app link opens webview in Outlook instead of my app

My app is a hybrid with a native login activity and a webview. In some cases you get a link in an email that navigates you to a certain screen inside the webview. This part works just fine, the webview opens and the user is taken to the correct adress.
When the link is clicked in outlook the whole app seems to open inside outlook and I can even reach my native login screen still inside outlook. It's like my webview is hijacked.
Is there something missing from my webview config?
AndroidManifest.xml:
`
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<application
android:allowBackup="true"
android:configChanges="orientation"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/Theme.Androidappshell"
android:usesCleartextTraffic="true">
<activity
android:name="package.name.LoginActivity"
android:exported="true"
android:theme="#style/Theme.App.SplashScreen">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="package.name.MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</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="https"
android:host="domain.com"
android:port="9201" />
</intent-filter>
</activity>
</application>
`
Webview setup:
#SuppressLint("SetJavaScriptEnabled")
private fun webViewSetUp(jsonData: String, url: String) {
wb_webView.webViewClient = object : WebViewClient() {
override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
super.onPageStarted(view, url, favicon)
wb_webView.evaluateJavascript(
"javascript:localStorage.setItem('clientMode', 'android')", null
)
}
override fun onPageFinished(view: WebView, url: String) {
wb_webView.evaluateJavascript("javascript:setUpAngular($jsonData)", null)
}
}
wb_webView.clearCache(false)
wb_webView.loadUrl(url)
wb_webView.settings.javaScriptEnabled = true
wb_webView.settings.domStorageEnabled = true
wb_webView.addJavascriptInterface(JsWebInterface(this, this), "androidApp")
}
The problem was that my activities were not marked as singleton instances adding: android:launchMode="singleInstance" to my activites.

react native android ask camera permission when user first logs in

I'm not familiar with the react-native app permissions for android and ios. I'm in thihs project which needs camera and audio permissions for videocalls that are already implemented and work fine.
The thing is that currently these permissions are asked the first time the users enters a videocall and that causes delay and bugs on the videocall flow. I'd like to aks these permissions the first time the users opens the app (they enter first to their profile or the dashboard, the videocall part happens afterwards), like I've seen other apps do.
This is the androidManifest.xml file that handles the permissions. I looked for a way to change when they're asked but I couldn't find anything on the format I'm currently at, and since it's new to me I don't want to change the behaviour completely by accident.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.rectnativetemplate">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<application
android:name=".MainApplication"
android:usesCleartextTraffic="true"
android:label="#string/app_name"
android:requestLegacyExternalStorage="true"
android:icon="#mipmap/ic_launcher"
android:roundIcon="#mipmap/ic_launcher_round"
android:allowBackup="false"
android:theme="#style/AppTheme">
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:launchMode="singleTask"
android:windowSoftInputMode="adjustPan">
<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:host="dev--b45llct.us.auth0.com"
android:pathPrefix="/android/${applicationId}/callback"
android:scheme="${applicationId}" />
</intent-filter>
</activity>
------------
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
</application>
</manifest>
Is there a way to ask the permissions when the user first enters the app? And if it's possible, how can I implement the same behaviour on IOS?
Use request from PermissionsAndroid.
const granted = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.CAMERA);
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
console.log('Camera permission granted');
} else {
console.log('Camera permission denied');
}

DeepLinking work but no navigate to Intended Screen using react navigation

I am on Android and I want to use DeepLink to open a specific screen using react navigation.
Here is my manifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.samtbook">
<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:supportsRtl="false"
android:usesCleartextTraffic="true"
>
<activity
android:launchMode="singleTask"
android:name=".MainActivity"
android:label="#string/app_name"
android:screenOrientation="portrait"
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>
<intent-filter android:autoVerify="true">
<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="samtbook.me"/>
</intent-filter>
</activity>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity"/>
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="API_KET"/> // HIDDEN
</application>
and here is the link I use:
http://samtbook.me/test/
and I registered my deepLink like this:
componentDidMount() {
Linking.addEventListener('url', this.handleOpenURL);
}
componentWillUnmount() {
Linking.removeEventListener('url', this.handleOpenURL);
}
handleOpenURL = (event) => {
this.navigate(event.url);
};
navigate = (url) => {
this.props.navigation.navigate('TestScreen');
};
The poblem is When the app is not running in the background(Means dead)
I click over the link and it opens the app but not navigate to intended screen
but when the app is running in background it navigates
Thanks in advance
Use react navigation deeplinking mentioned in doc:
https://reactnavigation.org/docs/en/deep-linking.html
Http scheme is detected as a web url just change your scheme to a custom scheme for example "myapp" and change your url to myapp://samtbook.me/test/ good luck!

React native Linking.getInitialUrl on Android called always

I've a React-Native app with the following code (here App.js, the app entry point) that manages deep link on Android.
Linking.getInitialURL().then((deepLinkUrl) => {
if (deepLinkUrl) {
manageDeepLink(deepLinkUrl);
} else {
Navigation.startSingleScreenApp('rootScreen');
}
});
The problem here is that getInitialURL is called every time I launch my app, from both deep link or normally, and everytime it contains deepLinkUrl parameter empty.
I've registered in AndroidManifest my intent as follows:
<application
android:name=".MainApplication"
android:allowBackup="true"
android:launchMode="singleTask"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme">
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:windowSoftInputMode="adjustResize">
<!-- deeplink -->
<intent-filter android:label="#string/app_name">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="myapp" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<action android:name="android.intent.action.DOWNLOAD_COMPLETE"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
UPDATE
I'm using react-native navigation to register screens, if this can e useful.
It seems it doesn't work if you register listener too soon in the app lifecycle (ex. directly in some .js file, so it's executed when app is loaded).
If you move it into componentDidMount() on the root component everything works fine.
componentDidMount() {
Linking.addEventListener('url', event => {
console.warn('URL', event.url)
})
Linking.getInitialURL().then(url => {
console.warn('INITIAL', url)
})
}
Because you added android:launchMode="singleTask" to AndroidManifest.xml. Please modify it to android:launchMode="singleTop", then your problem will be gone.

cannot receive any push notification on react native android app

I am following this documentation for receiving push notification on react native android https://github.com/evollu/react-native-fcm, I am able to receive the device token id, but I am not able to receive any notification when I am using sending manually from firebase using that device id:
This is the code on my react native app:
import {Platform} from 'react-native';
import FCM, {FCMEvent, RemoteNotificationResult, WillPresentNotificationResult, NotificationType} from 'react-native-fcm';
// this shall be called regardless of app state: running, background or not running. Won't be called when app is killed by user in iOS
FCM.on(FCMEvent.Notification, async (notif) => {
// there are two parts of notif. notif.notification contains the notification payload, notif.data contains data payload
if(notif.local_notification){
//this is a local notification
}
if(notif.opened_from_tray){
//iOS: app is open/resumed because user clicked banner
//Android: app is open/resumed because user clicked banner or tapped app icon
}
// await someAsyncCall();
if(Platform.OS ==='ios'){
//optional
//iOS requires developers to call completionHandler to end notification process. If you do not call it your background remote notifications could be throttled, to read more about it see https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623013-application.
//This library handles it for you automatically with default behavior (for remote notification, finish with NoData; for WillPresent, finish depend on "show_in_foreground"). However if you want to return different result, follow the following code to override
//notif._notificationType is available for iOS platfrom
switch(notif._notificationType){
case NotificationType.Remote:
notif.finish(RemoteNotificationResult.NewData) //other types available: RemoteNotificationResult.NewData, RemoteNotificationResult.ResultFailed
break;
case NotificationType.NotificationResponse:
notif.finish();
break;
case NotificationType.WillPresent:
notif.finish(WillPresentNotificationResult.All) //other types available: WillPresentNotificationResult.None
break;
}
}
});
FCM.on(FCMEvent.RefreshToken, (token) => {
console.log(token)
// fcm token may not be available on first load, catch it here
});
class App extends Component {
componentDidMount() {
// iOS: show permission prompt for the first call. later just check permission in user settings
// Android: check permission in user settings
FCM.requestPermissions().then(()=>console.log('granted')).catch(()=>console.log('notification permission rejected'));
FCM.getFCMToken().then(token => {
console.log(token)
// store fcm token in your server
});
this.notificationListener = FCM.on(FCMEvent.Notification, async (notif) => {
// optional, do some component related stuff
});
// initial notification contains the notification that launchs the app. If user launchs app by clicking banner, the banner notification info will be here rather than through FCM.on event
// sometimes Android kills activity when app goes to background, and when resume it broadcasts notification before JS is run. You can use FCM.getInitialNotification() to capture those missed events.
// initial notification will be triggered all the time even when open app by icon so send some action identifier when you send notification
FCM.getInitialNotification().then(notif => {
console.log(notif)
});
}
componentWillUnmount() {
// stop listening for events
this.notificationListener.remove();
}
Android Manifest file looks as below:
<?xml version="1.0" encoding="utf-8"?>
<manifest package="fi.rogerstudio.possis"
xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION"/>
<uses-permission android:name="com.example.healthgps.permission.MAPS_RECEIVE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-feature android:name="android.hardware.location.gps" />
<application
android:name=".MainApplication"
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true">
<activity android:name=".MainActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:theme="#style/Theme.Exponent.Light"
android:windowSoftInputMode="adjustResize"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<intent-filter>
<data android:scheme="exp6a747c4f7f604b89a93d9f3d281cbb77"/>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
</intent-filter>
</activity>
<service
android:name="io.invertase.firebase.messaging.MessagingService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<service android:name="io.invertase.firebase.messaging.InstanceIdService" android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>
<service android:name="com.evollu.react.fcm.MessagingService" android:enabled="true" android:exported="true">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
<service android:name="com.evollu.react.fcm.InstanceIdService" android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>
<!-- The Facebook SDK runs FacebookInitProvider on startup and crashes if there isn't an ID here -->
<meta-data android:name="com.facebook.sdk.ApplicationId" android:value="fb0"/>
<!-- react-native-background-geolocation licence -->
<meta-data android:name="com.transistorsoft.locationmanager.license" android:value="14ef777231a8412c8b2d109443999356a2c13e62c07e2868345f5e13f01b3c83" />
<meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="#mipmap/ic_launcher"/>
<receiver android:name="com.evollu.react.fcm.FIRLocalMessagingPublisher"/>
<receiver android:enabled="true" android:exported="true" android:name="com.evollu.react.fcm.FIRSystemBootEventReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.QUICKBOOT_POWERON"/>
<action android:name="com.htc.intent.action.QUICKBOOT_POWERON"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
</application>
</manifest>
I see your current problem is about your installed package. You made some conflict package install.
Please remove io.invertase.firebase.messaging from your app.
npm uninstall react-native-firebase --save
Then you also need to remove from your settings.gradle

Categories

Resources