PlayTubeVideo

Mobile app guide

Explore the PlayTubeVideo iOS and Android app, configure it from the repository root, connect it to your website, and prepare mobile integrations and Apple In-App Purchases.

Important: Apple In-App Purchases are available only in the iOS app. Android and web checkout keep using their configured payment methods.

What the mobile app includes

The React Native app connects to your PlayTubeVideo website and exposes the platform's mobile experience. Content availability, payment options and creator tools depend on the server's admin settings, user permissions, subscription status and configured integrations.

Discover and watch

Browse the home feed, videos, categories, channels, playlists, artists, movies and series, events, blogs, audio, products and members. Search and open supported content details. The watch screen includes playback controls, related videos and playlist queues when opened from a playlist.

Participate and connect

Sign in or register, manage your profile, follow creators, react and comment where enabled, view stories and reels, join community posts, and use direct messages and supported voice or video calls.

Create and manage

Use the upload flow for supported videos, audio, playlists, channels, movies, events, blogs, products, reels, stories and ads. Creator dashboards expose available content, audience, earnings and stream-management tools according to account permissions.

Library and account

Manage watch-later and favourite videos, offline media when permitted, notifications, account settings, wallet and subscriptions. Supported iOS builds can use Apple In-App Purchases for configured wallet and membership products.

Live and social

Discover and watch live streams and use the configured broadcast flow. Live playback and broadcasting depend on the server's streaming provider, network access and native platform setup.

This is a feature overview, not a guarantee that every feature is enabled for every installation. Configure the corresponding server modules and permissions before testing each flow.

When the device has no internet connection, the app displays a full-screen offline message with a retry action. It returns to the app automatically when internet access is restored.

1. Requirements

  • A working PlayTubeVideo website and API over HTTPS for production use.
  • The standalone mobile source ZIP, Node.js 22.11 or newer, and the Android Studio / Xcode tooling for the platform you are building.
  • Use com.playtubevideo as the app identifier on both platforms. Register this identifier with Apple, Firebase, OAuth providers and push services as applicable.

Prepare the standalone mobile project

Create the mobile ZIP from the repository root, then extract it. The ZIP contains the mobile project files directly at its root. Run the following setup and build commands from that extracted project root, not from the website repository root.

  1. Extract the standalone mobile project ZIP into a working folder, then open a terminal in the extracted project root.
  2. In the extracted project root, create .env from .env.example. Set API_URL to your website origin (for example https://example.com, without appending /api). For a physical device on a development network, use a server address reachable from that device.
  3. Configure optional provider values in .env. Required credentials vary by enabled feature:
    VariablePurpose
    API_URLRequired website origin; use HTTPS in production and do not add /api.
    AGORA_APP_IDOptional client App ID for live streaming when the server does not provide it. Never put the App Certificate or token secret in the app.
    GOOGLE_WEB_CLIENT_ID, GOOGLE_IOS_CLIENT_ID, GOOGLE_IOS_URL_SCHEMEGoogle sign-in client identifiers and iOS callback scheme. Configure matching OAuth clients and server validation.
    FACEBOOK_APP_ID, FACEBOOK_CLIENT_TOKEN, FACEBOOK_DISPLAY_NAME, FACEBOOK_URL_SCHEMEFacebook native sign-in identifiers. Never use a Facebook App Secret as the client token.
    Copy exact variable names and sample formats from .env.example. Never commit or distribute .env.
  4. Keep the native and Expo identifiers aligned: com.playtubevideo for Android applicationId, iOS Bundle Identifier and app.json identifiers. For iOS, register the identifier with your Apple Developer team and select the matching signing team/profile in Xcode.
  5. Install dependencies from the extracted project root:
    npm install
    The mobile package applies its included native dependency patches during installation. For iOS, install CocoaPods from the same root:
    BUNDLE_GEMFILE=Gemfile bundle install
    BUNDLE_GEMFILE=Gemfile RCT_USE_PREBUILT_RNCORE=0 RCT_USE_RN_DEP=0 bundle exec pod install --project-directory=ios
  6. In one terminal at the extracted project root, start Metro:
    npm start
    In a second terminal at that same root, launch the target:
    npm run android
    # or, on macOS with Xcode installed:
    npm run ios
    For iOS purchases, use a signed device or a simulator configured for StoreKit testing.

Run mobile checks from the extracted project root with npm test -- --runInBand, npm run typecheck, or npm run lint.

Keep production API URLs and signing credentials out of public source control. Do not ship an app build that points to a developer machine or local-only HTTP address.

App icon and splash screen

Make branding changes in the extracted mobile project, then rebuild the native app. This is a bare React Native project: changing an Expo icon or splash setting alone does not replace its native launch assets.

The supplied branding masters are in assets/branding/logo-app.png and assets/branding/splash-image.png. Use the logo for launcher/app icons and the splash artwork for the native launch screen; platform-specific copies are stored in the native asset catalogs and Android resources.

iOS app icon

  1. Open ios/PlayTubeVideo.xcodeproj in Xcode and select PlayTubeVideo/Images.xcassets/AppIcon.
  2. Drag your app icon artwork into the matching slots in the AppIcon set. Supply the required iPhone and App Store sizes; the App Store image must be a 1024 × 1024 PNG without transparency. Check that Xcode shows no missing icon slots.
  3. Confirm the app target's Build Settings has Asset Catalog App Icon Set Name set to AppIcon, then build and install again.

Android app icon

  1. Replace android/app/src/main/res/mipmap-*/ic_launcher.png and ic_launcher_round.png with your artwork at each directory's existing density and pixel size. The manifest already refers to these launcher resources.
  2. For adaptive icons on Android 8 and later, add a foreground image and background color or drawable, create the adaptive icon XML under mipmap-anydpi-v26, and update the manifest's android:icon and android:roundIcon references. Keep the main logo inside the safe area because Android launchers apply different masks.
  3. Build and reinstall the app; launcher icon caches can make an updated icon appear only after reinstalling.

iOS splash screen

The launch storyboard displays SplashImage from ios/PlayTubeVideo/Images.xcassets/SplashImage.imageset. Replace that catalog image with assets/branding/splash-image.png when updating the artwork. Keep the launch screen static and lightweight. UILaunchStoryboardName in ios/PlayTubeVideo/Info.plist selects the storyboard.

Android splash screen

  1. The main activity uses SplashTheme. Its pre-Android 12 background is defined by android/app/src/main/res/drawable/splash_background.xml and drawable-nodpi/splash_image.png.
  2. Android 12 and newer use android/app/src/main/res/values-v31/styles.xml. Android controls the splash layout and displays splash_image as a centered system splash icon; it does not support full-screen launch artwork on these versions. postSplashScreenTheme returns to AppTheme after launch.
  3. Test both a pre-Android-12 device or emulator and Android 12+ after a clean rebuild. Keep the native splash short; use an in-app loading screen for any longer startup work.
Keep the source logo and splash artwork under assets/branding in the mobile project, not the website's public image folders. After changing native resources, rebuild and reinstall the app; refreshing Metro does not update native branding.

Push notifications with Firebase

Firebase Cloud Messaging (FCM) delivers standard notifications to the web app and signed-in Android and iOS mobile devices. Configure the Firebase native app files and the website's public web config before enabling push in Admin → Mobile Apps → Push Notifications. Create and configure the Firebase project in the Firebase Console. Follow the Firebase Cloud Messaging setup guide to enable the required messaging APIs. Web push requires HTTPS (localhost is allowed for development). Incoming iOS VoIP calls remain on direct APNs PushKit delivery.

Configure Firebase

  1. Create a Firebase project and register the exact Android package and iOS bundle identifiers used by the app. Enable Firebase Cloud Messaging.
  2. Download the Android google-services.json and put it in android/app/ at the root of the standalone mobile project. Download the iOS GoogleService-Info.plist, add it to the PlayTubeVideo Xcode target, then install pods and rebuild the native app.
  3. For iOS FCM delivery, upload an APNs authentication key in Firebase Console → Project settings → Cloud Messaging. Enable Push Notifications for the Apple App ID and use a provisioning profile with the matching aps-environment entitlement.
  4. In Firebase Project settings, create a Web App and copy its public config JSON. In the Web Push certificates section, create a key pair and copy the VAPID public key.
  5. Create a Firebase service-account key on the server with permission to send FCM messages. Keep its JSON private.
  6. In Admin → Mobile Apps → Push Notifications, enable push and enter the web config JSON, VAPID public key and service-account JSON. The service-account JSON is stored privately and is never included in public app settings.
Check app identifiers before release: the native Android Gradle ID, iOS Xcode bundle ID and app.json values are set to com.playtubevideo. Register this exact identifier with Apple, Firebase and other providers that require a platform app ID.

To verify delivery, install a freshly built app on a device, grant notification permission, sign in and trigger a server notification. On the web, allow notifications in the browser and test both foreground and background delivery. Android 13 and later require notification permission. Rebuild the app after adding or changing Firebase native configuration.

New direct messages are delivered as Firebase web and mobile push notifications and link to the relevant conversation. They are not added to the website notification dropdown or notifications list.

Notification taps route supported content to its mobile detail screen, and the app supports the playtubevideo:// scheme. To open HTTPS links directly from browsers, configure Universal Links/App Links and the domain association files for your production site. For incoming iOS VoIP calls, separately configure the APNs PushKit credentials described in the call notification section below.

Voice and video calling

One-to-one chat calls use Agora credentials separate from the live-streaming Agora project. If either credential is missing, the call-token endpoint responds that calling is not configured and calls cannot connect.

  1. Create or select an Agora project with App Certificate enabled. Keep its App ID and App Certificate private.
  2. In the website admin panel, open Chat Settings and set Chat Agora App ID and Chat Agora App Certificate. Save the settings.
  3. Ensure audio and/or video calling is enabled on the same Chat Settings page, then test a call between two signed-in users on separate devices.
Do not put the App Certificate in the mobile project's .env or the native app. The server uses the certificate to mint short-lived call tokens; the mobile app receives only the token and App ID. Live-streaming Agora credentials do not configure chat calls.

Incoming call notifications

Incoming calls use native call UI so a call can alert the user when the app is backgrounded. iOS uses PushKit and CallKit; Android uses Firebase Cloud Messaging (FCM) and Android Telecom. When a user has multiple registered devices, answering or ending a call on one device dismisses the call on the others.

Before deploying the updated server to an existing installation, apply the database upgrade included in Upgrade version 5.4. New installations already include these database changes.

Android setup

  1. Create a Firebase Android app using package name com.playtubevideo and enable Firebase Cloud Messaging. Add its google-services.json to android/app/ at the standalone mobile project root, set FIREBASE_CALLS_ENABLED=true in the mobile build environment, then open Admin > Mobile Apps > Push Notifications and paste the complete Firebase service-account JSON in the Firebase credentials field. The credential is stored in server settings and is not displayed after saving; keep it private and never put it in the mobile app or source control.
  2. On the device, allow notifications and enable the PlayTubeVideo phone account when prompted. Telecom requires the phone account to show native incoming-call UI.

iOS setup

  1. Enable Push Notifications for the app's Apple identifier and regenerate provisioning profiles. In the app target's Signing & Capabilities, enable Background Modes with Voice over IP and Audio, AirPlay, and Picture in Picture.
  2. In the web admin panel, open Mobile Apps → Push Notifications and configure the APNs .p8 key contents, Key ID, Apple Developer Team ID, iOS app bundle ID, and APNs environment. Choose Production for App Store builds or Sandbox for development/testing. Keep the key on the server; never include it in the mobile app or source control.

Build and test

  1. After configuring Firebase or iOS capabilities, install the native iOS dependencies from ios/ in the standalone mobile project with pod install, then rebuild and install the app. The Android Google Services plugin is enabled when google-services.json is present.
  2. Test on physical devices with the app backgrounded and the screen locked. Verify incoming calls in both directions, answer, decline, hang-up, multi-device dismissal, busy handling, and ring timeout. iOS Simulator does not deliver CallKit/PushKit calls.
FCM and APNs credentials must remain private on the server. Delivery is subject to OS restrictions and cannot be guaranteed after the user force-stops the Android app or force-quits the iOS app. Delivery also requires network access and valid provider credentials; a client-only implementation cannot guarantee WhatsApp-like delivery in those states.

Ant Media live streaming

  1. In the server admin's Live Streaming settings, choose Ant Media Server as the live streaming type. Set the Ant Media application name and server URL, then enable stream-token creation when required by your Ant Media server.
  2. Set HLS Live Streaming Supported to match the server configuration and enter the Ant Media CDN URL when one is configured. The mobile app uses HLS for playback when HLS is enabled; otherwise, WebRTC playback requires Ant Media Enterprise Edition.
  3. Install the mobile JavaScript dependencies and run pod install --project-directory=ios from the extracted project root after changing native dependencies. React Native autolinks react-native-webrtc for iOS and Android.
  4. Test a camera broadcast and an RTMP-ingest broadcast from physical devices on a network that can reach the Ant Media server. Verify viewer playback, chat, recording, and stream termination before release.
  5. Hosts can select Share screen before starting a camera broadcast. Android uses MediaProjection; iOS uses the included ReplayKit broadcast upload extension. For iOS signing, enable the group.com.myiosapp1 App Group for both the app and extension App IDs and regenerate their provisioning profiles. If you change bundle IDs, keep the App Group, RTCAppGroupIdentifier, and RTCScreenSharingExtension values in the Xcode project and Info.plists in sync.

Use a publicly reachable secure server URL for production. When Ant Media is selected but its server URL or application name is missing, the mobile broadcast screen cannot start.

Mobile advertising

The mobile app uses the existing website ad campaign and placement settings; there is no separate mobile admin interface. Eligible pre-roll ads and their impressions are selected and billed by the server. Direct-video and VAST admin pre-roll formats are played before native watch, movie/episode, and reel playback, with click-through tracking handled by the existing ad routes.

Configured HTML placements (including home-feed static ads) render inside a mobile WebView. Test administrator-provided ad markup and its third-party scripts on both iOS and Android, since some browser-only ad integrations may not support embedded WebViews. Advertisers can search and filter their campaigns, view reporting, and recharge the same wallet used by other mobile payment flows from the Advertisements dashboard.

Configured placements are rendered on the matching mobile screens: home header/footer and available carousel slots, search results, movie details, the watch page, and comments. Placement HTML runs in a contained WebView; browser-only integrations may need a mobile-specific creative.

3. Create products in App Store Connect

Create the app record with the exact bundle identifier used by the iOS target. Enable In-App Purchase for the app, complete required agreements and tax/banking setup, and create product IDs before entering them in the admin panel.

Use in app App Store Connect product type Admin mapping
Wallet recharge amount Consumable Wallet Recharge product's Apple In-App Purchase Product ID
Recurring membership package Auto-Renewable Subscription Package's Apple In-App Purchase Product ID
Fixed-duration membership package Non-Renewing Subscription Package's Apple In-App Purchase Product ID
Lifetime membership package Non-Consumable Package's Apple In-App Purchase Product ID

Product IDs are case-sensitive and must match exactly. Use a distinct product ID for each active wallet amount or membership package. Do not map the same ID to multiple active products.

The iOS StoreKit test configuration includes com.playtubevideo.variable.10 as a $10 monthly auto-renewable membership and com.playtubevideo.fixed.20 as a $20 non-consumable lifetime membership. Create matching products in App Store Connect and map each ID to its corresponding package in admin before offering them outside local StoreKit testing.

4. Configure Apple payment settings

  1. Sign in to the site's admin panel and open ADMIN_SLUG/payments (Payments / Payment Settings).
  2. Enable Apple In-App Purchase and select Sandbox while testing or Live for production.
  3. For auto-renewable membership subscriptions, enter the App-Specific Shared Secret in Apple In-App Purchase Shared Secret. Keep it server-side; never put it in the app or a public repository.
  4. Leave other payment gateways enabled if you want users to keep the existing web checkout options.

The backend verifies the Apple receipt and checks the bundle and configured product ID before crediting a wallet or granting a membership. The app does not decide the package price or entitlement.

The Apple root certificate at server/certificates/AppleRootCA-G3.cer is used to verify Xcode StoreKit test transactions. It is Apple's shared root certificate and is not tied to your app or bundle ID, so it does not need to change if the bundle ID changes. Update IOS_APP_BUNDLE_ID and the iOS target's bundle identifier separately so transaction verification checks the correct app.

5. Configure wallet recharge products

  1. In admin, open Payments / Wallet Recharge and create or edit each recharge amount.
  2. Enter the matching App Store Connect consumable product ID in Apple In-App purchase product ID and mark the recharge option active.
  3. Test a purchase and confirm the wallet balance and transaction history update only once.

The App Store price is shown for Apple checkout; it can differ from the site's displayed amount due to storefront pricing and taxes.

6. Configure membership products

  1. Open Payments / Manage Packages and edit the membership package.
  2. Enter its unique App Store Connect product ID in Apple In-App Purchase Product ID. Ensure the package is enabled and its duration/type matches the Apple product configuration.
  3. Use an auto-renewable subscription for a recurring package. Use a non-renewing subscription for a fixed-duration package; set the package duration and unit to the same term.
  4. For lifetime access, use a non-consumable App Store product and configure the package duration type as forever. The mobile app restores and verifies this purchase without an expiration date.

The app offers Apple checkout only for configured eligible packages and displays Apple's localized price. Wallet and web gateway checkout remain available according to your settings. Auto-renewable subscriptions renew until the user cancels them; they cannot be configured to stop automatically after 12 monthly payments.

7. Renewal and expiration notifications

For auto-renewable memberships, configure App Store Server Notifications to use:

https://YOUR_DOMAIN/apple-pay-notification

Use the exact public HTTPS hostname. Notifications let the backend refresh subscription state and apply renewals or expiration changes. Confirm the notification endpoint is reachable from Apple and review server logs during sandbox tests.

8. Apply the migration, test and release

  1. Back up the database, then apply Upgrade/v5.3/playtubevideo.sql once. It creates the transaction ledgers used to prevent duplicate wallet credits and membership activations.
  2. Use App Store Connect Sandbox testers or StoreKit testing to test successful, cancelled, restored and failed purchases.
  3. Verify wallet balances, membership role/expiry, transaction history and repeat receipt submission. A transaction must not grant its benefit twice or to a second account.
  4. Before release, switch to Live products and configuration, verify signing and bundle IDs, confirm the app uses the production HTTPS API, and submit the app with the IAP products for App Review.

A user's eligible Apple purchases can be restored from Restore Apple Purchases on the mobile Upgrade screen.

Troubleshooting

  • Product unavailable: check Apple IAP is enabled, the product is available in the current storefront, the environment is correct, and the product ID exactly matches the admin mapping.
  • Receipt rejected: confirm the bundle ID, server environment, product type and server shared secret for auto-renewable subscriptions.
  • Plan does not appear in Apple checkout: only eligible recurring or fixed-duration packages with a configured App Store product are offered through StoreKit.
  • Duplicate product mapping: ensure each product ID belongs to exactly one active wallet option or membership package.
  • Check the server error log for the request failure. Never include receipts, shared secrets or customer data in public support requests.
Database upgrade: apply the v5.3 SQL once after taking a backup and before enabling IAP purchases. Do not rerun a CREATE TABLE migration against an already-upgraded database unless you have confirmed the table does not exist.