React Native EXPO Notifications

Bir web sitesinin yada kurumsal bir şirketin mobil uygulamasını geliştiriyorsanız bu uygulamayı responsive web tasarımından ayıran tek özelliği Push mesajları olacaktır, daha spesifik özellikler eklenebilir ancak belirttiğim gibi bir web sitesinin uygulaması geliştiriliyorsa çok fazla bir özellik beklenmez.

NOT: Bu makaleyi hazırladığım zamanda React Native EXPO ile push mesaj gönderilemiyordu ancak yeni gelen güncelleme ile birlikte artık gönderim sağlanabilmektedir, bunun ile ilgili yazıyı yeni makalelerimden bulabilirsiniz. 

Expo ile bir proje oluşturduysanız Firebase cloud message veya OneSignal kullanmanız oldukça güç çünkü şuan itibari ile arka planda kod çalıştırmasını desteklemiyor. Expo tarafından geliştirilen Notifications da aynı şekilde tam anlamıyla push mesaj değil çünkü sistem sadece uygulamanız açıksa veya arka planda çalışıyorsa bildirim gönderebiliyorsunuz.

Anlaşılacağı üzere Java yada Swift ile yazılan bir uygulama gibi bildirim göndermeyi React Native den beklemeyin , direk create-react-native-app ile bir uygulama projesi oluşturduysanız bunda Native uygulama geliştirmede olduğu gibi bildirim gönderebilirsiniz ancak EXPO da yok .

Expo push mesaj göndermeyi anlatacak olursak ilk önce kütüphanelerimizi import edelim;

import React, { Component } from 'react';
import { Text, TouchableOpacity, View, StyleSheet, Platform } from 'react-native';
import { Constants, Permissions, Notifications } from 'expo';

import işlemlerinden sonra PHP tarafında önce bir API yazmalıyız bu API nın amacı her cihazın token bilgisini veritabanımızda saklamak , bildirimlerimizi bu token a gönderecez Expo bizim yerimize cihazlara iletecek.

const PUSH_ENDPOINT = 'https://www.brkdgn.com/tokensakla';

yukarıdaki tanımlama token bilgilerinizin gönderileceği URL dir.

export default class App extends Component {
  state = {
    receivedNotification: null,
    lastNotificationId: null,
  }
  
  componentWillMount() {
    this.registerForPushNotificationsAsync();
    
    Notifications.addListener((receivedNotification) => {
      this.setState({
        receivedNotification,
        lastNotificationId: receivedNotification.notificationId,
      });
    });
  }
  
  registerForPushNotificationsAsync = async () => {
    // Android remote notification permissions are granted during the app
    // install, so this will only ask on iOS
    let { status } = await Permissions.askAsync(Permissions.REMOTE_NOTIFICATIONS);
  
    // Stop here if the user did not grant permissions
    if (status !== 'granted') {
      return;
    }
  
    // Get the token that uniquely identifies this device
    let token = await Notifications.getExpoPushTokenAsync();
    console.log(token);
  
    // POST the token to our backend so we can use it to send pushes from there
    return await fetch(PUSH_ENDPOINT, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
      },
      body: serializeKey({
        anahtar: token
      }),
    });
  };
  
  onPressDismissAllNotifications = () => {
    Notifications.dismissAllNotificationsAsync();
    this.setState({
      lastNotificationId: null,
    });
  };
  
  onPressDismissOneNotification = () => {
    Notifications.dismissNotificationAsync(this.state.lastNotificationId);
    this.setState({
      lastNotificationId: null,
    });
  };
  
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.paragraph}>
          receivedNotification: {JSON.stringify(this.state.receivedNotification)}
        </Text>
        {Platform.OS === 'android' && this.renderAndroid()}
      </View>
    );
  }
  
  renderAndroid = () => {
    return (
      <View>
        <TouchableOpacity
          onPress={this.onPressDismissAllNotifications}>
          <Text style={styles.paragraph}>
            Dismiss All Notifications
          </Text>
        </TouchableOpacity>
        {this.state.lastNotificationId && <TouchableOpacity
          onPress={this.onPressDismissOneNotification}>
          <Text style={styles.paragraph}>
            Dismiss Notification {this.state.lastNotificationId}
          </Text>
        </TouchableOpacity>}
      </View>
    );
  }
}

uygulamamızıda bu şekilde tamamlamış oluyoruz, bu işlemlerden sonra uygulamamızı çalıştırdığımızda bildirim almaya hazır olacak sonrasında veritabanımıza kaydedilen Token değerini alarak https://expo.io/dashboard/notifications adresinden push mesaj gönderebilirsiniz, URL üzerinden değilde cURL ile bildirim göndermek istiyorsanız ;

curl -H "Content-Type: application/json" -X POST https://exp.host/--/api/v2/push/send -d '{
  "to": "ExponentPushToken[xxxxxxxxxxxxxxxxxxxxxx]",
  "title":"hello",
  "body": "world"
}'

satırları size yardımcı olacaktır, buradaki URL alanına dokunmayınız çünkü bildirimimizi biz expo ya gönderiyoruz expo da cihazlara gönderiyor.

Uygulamanın tamamı ;

import React, { Component } from 'react';
import { Text, TouchableOpacity, View, StyleSheet, Platform } from 'react-native';
import { Constants, Permissions, Notifications } from 'expo';

const PUSH_ENDPOINT = 'https://www.brkdgn.com/tokenkaydet';

export default class App extends Component {
  state = {
    receivedNotification: null,
    lastNotificationId: null,
  }
  
  componentWillMount() {
    this.registerForPushNotificationsAsync();
    Notifications.addListener((receivedNotification) => {
      this.setState({
        receivedNotification,
        lastNotificationId: receivedNotification.notificationId,
      });
    });
  }
  
  registerForPushNotificationsAsync = async () => {
    let { status } = await Permissions.askAsync(Permissions.REMOTE_NOTIFICATIONS);
    if (status !== 'granted') {
      return;
    }
  
    let token = await Notifications.getExpoPushTokenAsync(); // cihazın token değeri
    console.log(token);
  

    return await fetch(PUSH_ENDPOINT, { // token değeri sunucuya gönderiliyor
      method: 'POST',
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
      },
      body: serializeKey({
        anahtar: token
      }),
    });
  };
  
  onPressDismissAllNotifications = () => {
    Notifications.dismissAllNotificationsAsync();
    this.setState({
      lastNotificationId: null,
    });
  };
  
  onPressDismissOneNotification = () => {
    Notifications.dismissNotificationAsync(this.state.lastNotificationId);
    this.setState({
      lastNotificationId: null,
    });
  };
  
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.paragraph}>
          receivedNotification: {JSON.stringify(this.state.receivedNotification)}
        </Text>
        {Platform.OS === 'android' && this.renderAndroid()}
      </View>
    );
  }
  
  renderAndroid = () => {
    return (
      <View>
        <TouchableOpacity
          onPress={this.onPressDismissAllNotifications}>
          <Text style={styles.paragraph}>
            Dismiss All Notifications
          </Text>
        </TouchableOpacity>
        {this.state.lastNotificationId && <TouchableOpacity
          onPress={this.onPressDismissOneNotification}>
          <Text style={styles.paragraph}>
            Dismiss Notification {this.state.lastNotificationId}
          </Text>
        </TouchableOpacity>}
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
    paddingTop: Constants.statusBarHeight,
    backgroundColor: '#ecf0f1',
  },
  paragraph: {
    margin: 24,
    fontSize: 18,
    fontWeight: 'bold',
    textAlign: 'center',
    color: '#34495e',
  },
});
export function serializeKey(data) {
	var formBody = [];
	for (var property in data) {
	  var encodedKey = encodeURIComponent(property);
	  var encodedValue = encodeURIComponent(data[property]);
	  formBody.push(encodedKey + "=" + encodedValue);
	}
	formBody = formBody.join("&");
	return formBody;
}