Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[KEPLR-319, Mobile] Add firebase push notification POC #1140

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions apps/mobile/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ DerivedData
*.ipa
*.xcuserstate
ios/.xcode.env.local
GoogleService-Info.plist

# Android/IntelliJ
#
Expand All @@ -33,6 +34,7 @@ local.properties
.cxx/
*.keystore
!debug.keystore
google-services.json

# node.js
#
Expand Down
104 changes: 103 additions & 1 deletion apps/mobile/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,14 @@ import {StoreProvider} from './src/stores';
import {GestureHandlerRootView} from 'react-native-gesture-handler';
import {StyleProvider, useStyle} from './src/styles';
import {AppNavigation} from './src/navigation';
import {I18nManager, Platform, Settings, StatusBar} from 'react-native';
import {
I18nManager,
Linking,
PermissionsAndroid,
Platform,
Settings,
StatusBar,
} from 'react-native';
import {SafeAreaProvider} from 'react-native-safe-area-context';
import {AppIntlProvider} from './src/languages';
import codePush from 'react-native-code-push';
Expand Down Expand Up @@ -46,6 +53,9 @@ import {ImportFromExtensionProvider} from 'keplr-wallet-mobile-private';
import {AsyncKVStore} from './src/common';
import {AutoLock} from './src/components/unlock-modal';
import {setJSExceptionHandler} from 'react-native-exception-handler';
import messaging from '@react-native-firebase/messaging';
import notifee, {EventType} from '@notifee/react-native';

const semver = require('semver');

const ThemeStatusBar: FunctionComponent = () => {
Expand Down Expand Up @@ -126,6 +136,10 @@ class AppUpdateWrapper extends Component<{}, AppUpdateWrapperState> {

protected lastTimeout?: number;

protected firebaseForegroundNotification?: () => void;
protected notifeeForegroundNotification?: () => void;
protected firebaseOpenApp?: () => void;

override componentDidMount() {
// Ensure that any CodePush updates which are
// synchronized in the background can't trigger
Expand Down Expand Up @@ -248,6 +262,7 @@ class AppUpdateWrapper extends Component<{}, AppUpdateWrapperState> {
protected async init(): Promise<void> {
this.crawlStoreUpdate();
this.crawlCodepushUpdate();
this.initPushNotification();
}

protected async crawlStoreUpdate(): Promise<void> {
Expand Down Expand Up @@ -388,6 +403,93 @@ class AppUpdateWrapper extends Component<{}, AppUpdateWrapperState> {
}
}

protected async initPushNotification(): Promise<void> {
let enabled = false;

// 각 플랫폼별로 권한을 요청함.
if (Platform.OS === 'android') {
const status = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS['POST_NOTIFICATIONS'],
);

if (status === 'granted') {
enabled = true;
}
}

if (Platform.OS === 'ios') {
const authStatus = await messaging().requestPermission();
enabled =
authStatus === messaging.AuthorizationStatus.AUTHORIZED ||
authStatus === messaging.AuthorizationStatus.PROVISIONAL;
}

if (enabled) {
this.firebaseForegroundNotification = messaging().onMessage(
async remoteMessage => {
// Create a channel (required for Android)
const channelId = await notifee.createChannel({
id: 'default',
name: 'Default Channel',
});

if (
remoteMessage.notification?.title &&
remoteMessage.notification?.body
) {
// Firebase를 통해 노티가 왔을 때 Notifee를 통해 노티를 띄움
await notifee.displayNotification({
title: remoteMessage.notification?.title,
body: remoteMessage.notification?.body,
android: {
channelId,
},
});
}
},
);

this.notifeeForegroundNotification = notifee.onForegroundEvent(
({type}) => {
if (type === EventType.PRESS) {
// 유저가 내부 알림을 눌렀을 때 딥링크 테스트
Linking.openURL(
'keplrwallet://staking?chainId=cosmoshub-4&validatorAddress=cosmosvaloper1gf3dm2mvqhymts6ksrstlyuu2m8pw6dhfp9md2',
);
}
},
);

this.firebaseOpenApp = messaging().onNotificationOpenedApp(
notification => {
console.log(
'Notification opened by tapping on the notification',
JSON.stringify(notification),
);

// 유저가 백그라운드 알람을 눌렀을 때 딥링크 테스트
Linking.openURL(
'keplrwallet://staking?chainId=cosmoshub-4&validatorAddress=cosmosvaloper1gf3dm2mvqhymts6ksrstlyuu2m8pw6dhfp9md2',
);
},
);
}
}

override componentWillUnmount() {
if (this.firebaseForegroundNotification) {
this.firebaseForegroundNotification();
}

if (this.notifeeForegroundNotification) {
this.notifeeForegroundNotification();
}

if (this.firebaseOpenApp) {
this.firebaseOpenApp();
}
}

restartApp() {
if (Platform.OS === 'ios') {
codePush.allowRestart();
Expand Down
1 change: 1 addition & 0 deletions apps/mobile/android/app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
apply plugin: "com.android.application"
apply plugin: "com.google.gms.google-services"
apply plugin: "org.jetbrains.kotlin.android"
apply plugin: "com.facebook.react"

Expand Down
1 change: 1 addition & 0 deletions apps/mobile/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ buildscript {
classpath("com.bugsnag:bugsnag-android-gradle-plugin:7.+")
classpath("com.facebook.react:react-native-gradle-plugin")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin")
classpath("com.google.gms:google-services:4.4.2")
}
}

Expand Down
3 changes: 3 additions & 0 deletions apps/mobile/ios/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ target 'keplrmobile' do
end
config = use_native_modules!

use_frameworks! :linkage => :static
$RNFirebaseAsStaticFramework = true

use_react_native!(
:path => config[:reactNativePath],
# Hermes is now enabled by default. Disable by setting this flag to false.
Expand Down
Loading
Loading