The THN Native SDK enables seamless integration of The Hotels Network widgets into your native iOS and Android applications. This SDK provides a lightweight bridge between your app and THN's web-based personalization features.
- iOS 15.0+
- Xcode 14+
- Swift 5.0+
- Android API 21+ (Android 5.0 Lollipop)
- AndroidX compatibility
- Download the THNNativeSDK.xcframework from the latest release
- Drag the framework into your project
- Ensure it's added to the "Embed & Sign" section in your target's settings
- Download the AAR file from the latest release
- Place it in your app's libs directory
- Add the following to your build.gradle:
dependencies {
implementation fileTree(dir: 'libs', include: ['*.aar'])
}import UIKit
import THNNativeSDK
class HotelViewController: UIViewController {
private var widgetLoader: THNWidgetLoader!
override func viewDidLoad() {
super.viewDidLoad()
// Create and configure the widget
let data = THNData(
propertyId: "YOUR_PROPERTY_ID",
pageName: .roomsAndRates,
languageCode: "en"
)
// Create a binding for the data
let dataBinding = Binding(
get: { data },
set: { _ in }
)
// Create bindings for error and visibility states
let errorBinding = Binding<Error?>(
get: { nil },
set: { _ in }
)
let visibilityBinding = Binding(
get: { true },
set: { _ in }
)
// Create the widget
widgetLoader = THNWidgetLoader(
data: dataBinding,
error: errorBinding,
debugMode: false,
isVisible: visibilityBinding
)
// Add it to your view
let hostedView = UIHostingController(rootView: widgetLoader)
addChild(hostedView)
view.addSubview(hostedView.view)
hostedView.view.frame = view.bounds
hostedView.didMove(toParent: self)
}
}import SwiftUI
import THNNativeSDK
struct HotelView: View {
@State private var thnData = THNData(
propertyId: "YOUR_PROPERTY_ID",
pageName: .roomsAndRates,
languageCode: "en",
currencyCode: "USD"
)
@State private var isVisible: Bool = true
@State private var error: Error? = nil
var body: some View {
ZStack {
// Your content here
// THN Widget
THNWidgetLoader(
data: $thnData,
error: $error,
debugMode: false,
isVisible: $isVisible
)
}
}
}import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.thehotelsnetwork.thnnativesdk.THNData
import com.thehotelsnetwork.thnnativesdk.THNPageName
import com.thehotelsnetwork.thnnativesdk.THNWidgetLoader
class HotelActivity : AppCompatActivity() {
private lateinit var widgetLoader: THNWidgetLoader
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_hotel)
widgetLoader = findViewById(R.id.thn_widget)
// Create the data for the widget
val thnData = THNData(
propertyId = "YOUR_PROPERTY_ID",
pageName = THNPageName.ROOMS_AND_RATES,
languageCode = "en",
currencyCode = "USD"
)
// Configure the widget
widgetLoader.configure(
data = thnData,
debugMode = false,
isVisible = { isVisible ->
// Handle visibility changes
}
)
}
}Layout XML:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- Your other views here -->
<com.thehotelsnetwork.thnnativesdk.THNWidgetLoader
android:id="@+id/thn_widget"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>The THN SDK uses several data models to structure information:
The main container for all widget data:
// Swift
THNData(
propertyId: String, // Your THN property ID
pageName: THNPageName, // Current page type
languageCode: String? = nil, // Optional language code (e.g., "en")
currencyCode: String? = nil, // Optional currency code (e.g., "USD")
bookingId: String? = nil, // Optional booking identifier
search: THNSearch? = nil, // Optional search parameters
results: THNResults? = nil // Optional search results
)// Kotlin
THNData(
propertyId: String, // Your THN property ID
pageName: THNPageName, // Current page type
languageCode: String? = null, // Optional language code (e.g., "en")
currencyCode: String? = null, // Optional currency code (e.g., "USD")
bookingId: String? = null, // Optional booking identifier
search: THNSearch? = null, // Optional search parameters
results: THNResults? = null // Optional search results
)Enum that identifies the current page type:
// Swift
enum THNPageName {
case index // Homepage
case search // Search page
case roomsAndRates // Rooms and rates page
case booking // Booking page
case bookingConfirmed // Booking confirmation page
}// Kotlin
enum class THNPageName {
INDEX, // Homepage
SEARCH, // Search page
ROOMS_AND_RATES, // Rooms and rates page
BOOKING, // Booking page
BOOKING_CONFIRMED // Booking confirmation page
}Search parameters for hotel rooms:
// Swift
THNSearch(
checkIn: String, // Check-in date (format: "YYYY-MM-DD")
checkOut: String, // Check-out date (format: "YYYY-MM-DD")
promoCode: String? = nil, // Optional promotion code
adults: Int? = nil, // Optional number of adults
children: Int? = nil, // Optional number of children
rooms: [THNRoom] = [] // List of room configurations
)// Kotlin
THNSearch(
checkIn: String, // Check-in date (format: "YYYY-MM-DD")
checkOut: String, // Check-out date (format: "YYYY-MM-DD")
promoCode: String? = null, // Optional promotion code
adults: Int? = null, // Optional number of adults
children: Int? = null, // Optional number of children
rooms: List<THNRoom> = emptyList() // List of room configurations
)Enable debug mode to help with integration issues:
// Swift
THNWidgetLoader(
data: $thnData,
error: $error,
debugMode: true, // Enable debug mode
isVisible: $isVisible
)// Kotlin
widgetLoader.configure(
data = thnData,
debugMode = true, // Enable debug mode
isVisible = { isVisible ->
// Handle visibility changes
}
)When debug mode is enabled:
- A border appears around the widget area
- Enhanced logging is active
- WebView inspection is available
- Touch events are visualized
-
Widget Not Loading
- Verify your internet connection
- Check that the property ID is correct
- Ensure the widget is properly initialized in your lifecycle methods
-
Widget Shows Nothing
- Make sure the isVisible binding is set to true
- Verify your data model is properly structured
- Check the error binding for any loading errors
-
Memory Issues
- iOS: Make sure your bindings don't create reference cycles
- Android: Properly handle the widget lifecycle and clear listeners when needed
-
Touch Events Not Working
- Make sure your widget is properly sized and visible
- On Android, verify the touch interception is working correctly
- Enable debug mode to visualize touch boundaries
For additional support:
- Enable debug mode to get detailed logs
- Check our sample applications for reference implementations
- Contact support at tech@thehotelsnetwork.com