my space

iOS | เปิด App หรือ Store ด้วย Universal App Link

react-native

August 06, 2019

การเปิด App จาก http link ถ้ามี App ที่ install ไว้แล้วให้เปิดไปที่ App เลย แต่ถ้ายังไม่เคยลง App ให้เปิดไปที่หน้า Store โดยในบทความนี้จะมี 3 ตอนคือ

  1. ทำให้กับ iOS (ตอนนี้)
  2. ทำให้กับ Android
  3. ในกรณีที่ไม่ได้ลง App และมีการเปิด Web นั้นเราจะมีการตรวจสอบและ redirect ไปที่ store ที่เหมาะสม

Test

ข้อดีของ Universal Link ที่ต่างจาก Deep Link คือถ้าเราไม่ได้ Install App เอาไว้ แล้วเปิด Deep Link จะเปิดไม่ได้เลย แต่ถ้าเป็น Universal Link นั้น URL Schemes จะเป็น https ธรรมดา ดังนั้นถ้าไม่ได้ลง App ไว้ก็จะยังสามารถเปิดไปที่ Web เพื่อแสดง Content ที่ต้องการได้

หลักการ

  1. สร้าง Apple App Site Association file ขึ้นมา เพื่อให้ Web รู้ว่ามันสามารถจัดการกับ App อะไรได้
  2. กำหนด Associated Domains (ใน App)
  3. เมื่อ User เปิดเข้า Url นั้นถ้ามัน match กับที่ define ไว้บน Apple App Site Association มันก็จะเปิด App ขึ้นมาให้เลย แต่ถ้าไม่มี App ลงอยู่มันก็จะเปิด Web ขึ้นมาให้ และใน Web นั้นค่อยไปเช็คว่า user เปิดด้วย Platform อะไร หลังจากนั้นก็จะ redirect ไปที่ Store ของ Platform นั้นๆ

Implementation

สร้าง Apple App Site Association file

โดย format เป็น json มีลักษณะดังนี้

{
  "applinks": {
    "apps": [],
    "details": [
      {
        "appID": "9JA89QQLNQ.com.apple.wwdc",
        "paths": [
          "/wwdc/news/",
          "NOT /videos/wwdc/2010/*",
          "/videos/wwdc/201?/*"
        ]
      }
    ]
  }
}
  • apps จะต้องเป็น [] เท่านั้น
  • appID คือ team Id แล้วต่อด้วย . bundle id เช่น team Id = 9JA89QQLNQ และ bundle id คือ com.apple.wwdc ค่าของ appID ที่จะใช้คือ 9JA89QQLNQ.com.apple.wwdc (หาได้ใน https://developer.apple.com/account/#/membership)
  • paths คือ array ของ Website ที่เราจะเชื่อมกับ App เช่นในที่นี้คือ /wwdc/news นอกจากนี้ยังสามารถระบุได้ว่าส่วนไหนที่จะไม่ให้เชื่อมกับ App ทำได้โดยการใส่ "NOT " นำหน้า เช่น "NOT /videos/wwdc/2010/*" เป็นต้น การ evaluate ว่าจะใช้ path ไหนจะดูตามลำดับ ถ้า match ตรงตาม condition แล้วก็จะไม่ดู path ในลำดับถัดไป
  • จะเห็นว่า details นั้นเป็น array ดังนั้นเราจึงสามารถกำหนดให้ url นี้ทำงานร่วมกับหลาย App ได้ แต่การ evaluate ก็จะเป็นเหมือน paths คือถ้า match condition ไหนแล้ว ก็จะไม่ดูต่อ
{
  "applinks": {
    "apps": [],
    "details": [
      {
        "appID": "9JA89QQLNQ.com.apple.wwdc",
        "paths": ["/wwdc/news/", "/videos/wwdc/2015/*"]
      },
      {
        "appID": "ABCD1234.com.apple.wwdc",
        "paths": ["*"]
      }
    ]
  }
}

ตอนที่สร้างไฟล์นี้ไม่ต้องต่อท้ายด้วย .json ให้ตั้งชื่อว่า apple-app-site-association ไปเลย

นำ apple-app-site-association ไปวางไว้ที่ Web server

ต้องเป็น https เท่านั้น และวางไว้ที่ root directory หรือ .well-known และต้องสามารถเข้าถึงได้ด้วย https://<domain>/apple-app-site-association หรือ https://<domain>/.well-known/apple-app-site-association ในกรณีที่ host บน iis อาจจะต้องมีการสร้าง Web.config เพื่อให้ iis สามารถ serve file type นี้ได้ ตัวอย่าง Web.config คือ

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.WebServer>
    <staticContent>
      <!-- required for apple-app-site-association: -->
      <mimeMap fileExtension="." mimeType="application/json" />
    </staticContent>
  </system.WebServer>
</configuration>

กำหนด Associated Domains (ใน App)

XCode Associated Domains

  • Enable Associated Domains
  • ระบุ applinks: ตามด้วย Domain ที่เราเปิดแล้วสามารถเปิด App นี้ได้

Note

  • ถ้า user เปิด link นั้นมาจาก domain เดียวกันบน Safari เช่นตอนนี้อยู่ที่ https://gie.netlify.com/test.html แล้วกด link ให้เปิดไปที่ https://gie.netlify.com/wwdc/news แทนที่จะเปิด App, iOS จะทำการเปิดหน้า Web ให้แทนเพราะถือว่า user ตั้งใจจะ browse ผ่านทาง Safari แต่ถ้ากดมาจาก domain อื่น, iOS จะเปิด App นั้นขึ้นมาให้
  • ถ้าใช้ต่ำกว่า iOS 9.0 จะเปิดได้แค่ Safari
  • หากเขียน React Native และต้องการให้ redirect ใน App ตาม path ที่ส่งมา ที่ AppDelegate ให้เพิ่มนี้เข้าไปด้วย
#import <React/RCTLinkingManager.h>

- (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull NSUserActivity *)userActivity
 restorationHandler:(nonnull void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler
{
  return [RCTLinkingManager application:application
                   continueUserActivity:userActivity
                     restorationHandler:restorationHandler];
}

ทดสอบ

ทำการ Build App เพื่อรันบน Simulator แล้วทำการเปิด link ตามที่กำหนด (ในที่นี้คือ https://gie.netlify.com/wwdc/news) ควรจะเป็นการเปิด App ขึ้นมา

Test

Reference


gie

Written by gie who lives and works in Bangkok. Build things by code.
my twitter | github