I have a game made with unity on itch.io I want to open and play this game in my custom android app webview.
For this I'm using.
myWebView.loadUrl("https://teamwood.itch.io/super-auto-pets")
myWebView.settings.javaScriptEnabled = true
Url is being load but on tapping Run Game nothing happen. Can I even perform this in webview
Itch.io supports fullscreen webgl games altough that games can be run in web view if It is not in full screen. For full screen mode you can follow the code like, below is the code of my Game Activity code Which consists simply a web view.
package com.example.game
import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.os.Bundle
import android.view.View
import android.webkit.WebChromeClient
import android.webkit.WebView
import android.webkit.WebViewClient
import android.widget.FrameLayout
import androidx.appcompat.app.AppCompatActivity
class GameActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_game)
val webView: WebView = findViewById(R.id.gameView)
webView.settings.javaScriptEnabled = true
supportActionBar?.hide()
webView.webViewClient= MyBrowser()
webView.webChromeClient = MyWebClient(this#GameActivity.applicationContext,this#GameActivity)
webView.loadUrl("https://teamwood.itch.io/super-auto-pets")
}
internal class MyBrowser : WebViewClient() {
override fun shouldOverrideUrlLoading(paramWebView: WebView, paramString: String): Boolean {
paramWebView.loadUrl(paramString)
return true
}
}
}
open class MyWebClient(private val context: Context,private val activity: GameActivity) : WebChromeClient() {
private var mCustomView: View? = null
private var mCustomViewCallback: CustomViewCallback? = null
protected var mFullscreenContainer: FrameLayout? = null
private var mOriginalOrientation = 0
private var mOriginalSystemUiVisibility = 0
override fun getDefaultVideoPoster(): Bitmap? {
return if (this == null) {
null
} else BitmapFactory.decodeResource(
context.resources, 2130837573
)
}
override fun onHideCustomView() {
(activity.window.decorView as FrameLayout).removeView(mCustomView)
mCustomView = null
activity.window.decorView.systemUiVisibility = mOriginalSystemUiVisibility
activity.requestedOrientation = mOriginalOrientation
mCustomViewCallback!!.onCustomViewHidden()
mCustomViewCallback = null
}
override fun onShowCustomView(
paramView: View?,
paramCustomViewCallback: CustomViewCallback?
) {
if (mCustomView != null) {
onHideCustomView()
return
}
mCustomView = paramView
mOriginalSystemUiVisibility =
activity.window.decorView.systemUiVisibility
mOriginalOrientation = activity.requestedOrientation
mCustomViewCallback = paramCustomViewCallback
(activity.window.decorView as FrameLayout).addView(
mCustomView,
FrameLayout.LayoutParams(-1, -1)
)
activity.window.decorView.systemUiVisibility = 3846
}
}
Related
The error that appears is as follows "Type mismatch: inferred type is String? but String is expected". How can I solve this problem?
The source code is as follows:
package com.example.submission2.Activity
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
import com.example.submission2.Adapter.AdapterSectionPager
import com.example.submission2.ViewModel.DetailVM
import com.example.submission2.databinding.ActivityDetailBinding
class DetailActivity : AppCompatActivity() {
companion object{
const val EXTRA_USERNAME = "extra_username"
}
private lateinit var binding: ActivityDetailBinding
private lateinit var viewModel: DetailVM
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityDetailBinding.inflate(layoutInflater)
setContentView(binding.root)
supportActionBar?.apply {
setDisplayHomeAsUpEnabled(true)
setDisplayShowHomeEnabled(true)
}
val username = intent.getStringExtra(EXTRA_USERNAME)
viewModel = ViewModelProvider(this, ViewModelProvider.NewInstanceFactory()).get(DetailVM::class.java)
viewModel.setPenggunaDetail(username)
viewModel.getPenggunaDetail().observe(this) {
if (it != null) {
binding.apply {
tvNamaDetail.text = it.name
tvUsernameDetail.text = it.login
tvCompanyDetail.text = it.company
tvEmailDetail.text = it.email
tvFollowersDetail.text = "${it.followers} Followers"
tvFollowingDetail.text = "${it.following} Follwing"
Glide.with(this#DetailActivity)
.load(it.avatar_url)
.transition(DrawableTransitionOptions.withCrossFade())
.centerCrop()
.into(ivDetailProfil)
}
}
}
val sectionPagerAdpter = AdapterSectionPager(this,supportFragmentManager)
binding.apply {
viewPager.adapter = sectionPagerAdpter
tabs.setupWithViewPager(viewPager)
}
}
}
error appears on the line "viewModel.set User Data(username)" username is used in extra_username which will be called in main
for main activity as follows:
package com.example.submission2.Activity
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.KeyEvent
import android.view.View
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.submission2.Adapter.AdapterPengguna
import com.example.submission2.DataBase.Pengguna
import com.example.submission2.R
import com.example.submission2.ViewModel.MainVM
import com.example.submission2.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var viewModel: MainVM
private lateinit var adapter: AdapterPengguna
private fun searchPengguna(){
binding.apply {
val query = etSearch.text.toString()
if (query.isEmpty())return
showLoading(true)
viewModel.setSearchPengguna(query)
}
}
private fun showLoading(state: Boolean){
if (state){
binding.progressBarMain.visibility = View.VISIBLE
}else{
binding.progressBarMain.visibility = View.GONE
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
adapter = AdapterPengguna()
adapter.notifyDataSetChanged()
adapter.setOnItemClickCallback(object :AdapterPengguna.OnItemClickCallback{
override fun onItemCliked(data: Pengguna) {
Intent(this#MainActivity,DetailActivity::class.java).also {
it.putExtra(DetailActivity.EXTRA_USERNAME, data.login)
startActivity(it)
}
}
})
viewModel = ViewModelProvider(this,ViewModelProvider.NewInstanceFactory()).get(MainVM::class.java)
binding.apply {
rvPengguna.layoutManager = LinearLayoutManager(this#MainActivity)
rvPengguna.setHasFixedSize(true)
rvPengguna.adapter = adapter
btnSearch.setOnClickListener {
searchPengguna()
}
etSearch.setOnKeyListener { v, keyCode, event ->
if (event.action == KeyEvent.ACTION_DOWN && keyCode == KeyEvent.KEYCODE_ENTER){
searchPengguna()
return#setOnKeyListener true
}
return#setOnKeyListener false
}
}
viewModel.getSearchPengguna().observe(this,{
if (it!= null){
adapter.setList(it)
showLoading(false
)
}
})
}
}
In your code there is no such line as viewModel.setUserData
I guess that the error occurs in the line viewModel.setPenggunaDetail(username)
In this case, you should pay attention to the fact that the all intent.getExtra calls returns nullable values.
Thus, if the setPenggunaDetail call expects a non-nullable argument, you must first check username value for null
(Sorry for my poor English)
I have a web page which set a local storage value like localStorage.setItem('name', 'myName') , I load this web page inside a webView and I want to access to this local storage value inside the android app so I used below code but it returns "null", it takes half a day but i can't fix it, I'm not android developer so explain me a little more please.
package com.example.myWebViewApp
import android.os.Bundle
import android.os.Handler
import android.util.Log
import android.webkit.ValueCallback
import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.appcompat.app.AppCompatActivity
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val myWebView: WebView = findViewById(R.id.webview)
val webSettings = myWebView.settings
webSettings.javaScriptEnabled = true
webSettings.javaScriptCanOpenWindowsAutomatically = true
webSettings.allowFileAccess = true
webSettings.allowContentAccess = true
webSettings.domStorageEnabled = true
webSettings.textZoom = 100
webSettings.allowFileAccess = true
myWebView.loadUrl("http://192.168.1.99:3333")
myWebView.webViewClient = object : WebViewClient() {
override fun onPageFinished(view: WebView, url: String) {
myWebView.evaluateJavascript(
"window.localStorage.getItem('name');",
ValueCallback<String?> {
n -> run { Log.d("nameTag", "$n") }
}
)
}
}
val refreshLayout = findViewById<SwipeRefreshLayout>(R.id.swipeRefresher)
refreshLayout.setOnRefreshListener {
refreshLayout.isRefreshing = true
Handler().postDelayed(Runnable {
refreshLayout.isRefreshing = false
myWebView.reload()
}, 2000)
}
}
}
I am creating a simple application for my android tv box, which uses a webview object to show some streaming urls and choose beetween them with PGup and PGdown of a remote control (an hardware keyboard).
I am overriding method onKeyUp, but unfortunately my app seem not to detect any key press.
This is some code excerpt:
package com.dm.tutorialwebview
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.view.KeyEvent
import android.view.Menu
import android.webkit.WebChromeClient
import android.webkit.WebView
import android.webkit.WebViewClient
import android.util.Log
import android.view.MotionEvent
class MainActivity : AppCompatActivity() {
var webview: WebView? = null
data class Channel(val number: Int, val name:String, val url: String )
object ChannelList {
private val list = mutableListOf<Channel>()
private var curChannel: Int = 0
[..]
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
ChannelList.addItem(Channel(1,"channel1","https://...3"))
ChannelList.addItem(Channel(2,"channel2","https://..."))
ChannelList.addItem(Channel(3,"channel3","https://..."))
webview = findViewById(R.id.myweb)
webview!!.webViewClient = WebViewClient()
webview!!.settings.javaScriptEnabled = false
webview!!.webChromeClient = WebChromeClient()
webview!!.settings.domStorageEnabled = true
webview!!.settings.builtInZoomControls = false
webview!!.settings.setSupportZoom(false)
webview!!.overScrollMode = WebView.OVER_SCROLL_NEVER
webview!!.settings.useWideViewPort = true
webview!!.setInitialScale(1)
webview!!.loadUrl(ChannelList.getChannelUrl())
}
override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean {
Log.i("TAG", "onKeyUp is been called");
return when (keyCode) {
KeyEvent.KEYCODE_PAGE_UP -> {
ChannelList.nextChannel()
webview!!.loadUrl(ChannelList.getChannelUrl())
true
}
KeyEvent.KEYCODE_PAGE_DOWN -> {
ChannelList.prevChannel()
webview!!.loadUrl(ChannelList.getChannelUrl())
true
}
KeyEvent.KEYCODE_1 -> {
ChannelList.setChannel(1)
webview!!.loadUrl(ChannelList.getChannelUrl())
true
}
else -> super.onKeyUp(keyCode, event)
}
}
}
Method onKeyUp doesn't seem to be triggered at all.
Any hints on what could be wrong with this code?
Thanks and regards
Thanks #Ashwini-violet, I replaced onKeyUp with dispathKeyEvent.
I used a workaround to limit inputs to one every 250ms; not very polite but it's working.
var lastclick : Long = 0
var keyDelay : Int = 250
[..]
override fun dispatchKeyEvent(event: KeyEvent?): Boolean {
return when (event!!.keyCode) {
KeyEvent.KEYCODE_PAGE_UP , KeyEvent.KEYCODE_DPAD_UP -> {
if ((SystemClock.currentThreadTimeMillis() - lastclick) < keyDelay) true
else {
ChannelList.nextChannel()
webview!!.clearHistory()
webview!!.clearCache(true)
showChannelName()
webview!!.loadUrl(ChannelList.getChannelUrl())
lastclick = SystemClock.currentThreadTimeMillis()
true
}
}
I'm trying to use this package https://github.com/PierfrancescoSoffritti/android-youtube-player to play a youtube video. The error I'm getting is Unresolved reference: youTubePlayerView. I've never worked with fragments before so I'm not understanding what I'm doing wrong? After declaring the button in the oncreateview I could set up a listener for it fine, but for some reason after declaring the youtubePlayerView I cant use it and it results in an unresolved reference. What should I do?
here's my code:
package com.srm325.recyclertest.ui.features.receivesong
import android.net.Uri
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import com.aliakberaakash.cutiehacksproject2020.R
import com.google.android.material.button.MaterialButton
import com.pierfrancescosoffritti.androidyoutubeplayer.core.player.YouTubePlayer
import com.pierfrancescosoffritti.androidyoutubeplayer.core.player.listeners.AbstractYouTubePlayerListener
import com.pierfrancescosoffritti.androidyoutubeplayer.core.player.views.YouTubePlayerView
import kotlinx.android.synthetic.main.searchsong_layout.*
import java.io.BufferedReader
import java.io.InputStreamReader
import java.net.HttpURLConnection
import java.net.URL
import java.util.concurrent.CountDownLatch
private const val BASE_URL =
"https://www.googleapis.com/youtube/v3/search?key=AIzaSyAcqsfnhOFIyIgX1auWR-SzjcTXOoc3MDE&part=snippet,id&order=viewCount&maxResults=1&q="
class receivefragment : Fragment() {
companion object{
const val GET_FROM_GALLERY = 3
}
lateinit var videostring: String
lateinit var selectedImage:Uri
lateinit var storage: FirebaseStorage
val db = Firebase.firestore
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view: View = inflater.inflate(R.layout.receive_layout, container, false)
val youTubePlayerView: YouTubePlayerView = view.findViewById<YouTubePlayerView>(R.id.youtube_player_view)
val uploadBtn: MaterialButton = view.findViewById(R.id.uploadBtn)
return view
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
uploadBtn.setOnClickListener {
lifecycle.addObserver(youTubePlayerView)
youTubePlayerView.addYouTubePlayerListener(object : AbstractYouTubePlayerListener() {
override fun onReady(youTubePlayer: YouTubePlayer) {
var video123: String = "lOqy8cC72wA";
youTubePlayer.loadVideo(video123!!, 0f)
}
})
}
}
}
private fun requestData(urlstring: String): String? {
return try {
val response = arrayOfNulls<String>(1)
val latch = CountDownLatch(1)
Thread {
try {
Log.d("START", "Starting GET")
val url = URL(urlstring)
val connection = url.openConnection() as HttpURLConnection
connection.requestMethod = "GET"
connection.connectTimeout = 5000
connection.readTimeout = 5000
connection.connect()
Log.d("INFO", urlstring)
Log.d("INFO", Integer.toString(connection.responseCode))
Log.d("INFO", connection.responseMessage)
val rd = BufferedReader(InputStreamReader(connection.inputStream))
var content = ""
var line: String
while (rd.readLine().also { line = it } != null) {
content += """
$line
""".trimIndent()
}
response[0] = content
Log.d("SUCCESS", response[0]!!)
latch.countDown()
} catch (ex: Exception) {
Log.d("ERROR", "Error Processing Get Request...")
var i = 0
while (i < ex.stackTrace.size) {
Log.d("ERROR", ex.stackTrace[i].toString())
i++
}
latch.countDown()
}
}.start()
latch.await()
response[0]
} catch (ex: Exception) {
""
}
}
That's because you try to launch it from the fragment, not from the activity. Try to use requireActivity().youTubePlayerView instead.
I have the following Activity :
import android.graphics.Bitmap
import android.os.Bundle
import android.provider.Settings
import android.support.v7.app.AppCompatActivity
import android.util.Log
import android.webkit.WebView
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class ShowOneContactHtmlActivity : AppCompatActivity() {
private lateinit var maddress :String
private lateinit var mcontact_name : String
private lateinit var mavatar_to_str_base64: String
private lateinit var dialog: MyViewDialog
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_show_html)
val webview = findViewById<WebView>(R.id.webview)
dialog = MyViewDialog(ShowAddressessActivity#this)
dialog.showDialog()
maddress = intent.getStringExtra(SENT_ADDRESS_FROM_ADDRESSES_TO_SHOWONECONTACT_ACTIVITY)
mcontact_name = intent.getStringExtra(SENT_CONTACT_NAME_FROM_ADDRESSES_TO_SHOWONECONTACT_ACTIVITY)
val avatar = intent.getParcelableExtra<Bitmap>(SENT_BITMAP_FROM_ADDRESSES_TO_SHOWONECONTACT_ACTIVITY)
mavatar_to_str_base64 = bitmaptoStringBase64(avatar)
lateinit var htmlstring :String
GlobalScope.launch {
htmlstring = takeHtmlStringofThisContact()
withContext(Dispatchers.Main) {
webview.loadDataWithBaseURL(
"file:///android_asset/",
htmlstring,
"text/html",
"UTF-8",
""
)
dialog.hideDialog()
}
}
}
suspend private fun takeHtmlStringofThisContact():String {
lateinit var onecntcthtmlmaker: HtmlMaker
if (maddress == mcontact_name) {
onecntcthtmlmaker =
HtmlMaker(ShowOneContactHtmlActivity# this, mavatar_to_str_base64, maddress)
} else {
onecntcthtmlmaker =
HtmlMaker(
ShowOneContactHtmlActivity# this,
mavatar_to_str_base64,
mcontact_name
)
}
var smsparser = SmsParser(ShowOneContactHtmlActivity# this)
withContext(Dispatchers.Default) {
var all_messages_of_one_contact = smsparser.loadInboxAndSentOfAddress(maddress)
var sortedlist =
all_messages_of_one_contact.sortedWith(compareBy({ it.m_date_in_milli }))
for (msg in sortedlist) {
onecntcthtmlmaker.putHtmlMessageInCurrentHtml(msg)
}
onecntcthtmlmaker.clearHtmlAtLast()
}
return onecntcthtmlmaker.current_html
}
}
Rather it is unnecessary to see the whole code, my focus is on the dialog which displays a loading.gif. With this code my loading gif disappears when the loading of the url still happens.
I want the loading gif to disappears when the loading of the url has finished.
As I know (correct me if I am wrong) I have to make my WebViewClient and when onPageFinished() is executed then I have to notify the Activity and the dialog to disappear.
Is there another way ? Is there a function that is called, after the webview has stopped loading , in the activity to override it and to set there the disappearance of dialog(i.e loading gif)???
You can use WebViewClient and override onPageFinished:
webView.webViewClient = object : WebViewClient() {
override fun onPageFinished(view: WebView?, url: String?) {
// Here
}
}