React Native ve Deep Linking

Merhabalar, bu yazımda deep linking’in ne olduğundan ve nasıl yapabileceğimizden bahsedeceğim. Ayrıca yazıyı tam olarak okuduğunuzda şu konularda bilgi sahibi olacaksınız:

  • Deep Linking nedir?
  • Deep Linking nasıl yapılır?
  • Deep Linking ile React Native’de istediğim ekrana nasıl gidebilirim?
  • Deep Linking ile React Native’de istediğim ekrana istediğim veriyi nasıl gönderirim?

Deep Linking Nedir?

Deep linking bir web sitesini ziyaret etmek istediğimizde o web sitenin mobil uygulaması varsa web siteyi mobil uygulamaya yönlendirmemize ve mobil uygulamayı açabilmemize yarıyor. Bunun için ziyaretçileri uygulamamıza tanıttığımız linke yönlendirmemiz gerekiyor. Ben React Native ile mobil uygulama geliştirdiğim için React Native odaklı anlatacağım ama genel olarak mantık aynı diyebiliriz. Sonuçta ANDROID için AndroidManifest.xml dosyasında, IOS için ise Info.plist dosyasında değişiklik yapacağız. Geriye kalan kodlar ise kullandığımız yazılım dilinin syntax’ı ile ilgili.

Deep Linking Nasıl Yapılır?

İlk öncelikle bir React Native projesi oluşturalım.

react-native init DeepLinking ya da npx react-native init DeepLinking

ANDROID AYARLARI

DeepLinking adında oluşturduğumuz projemizin klasörüne girip AndroidManifest.xml dosyasını bulalım.

android > app > src > main > AndroidManifest.xml

Manifest dosyamızın içindeki <activity></activity> etiketlerinin arasına aşağıdaki kodu ekliyoruz.

<intent-filter>
   <action android:name="android.intent.action.VIEW" />
   <category android:name="android.intent.category.DEFAULT" />
   <category android:name="android.intent.category.BROWSABLE" />
   <category android:scheme="deep-linking" />
</intent-filter>

Yukarıdaki kodu manifest dosyamıza ekledikten sonra webte gezinen bir ziyaretçi eğer cihazında uygulamamız yüklüyse ve deep-linking:// adresine yönlendirilirse kullanıcıya bir popup açılıyor ve uygulamayı açmak isteyip istemediği soruluyor. Hangi seçeneği seçerse (browser ya da uygulama) o seçenekten devam ediyor. Fakat şöyle bir durum var ki ziyaretçi eğer tarayıcıyı seçerse boş bir ekran görecek çünkü deep-linking:// adresinde hiçbir şey yok aslında 🙂

Bu kodu şu şekilde de kullanabiliriz örneğin deep-linking:// adresine yönlendirmek yerine direkt web siteniz için bunu yapmak istiyorsunuz diyelim. O zaman aşağıdaki kodu yazabilirsiniz. Böylece yönlendirme yapmak zorunda kalmazsınız fakat şunu da hatırlatayım eğer kullanıcı sitenize direkt olarak erişirse (herhangi bir linke tıklamadan) web siteniz açılır fakat arama motoru üzerinden aratır ve çıkan sonuçlardan web sitenize tıklarsa o zaman mobil uygulama üzerinden açılır. Herhangi bir sosyal medya uygulamasının web sitesini direkt olarak adres çubuğuna yazıp girin bir de arama motorunuzda aratıp çıkan sonuçlardan uygulamanın web sitesine tıklayın. Ne demek istediğimi anlayacaksınız 🙂
Şimdi örnek kodumuzu yazalım.

<intent-filter>
   <action android:name="android.intent.action.VIEW" />
   <category android:name="android.intent.category.DEFAULT" />
   <category android:name="android.intent.category.BROWSABLE" />
   <category android:scheme="http" />
   <category android:scheme="https" />
   <category android:host="hasanberkm.com" />
</intent-filter>

Buradaki android:host etiketi bizim sunucumuzu tanımlıyor ve bu siteye her tıklandığında uygulamamızın açılmasını sağlıyor.

IOS AYARLARI

IOS için yapmamız gerekense öncelikle aşağıdaki yolu izleyerek Info.plist dosyasını bulmak.

ios > ProjeAdi > Info.plist

Şimdi ise aşağıdaki kodları Info.plist’in içindeki <dict></dict> etiketlerinin arasına ekliyoruz.

<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>deep-linking</string>
<key>CFBundleURLSchemes</key>
<array>
<string>deep-linking</string>
</array>
</dict>
</array>

Yukarıdaki kodu yazmak istemiyorsanız aşağıdaki sırayı izleyerek Xcode üzerinden de yapabilirsiniz.
xcode-deeplinking

Artık bu yaptıklarımızı test edebiliriz 🙂

İLK TEST

Şimdi localhost’u başlatıp deep-linking.html adında bir dosya oluşturup içine şu kodu ekleyelim:

<a href="deep-linking://">Deep Linking</a>

Şimdi React Native projemizi başlatalım ve projemiz simülatöre yüklenince simülatör üzerinden tarayıcıyı açıp linke tıklayalım.
react-native-deep-linking

Deep Linking ile React Native’de istediğim ekrana nasıl gidebilirim?

Şimdi deep-linking.html dosyamızı şu şekilde güncelleyelim:

<a href="deep-linking://">Deep Linking - Anasayfa Ekranı</a><br><br>
<a href="deep-linking://Profil">Deep Linking - Profil Ekranı</a><br><br>
<a href="deep-linking://Profil/id:1,username:hasanberkm.com">Deep Linking - Profil Ekranı (id:1)</a>

Burada izleyeceğim senaryo şu şekilde olacak. İlk önce uygulamayı tetikleyen linki ‘/’ işaretine göre parçalayacağım. Bu işlemde elde ettiğim dizinin ilk elemanı benim gideceğim ekranın (routeName) adı olacak. sonraki eleman ise göndereceğim parametreler olacak ve parametreleri de virgül ile ayırdığım için ‘,’ işaretine göre parçalayıp elde ettiğim metni objeye çevirip parametre olarak gönderebileceğim. Bu kısma geçmeden önce ben projemize React Navigation kütüphanesini dahil ettim çünkü ekranlar arası geçişi daha kolay hale getiriyor ayrıca header ve menü kodlamamıza gerek kalmadığı gibi istediğimiz gibi kişiselleştirebiliyoruz. Aşağıdaki kodları terminalinize yazarak React Navigation’u projenize dahil edebilirsiniz.

YARN İle KurulumNPM İle Kurulum
yarn add @react-navigation/nativenpm install @react-navigation/native
yarn add react-native-screens react-native-safe-area-contextnpm install react-native-screens react-native-safe-area-context
yarn add @react-navigation/stacknpm install @react-navigation/stack
yarn add react-native-gesture-handlernpm install react-native-gesture-handler

IOS ve Android için yapmanız gerekenleri resmi web sitesi üzerinden takip edebilirsiniz. Bu aşamada IOS için
npx pod-install ios ya da cd ios && pod install yazmanız yeterli olacaktır.

Şimdi link kontrolünü yapalım. Bunu yapabilmek için react-native kütüphanesinden Linking bileşenini çağırmamız gerekiyor. Ayrıca ekranın tam ortasına yazı ekleyeceğimiz için View ve Text bileşenlerini de çağırmamız gerekiyor.

import { Text, View, Linking } from "react-native"; 

Yukarıdaki kodu ilk açılan ekranımıza yazıyoruz. React Navigation’daki navigationa eklediğiniz ilk route ana ekranınız olacaktır (initialRouteName ile başka bir ekranı tanımlamadığınız sürece). Böylece ilk açılan ekranımızda birazdan yazacağımız kod ile istediğimiz ekrana yönlendirme yapabileceğiz. Kısaca Stack Navigation yapımı da göstereyim (Kodları App.tsx dosyama ekledim).

//React Navigation
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';

//Stack Navigator
const Stack = createStackNavigator();

//Screens
import Home from './screens/Home';
import Profile from './screens/Profile';

const App = () => {
   return (
      <NavigationContainer>
         <Stack.Navigator> 
            <Stack.Screen name="Anasayfa" component={Home} /> 
            <Stack.Screen name="Profil" component={Profile} /> 
         </Stack.Navigator> 
      </NavigationContainer>
    );
}
export default App;

Şimdi az önce bahsettiğimiz link parçalama olayına gelelim. Aşağıdaki kodu screens/Home.tsx dosyasına ekleyerek url’i ‘/’ işaretine göre parçalamış olacağız.

Linking.getInitialURL().then(url => { 
   url = url.split("deep-linking://")[1].split("/");
   const screen = url[0];
   navigation.navigate(screen); 
});

Burada ilk önce “deep-linking://”e göre parçalıyoruz çünkü o görevini bizim için tamamladı dolayısıyla işimiz kalmadığı için onu almıyoruz. Bizim için ondan sonra gelen kısım önemli ve o kısmı da “/” işaretine göre parçaladık sonra da url değişkenine aktardık.
İkinci satırda ise url dizisindeki ilk elemanı screen değişkenine aktardık. Böylece bizim buradan çektiğimiz veri eğer navigationda tanımlıysa açacak değilse anasayfada kalacak.
Biraz önce yukarıda yazdığımız html kodunu hatırlayalım. Oradaki <a> etiketlerinden birine href olarak deep-linking://Profil tanımlamıştık. Buradaki Profil aslında bizim tanımladığımız route adı. Bu linke tıkladığımızda Profil adında bir route tanımladığımız için Profil sayfamız açılacak. Hadi test edelim 🙂

Deep Linking ile React Native’de istediğim ekrana istediğim veriyi nasıl gönderirim?

Artık yazımın son kısmına geldik. Yukarıda Linking bileşenini kullanarak yazdığımız kodu ufak bir geliştirmeyle parametreyi istediğimiz ekrana gönderebileceğiz. Yukarıda yazmış olduğumuz kodu aşağıdaki kod ile değiştirmemiz yeterli. Ayrıca url yapısını yukarıdaki html sayfamızdaki üçüncü <a> etiketinde görebilirsiniz. Şimdi kodumuzu şu şekilde güncelleyelim:

Linking.getInitialURL().then(url => { 
   url = url.split("deep-linking://")[1].split("/");
   const screen = url[0];
   let params = [];

   if(url[1]){
       params = url[1].split(",")
       .map(val => val.split(":"))
       .reduce((acc, curr) => {
          acc[curr[0]] = curr[1]
          return acc
       }, {}); 
   }

   navigation.navigate(screen, params); 
});

Yukarıda if bloğunun içinde önce linkte göndereceğimiz parametrelerimizin bulunduğu kısmı virgülle ayırdığımız için ‘,’ işaretine göre ayırdık sonra map fonksiyonuyla parametrelerimizi ‘:’ işaretine göre parse ederek diziye çevirdik sonra reduce fonksiyonuyla objeye çevirdik. Böylece yukarıdaki tanımladığımız linkteki parametre şu şekilde bir objeye dönüştü: {‘id’:’1′,’username’:’hasanberkm.com’}. Bu objeyi de navigate fonksiyonuna ikinci parametre olarak gönderdik o da aktarmak istediğimiz ekrana gönderdi bile 🙂

Peki gitmek istediğiö ekranda bu parametreleri nasıl alacağız? Cevabı çok basit önce Profil sayfasını oluşturalım ben root klasörümün içine screens klasörü oluşturdum ve içine de screens/Profile.tsx dosyasını yanı profil ekranımı oluşturdum. Şimdi de ekranın kodlarını görelim:

import React, { useEffect, useState } from "react";
import { Text, View } from "react-native";

const Profile = ({ navigation, route }) => { 
   let params = [];

   if(route.params){
      Object.keys(route.params).map((val,i) => { 
         params.push(<Text key={i}>{val + ":" +    route.params[val]}</Text>);
      }) 
   }

   return (
      <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
        {params}
      </View> 
   )
}

export default Profile;

Burada tüm parametreleri ekrana yazdırmak istediğim için Object.keys kullandım. Siz istediğiniz parametreyi route.params.parametreAdi olarak alabilirsiniz ya da const {parametreAdi1, parametreAdi2} = route.params şeklinde de tanımlayabilirsiniz.

Hadi gelin şimdi de projemizin son halini test edelim 🙂

Böylece uzun ama zevkli bir konuya da el atmış olduk. URL yapınızı ve değişkenlerinizi istediğiniz gibi tanımlayabilirsiniz. Yazımı beğendiyseniz arkadaşlarınızla paylaşmayı ihmal etmeyin. Bir başka yazıda görüşmek üzere… 🙂