This article explains how to implement the AnyClip Player inside a WebView for in‑app experiences, using preloading to make transitions feel instant. You’ll find platform‑specific examples for iOS and Android that you can adapt to your app structure.
Note: If you’re embedding an entire Watch experience, see the companion WebView article for Watch, which covers general embed and page requirements. AnyClip Help Center
Before You Start
Have your Player or Watch URL ready. You’ll preload that URL so content is cached and ready when the screen appears.
Use an embed‑ready page. For Watch embeds, ensure your page includes a responsive viewport meta tag to optimize mobile rendering (example shown in the Watch Embed article). AnyClip Help Center
Handle media policies. Allow inline playback and configure gesture requirements appropriately (both samples below demonstrate the correct flags).
Why Preloading?
Preloading creates and prepares the WebView before the user navigates to it. When the user switches tabs or opens the relevant screen, the content is already loaded, reducing perceived latency and improving UX—especially on slower networks.
iOS: WebView Preloading in a Tabbed App
Approach: Before displaying the ViewController in the UITabBarController, create and preload the WKWebView
in the UITabBarController
. Call webView.load
with your current URL there, then pass the preloaded WebView to the tab’s ViewController
that will display it.
Sample:
let configuration = WKWebViewConfiguration()
configuration.allowsInlineMediaPlayback = true
let webView = WKWebView(frame: .zero, configuration: configuration)
if #available(iOS 16.4, *) {
webView.isInspectable = true
}
configuration.userContentController.add(watchProductVC, name: "openLink")
webView.load(NSURLRequest(url: NSURL(string: "https://demo.anyclip.com/")! as URL ) as URLRequest)
watchProductVC.webView = webView
How It Works
Create once, reuse across tabs. Construct the
WKWebView
in the tab controller so it survives tab switches.Inline playback:
allowsInlineMediaPlayback = true
ensures video plays in place instead of forcing fullscreen.Preload:
webView.load(...)
runs early, so the first render in your tab is instantaneous.Messaging:
userContentController.add(..., name: "openLink")
wires native handling for in‑page actions such as link taps or deep links.Debugging (iOS 16.4+):
isInspectable = true
helps you debug WebView content via Web Inspector.
Integration Tips
View lifecycle: Add the preloaded WebView to the view hierarchy in
viewDidLoad
/viewWillAppear
, and remove it appropriately if you need to reclaim memory.Navigation delegation: If you need to intercept URL changes (e.g., to open external links natively), implement
WKNavigationDelegate
andWKUIDelegate
.Memory: If your app hosts multiple heavy WebViews, consider a small shared pool and dispose of the least‑recently used instance when memory warnings occur.
Android: WebView Preloading in an Activity + Fragment
Approach: Initialize and store the preloaded WebView
before the Fragment
is created, then attach/detach that instance as the Fragment
appears or is destroyed.
Note: While you can hold a WebView in a ViewModel
, it breaks MVVM principles because ViewModel
should not hold UI references. If you do it, be extremely careful with lifecycle and memory management. The implementation below stores the WebView in the Activity
’s companion object and exposes getters for the Fragment
.
PlayerActivity:
import android.annotation.SuppressLint
import android.content.Context
import android.os.Bundle
import android.view.View
import android.view.ViewGroup
import android.webkit.CookieManager
import android.webkit.WebView
import androidx.appcompat.app.AppCompatActivity
import com.anyclip.sample.databinding.ActivityPlayerBinding
import com.anyclip.sample.webview.WebViewClient
class PlayerActivity : AppCompatActivity() {
private lateinit var binding: ActivityPlayerBinding
companion object {
private var watchProductWebView: WebView? = null
private var fullScreenWebView: WebView? = null
fun getWatchProductWebView(context: Context): WebView? {
val url = SettingsManager.resourcesUrl
if (watchProductWebView == null && url != null) {
watchProductWebView = initWebView(url, context)
}
return watchProductWebView
}
fun getFullScreenWebView(context: Context): WebView? {
val url = SettingsManager.fullScreenWebViewUrl
if (fullScreenWebView == null && url != null) {
fullScreenWebView = initWebView(url, context)
}
return fullScreenWebView
}
@SuppressLint("SetJavaScriptEnabled")
private fun initWebView(link: String, context: Context): WebView {
return WebView(context).apply {
layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
CookieManager.getInstance()
.setAcceptThirdPartyCookies(this, true)
settings.javaScriptEnabled = true
settings.domStorageEnabled = true
settings.mediaPlaybackRequiresUserGesture = true
webViewClient =
WebViewClient(context)
setLayerType(View.LAYER_TYPE_HARDWARE, null)
loadUrl(link)
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityPlayerBinding.inflate(layoutInflater)
setContentView(binding.root)
}
override fun onResume() {
super.onResume()
getFullScreenWebView(this)
getWatchProductWebView(this)
}
override fun onPause() {
super.onPause()
watchProductWebView = null
fullScreenWebView = null
}
override fun onUserLeaveHint() {
super.onUserLeaveHint()
PlayerFragment.getInstance().onUserLeaveHint()
}
}
WatchProductFragment:
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import com.anyclip.sample.databinding.FragmentWatchProductBinding
class WatchProductFragment : Fragment(R.layout.fragment_watch_product) {
private lateinit var binding: FragmentWatchProductBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View {
binding = FragmentWatchProductBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
addWebView()
}
override fun onDestroyView() {
super.onDestroyView()
removeWebView()
}
private fun addWebView() {
val webView = PlayerActivity.getWatchProductWebView(requireContext())
webView?.let {
binding.root.addView(it)
}
}
private fun removeWebView() {
val webView = PlayerActivity.getWatchProductWebView(requireContext())
webView?.let {
(it.parent as ViewGroup?)?.removeView(it)
}
}
}
How It Works
Initialize early in the Activity.
getWatchProductWebView()
andgetFullScreenWebView()
lazily create and load WebViews so they’re warm when the Fragment attaches them.Attach/detach in the Fragment.
addWebView()
andremoveWebView()
move the preloaded instance in and out of the view hierarchy as the Fragment’s view is created/destroyed.Playback & storage: JavaScript and DOM storage are enabled;
mediaPlaybackRequiresUserGesture = true
ensures compliance with Android’s media policies.Performance: Hardware acceleration (
setLayerType(View.LAYER_TYPE_HARDWARE, null)
) keeps rendering smooth.Cookies: Third‑party cookies are allowed to support playback and analytics scenarios that rely on them.
Integration Tips
Lifecycle ownership: Because the WebView lives outside the Fragment, make sure you clear or recreate it if the Activity is destroyed.
Multiple screens: If you maintain two WebViews (e.g., a “watch” and a dedicated fullscreen instance), preload both in
onResume()
so either is ready on demand.Memory: On low‑end devices, consider tearing down the least‑used WebView to reduce RAM pressure.
Testing Checklist
The target URL renders correctly inside the WebView.
Videos play inline (no unexpected fullscreen jumps) and respect your gesture policy.
Switching tabs or opening the player screen after app launch feels instant thanks to preloading.
External links, deep links, and share actions behave as expected (handled by native code where needed).
Related Articles
Embedding the AnyClip Watch in an App WebView Environment — baseline WebView setup and Watch‑specific considerations. AnyClip Help Center
Watch Embed — reference embed code and mobile viewport guidance. AnyClip Help Center