RxJava2, Android, Webview Create Observable in Kotlin - android

Just getting started with trying to "Rx-ify" some of Android's Webview events.
class PageStartData(val url: String, val favicon: Bitmap?)
myWebview.webViewClient = object: WebViewClient() {
val pageStartEvents: Observable<PageStartData> = Observable.create{ emitter->
override fun onPageStarted(view: WebView, url: String, favicon: Bitmap){
emitter.onNext(PageStartData(url, favicon))
}
}
}
And I have found that the onPageStarted function is out of scope in the emitter lambda function. Very simple, I'm sure. How to fix?
All help appreciated.

Check this:
sealed class WebViewEvent {
data class PageStartData(val url: String?,
val favicon: Bitmap?) : WebViewEvent()
}
...
class RxWebViewWrapper(private val webView: WebView) : ObservableOnSubscribe<WebViewEvent> {
override fun subscribe(emitter: ObservableEmitter<WebViewEvent>) {
webView.webViewClient = object :WebViewClient(){
override fun onPageStarted(view: WebView?,
url: String?,
favicon: Bitmap?) {
super.onPageStarted(view, url, favicon)
emitter.onNext(WebViewEvent.PageStartData(url, favicon))
}
}
}
}
...
val source = Observable.create<WebViewEvent>(RxWebViewWrapper(myWebview))

It can be done via PublishSubject
myWebview.webViewClient = object : WebViewClient() {
private val pageStartSubject = PublishSubject.create<PageStartData>()
val pageStartEvents: Observable<PageStartData> = pageStartSubject
override fun onPageStarted(view: WebView, url: String, favicon: Bitmap) {
pageStartSubject.onNext(PageStartData(url, favicon))
}
}

Related

Trying to load params through webViewClient but getting error from mnemonics not defined

Here is my code and it's working in demo project but not in my project. I am trying to add these parameters through webView Client but it is showing from mnemonics not found.
fun sendTrx(c:Context, from_address: String, fromMnemonics: String, amount: String, toAddress: String) {
mycontext=c
var webvw = WebView(mycontext)
webvw.addJavascriptInterface(this, "Android")
webvw.settings.javaScriptEnabled = true
webvw.settings.domStorageEnabled=true
webvw.webViewClient = object : WebViewClient() {
override fun shouldOverrideUrlLoading(
view: WebView?,
request: WebResourceRequest?
): Boolean {
getCustomHeaders()?.let { view!!.loadUrl(request!!.url.toString(), it) };
return true;
}
}
webvw.loadUrl("file:///android_asset/send.html")
val amtChanged = amount.toDouble() * 1000000000000
val amtTobeTransferred = BigDecimal(amtChanged).toBigInteger()
webvw.webViewClient = object : WebViewClient() {
override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
super.onPageStarted(view, url, favicon)
webvw.loadUrl("javascript:from_address(\"$from_address\")")
webvw.loadUrl("javascript:fromMnemonics(\"$fromMnemonics\")")
webvw.loadUrl("javascript:amtTobeTransferred(\"$$amtTobeTransferred\")")
webvw.loadUrl("javascript:toAddress(\"$toAddress\")")
// webvw.loadUrl("javascript:toAddress(\"$toAddress\")")
}
}
check in your javascript code that you have field/ method named "fromMnemonics" or not

WebView Issue when using thumbnail page

Some time page with poster thumbnail throws null pointer exception in web view[Andoid].
I have already tried this code.
`lateinit var webView: WebView
webView = view.findViewById(R.id.webView) as WebView
webView.settings.javaScriptEnabled = true
webView.isHorizontalScrollBarEnabled = false
webView.postDelayed({ webView.loadUrl(url) }, 100)
webView.webViewClient = object : WebViewClient() {
override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
super.onPageStarted(view, url, favicon)
progressLayout.visibility = View.VISIBLE
}
override fun onPageFinished(view: WebView, url: String) {
// do your stuff here
progressLayout.visibility = View.INVISIBLE
homeScreenImage.visibility = View.GONE
}
}`
Please try this if it works
you can use web chrome client and override default video poster and load default bitmap in case of loading fails
webView.webChromeClient = object : WebChromeClient() {
override fun getDefaultVideoPoster(): Bitmap? {
val result = super.getDefaultVideoPoster()
return result ?: Bitmap.createBitmap(1, 1, Bitmap.Config.RGB_565)
}
override fun onProgressChanged(view: WebView?, newProgress: Int) {
super.onProgressChanged(view, newProgress)
}
}

App redirects to blank screen when opening modal in webview

I have a WebView in my app. But when the website behavior is to open a modal, the webview redirects me to a blank screen. I put logs in onPageStarted and shouldOverrideUrlLoading, and saw that it doesn't fit in either method.
webview.settings.javaScriptEnabled = true
webview.settings.domStorageEnabled = true
webview.settings.javaScriptCanOpenWindowsAutomatically = true
webview.settings.setSupportMultipleWindows(true)
webview.settings.allowFileAccess = true
webview.setWebChromeClient(object : WebChromeClient() {
#SuppressLint("SetJavaScriptEnabled")
override fun onCreateWindow(
view: WebView?,
isDialog: Boolean,
isUserGesture: Boolean,
resultMsg: Message
): Boolean {
val newWebView = WebView(context)
val webSettings = newWebView.settings
webSettings.javaScriptEnabled = true
// Other configuration comes here, such as setting the WebViewClient
val dialog = Dialog(context!!)
dialog.setContentView(newWebView)
dialog.show()
newWebView.setWebChromeClient(object : WebChromeClient() {
override fun onCloseWindow(window: WebView) {
dialog.dismiss()
}
})
(resultMsg.obj as WebViewTransport).webView = newWebView
resultMsg.sendToTarget()
return true
}
})
webview.setWebViewClient(object : WebViewClient() {
override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
super.onPageStarted(view, url, favicon)
}
override fun shouldOverrideUrlLoading(webView: WebView, url: String): Boolean {
webView.loadUrl(url)
return true
}
override fun onPageFinished(view: WebView, url: String) {
super.onPageFinished(view, url)
Handler().postDelayed({
if(progressBar!=null)
progressBar.visibility = View.GONE
}, 3500)
}
})
webview.loadUrl(url)
I also tried to redirect it to the chrome client if it was going to open the modal, but as it doesn't load any new urls, I don't think it's overwriting the method

How to check if variable value is Changed in other thread in Kotlin?

I am trying to change my Variable inside my WebViewClient but my Function don't wait for page to load. I think It is because WebView has its own thread. If that is the case then how can I pause my function to wait for page. or is there any other method to keep the value in my Function?
private fun getNewUrl(url: String): String {
var newUrl = "null"
val webView = WebView(applicationContext)
webView.webViewClient = object : WebViewClient() {
override fun onPageFinished(view: WebView?, url: String?) {
super.onPageFinished(view, url)
Toast.makeText(applicationContext, "Page Loaded", Toast.LENGTH_SHORT).show()
newUrl = url.toString()
}
}
webView.loadUrl(url)
return newUrl
}
Yes. Because that call happens Asynchronously. It doesn't block the execution of following lines.
So you need to have your listener class called when that result is loaded & use that result.
For example:
Create an interface:
interface OnPageLoadedListener {
fun onLoaded(url: String)
}
Pass it as an argument to your function:
private fun getNewUrl(url: String, onPageLoadedListener: OnPageLoadedListener) {
var newUrl: String
val webView = WebView(applicationContext)
webView.webViewClient = object : WebViewClient() {
override fun onPageFinished(view: WebView?, url: String?) {
super.onPageFinished(view, url)
Toast.makeText(applicationContext, "Page Loaded", Toast.LENGTH_SHORT).show()
pageUrl = url.toString()
newUrl = url.toString()
onPageLoadedListener.onLoaded(newUrl)
}
}
webView.loadUrl(url)
}
Call your function:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
getNewUrl("https://www.google.com/", object : OnPageLoadedListener {
override fun onLoaded(url: String) {
Toast.makeText(applicationContext, url, Toast.LENGTH_SHORT).show()
}
})
}

Handle Multiple Tab in Android WebView

I am making an Android browser app, I want to handle link click that has target='_blank', which will open in a new tab in normal browsers.
There is a method call onCreateWindow in WebChromeClient which is triggering when a _blank link clicked. But my question is how can I get the link URL? following code is just returning the current URL
override fun onCreateWindow(view: WebView?, isDialog: Boolean, isUserGesture: Boolean, resultMsg: Message?): Boolean {
Toast.makeText(context, view?.url, Toast.LENGTH_LONG).show()
return super.onCreateWindow(view, isDialog, isUserGesture, resultMsg)
}
Finally, I found a way to capture the link URL.
#SuppressLint("SetJavaScriptEnabled")
override fun onCreateWindow(view: WebView?, isDialog: Boolean, isUserGesture: Boolean, resultMsg: Message?): Boolean {
val newWebView = WebView(context)
addView(context, newWebView)
val transport = resultMsg?.obj as WebView.WebViewTransport
transport.webView = newWebView
val settings = newWebView.getSettings()
settings.javaScriptEnabled = true
settings.javaScriptCanOpenWindowsAutomatically = true
settings.setSupportMultipleWindows(true)
settings.useWideViewPort = false
newWebView.webViewClient = object : WebViewClient() {
override fun onPageFinished(view: WebView?, url: String?) {
super.onPageFinished(view, url)
}
override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
Toast.makeText(context, url, Toast.LENGTH_LONG).show()
super.onPageStarted(view, url, favicon)
}
}
resultMsg.sendToTarget()
return true
}
By creating a new web and adding it to the WebViewTransport, you can add a new WebViewClient to that new WebView then its easy to capture that URL from onPageStarted method.

Categories

Resources