how to set setjavascriptenabled in android webview using kotlin - android

I am new in Kotlin, and while working on a WebView app. I found
val webSettings = mWebView.settings
webSettings.javaScriptEnabled = true
2.mWebView.getSettings().setJavaScriptEnabled(true)
1 and 2 are Kotlin statements
What is the difference between these? which one is better to use?
There is no detail explanation about these.

There is no difference between both.
Kotlin supports property access syntax, which means if you have declared one variable in Kotlin, it'll have it's getters & setters by default (No need to declare explicitly).
You can also access getters & setters by accessing variable directly,
So, acessing setter method in kotlin :
mWebView.getSettings().setJavaScriptEnabled(true)
be like this if using property access syntax,
webSettings.javaScriptEnabled = true
More from here
Conclusion:
Simply,
if you assign variable in kotlin -> it will treated as setter
for that (in your case)
if you access variable in kotlin -> it will treated as getter
for that

First it will not different between writing a statement in android with java or kotlin .. both will make the same effect.
For using webSetting there is no different between both ..
but most of tutorials use the first one to get the Websetting object one then modify at as they want to enable or disable any webview setting instead of calling getSetting object every time they need it.
You can read more about Webiew in android from this article.
https://www.oreilly.com/library/view/building-hybrid-android/9781449361907/ch04.html

Related

Why does kotlin change method invocation by variable name

If I write in Android Studio in a kotlin file getPackageManager this is automatically changed to "packageManager" in cursive, why does this happen and why should somebody think that this is straightforward to understand?
If I write in Android Studio in a kotlin file getPackageManager this is automatically changed to "packageManager" in cursive, why does this happen
getPackageManager() is a method written in Java. By convention, a method starting with get in Java is considered a field accessor. In Kotlin fields are accessed through properties. When inter-opting with Java, Kotlin automatically converts the Java way of accessing properties with the Kotlin way. This makes your code consistently "Kotliny" even if you're accessing Java classes.
Why should somebody think that this is straightforward to understand?
Because - like the syntax in the Kotlin language itself - once you know how it works, it's straightforward to understand. This goes for most things one learns. Why would someone think this is not straightforward to understand?
So, it means you could understand the cursive stuff like an alias? because normally what you write in a file is something that exists, if you write getPackageManager this exists somewhere, if you write the name of a variable this exists somewhere, but in this case packageManager doesn't really exist
Well, it does exist because the compiler makes it exist, otherwise it wouldn't compile, would it? It's just syntactic sugar. You see packageManager (so that - again - your code looks more like Kotlin). Meanwhile the compiler sees getPackageManager(). Either way it refers to the same thing.
Hope that helps!
By default all the variables are private and their getter and setter are generated by the compilers, when you pick some value it is changed to getter or when you assign value it is changed to setter call by compiler.
class Obj(var variable = "Default Value")
val obj = Obj()
obj.variable // same as obj.getVariable()
obj.variable = "Hello" // same as obj.setVariable("Hello")
Reference: https://kotlinlang.org/docs/reference/java-interop.html#getters-and-setters

Unexpected implicit cast to CharSequence: layout tag was TextView

Android Studio shows the error
Unexpected implicit cast to CharSequence: layout tag was TextView
at this code
findViewById<TextView>(R.id.tv_name).text = "text"
If I write
(findViewById<TextView>(R.id.tv_name) as TextView).text = "text"
Everything is fine.
The question is why this happens? Doesn't findViewById<TextView> already have type TextView?
You can use Kotlin Android Extensions
Kotlin Android Extensions are Kotlin plugin that will allow to recover views from Activities, Fragments and Views in an amazing seamless way.
you can directly use
tv_name.text = "text"
no need of findViewById
Reference
https://antonioleiva.com/kotlin-android-extensions/
You can directly use all the views using DataBinding. Less code and very advance feature of android. There are many articles for Android DataBinding.
https://developer.android.com/topic/libraries/data-binding/index.html
This is only warning of lint. You can ignore it with #SuppressLint("WrongViewCast"). This happend because of usage of generic types from Java in Kotlin.
First of, Kotlin under the hood, just wraps up java findViewById method. Up to API 26 explicit cast was neccessary as method returned View, but now it returns . Check this answer No need to cast the result of findViewById?
If you dive into the source code, through invokations of findViewById, you'll get to Window.findViewById method, and if you look to description of it in documentation, you'll see one note there, which says that: "In most cases -- depending on compiler support -- the resulting view is automatically cast to the target class type. If the target class type is unconstrained, an explicit cast may be necessary." https://developer.android.com/reference/android/view/Window.html#findViewById(int)
I don't know what "unconstrained" actually means in this context, but as i understand, in some cases cast is required in others is not, so just deal with it. For example, i tried to add some param to ImageView and compiler didn't show any kind of warnings:
findViewById<ImageView>(R.id.iv).adjustViewBounds = true

Kotlin's Android Extensions and variables

Before Kotlin, Android developers supposed to save reference to the Activity's Views in a variable like this:
Button fooBtn = (Button) findViewById(R.id.btn_foo)
to reduce the amount of the boiler-plate code and the number of findViewById calls.
With the introduction of the Kotlin's Android Extensions we can reference the same Button by simply using:
btn_foo
Questions:
Does the btn_foo have a reference to the Button saved, or does it call findViewById every time?
Do developers still suppose to use variables to store btn_foo to improve app's performance, or just use it directly in the code?
Edit: there is an explanation how Extensions work, however it is still a bit unclear.
It's cached, so findViewById isn't called every time you need it. Storing the variable won't definitely improve the app's performance
One of the Kotlin Android Extension (KAE) developers Ihor Kucherenko confirmed that:
KAE will keep a reference to the view after the first call, instead of using findViewById all the time. That works only for Activities and Fragments.
KAE will not cache data and will use findViewById every time for any other element (except for an Activity/Fragment).
So in case you are going to init a ViewHolder:
class FooViewHolder(view: View): RecyclerView.ViewHolder(view) {
fun bind(day: FooItem.Day) {
btn_foo.text = day.title
}
}
Decompile into Java call will look like:
((Button)this.itemView.findViewById(R.id.btn_foo)).setText((CharSequence)day.getTitle());
which is exactly what you want to avoid.
The developers might be aware of this.
Conclusion: fill free to use KAE without any additional variables, but only for your Activitiies/Fragments.

Android Realm copyToRealmOrUpdate updates existing fields

When using copyToRealmOrUpdate it also overrides fields with existing values. I would expect it would only update the fields I gave and use the existing values for the other fields.
I saw this issue for createOrUpdateFromJson: https://github.com/realm/realm-java/issues/933
cmelchior says this:
It is impossible to tell the difference between an value not set and
it's default value, so there it should override all properties.
I wanted to create an issue with label enhancement for realm, but instead I ask it here first. Is it really impossible? Because it would be a great improvement to me.
Thanks!
Note there is difference between using Realm.copyToRealmOrupdate(RealmObject) and Realm.createOrUpdateFromJson(Json)
The answer I gave is true for copyToRealmOrUpdate() eg. you cannot tell the difference between the following in Java:
boolean bool1;
boolean bool2 = false;
It is different for JSON where you can tell if a property is missing altogether. However the current implementation doesn't work that way. We are currently in process of merging a Pull Request that actually has the behaviour you are looking for. You can follow the progress here: https://github.com/realm/realm-java/pull/1022

Javascript namespaces in Android JavascriptInterface

I am creating a javascript api for my application and I want to use namespaces in my javascript code. However I am unable to get it to work nor find any information on the issue.
Desired Functionality:
HTML:
<script>
Android.typeOne.methodName();
Android.typeTwo.methodName();
</script>
Java Code:
webView.addJavascriptInterface(new TypeOneInterface(context), "Android.typeOne");
webView.addJavascriptInterface(new TypeTwoInterface(context), "Android.typeTwo");
However this never works, if I remove .typeOne and have: Android.methodName then that works fine.
I'm looking at the documentation of addJavascriptInterface. It says that The Java object's fields are not accessible. Since typeOne would have to be a property on the exported Java Object, it seems you would need to arrange the "namespace" by hand. That is, export TypeOne and put it in the global JavaScript Android object.
So I'm guessing you need to create empty objects, and put stuff in them as needed.
<script>
// after stuff has been "injected into the JS context of the main frame"
Android = {};
Android.typeOne = window.TypeOne;
... and
webView.addJavascriptInterface(new TypeOneInterface(context), "TypeOne");
This answer is a guess, I have never used JavaScript in a WebView.
I think that javascript understand that you are calling methodeName on object typeOne that is a child of object Android. But you don't have any object named Android nor typeOne.
The dot in javascript is used for hierarchy betweens parents and child.
You should try to use name without dots or, call your object differently (perhaps window["Android.typeOne"].methodName();

Categories

Resources