Android injects a JS interface into a web view:
JavaScriptInterface javaScriptInterface = new JavaScriptInterface(this);
browser.addJavascriptInterface(javaScriptInterface, "qp");
The interface looks like this:
public class JavaScriptInterface {
private ILoadEpi iLoadEpi;
public JavaScriptInterface(ILoadEpi iLoadEpi) {
this.iLoadEpi = iLoadEpi;
}
#JavascriptInterface
public void passParameters(String fldMerchCode,
String fldMerchRefNbr,
String fldTxnAmt,
String fldTxnScAmt,
String fldDatTimeTxn,
String fldDate1,
String fldDate2
) {
Log.d("fldMerchCode", fldMerchCode);
Log.d("fldMerchRefNbr", fldMerchRefNbr);
Log.d("fldTxnAmt", fldTxnAmt);
Log.d("fldTxnScAmt", fldTxnScAmt);
Log.d("fldDatTimeTxn", fldDatTimeTxn);
Log.d("fldDate1", fldDate1);
Log.d("fldDate2", fldDate2);
iLoadEpi.loadEpi(fldMerchCode, fldMerchRefNbr, fldTxnAmt, fldTxnScAmt, fldDatTimeTxn, fldDate1, fldDate2);
}
}
How can a web app developed using TypeScript call this Android?
Or more broadly, how can a TypeScript application call an Android method?
Add a TypeScript definition for the JavaScriptInterface type that will be injected by Android. Then declare a variable with the name of the instance injected by Android, then use it as normal. In your example, the definition you need is:
interface JavaScriptInterface {
passParameters(fldMerchCode: string,
fldMerchRefNbr: string,
fldTxnAmt: string,
fldTxnScAmt: string,
fldDatTimeTxn: string,
fldDate1: string,
fldDate2: string) : void;
}
declare var qp: JavaScriptInterface;
The qp instance injected by Android will have the method passParameters available on it. The instance is created by Android with the name qp in your call to browser.addJavaScriptInterface(javaScriptInterface, "qp");. Note that, depending on how your passParameters function is used, you may need to declare the return type as any instead of void.
Here's a complete example based on the Android guide for binding JS:
In your HTML file, add:
<input type="button" value="Say hello" id ="button"/>
<script src="./generated/bundle.js"></script>
where I assume that your generated/transpiled JavaScript is located at ./generated/bundle.js, relative to the HTML file.
In your TypeScript file, add:
interface WebAppInterface {
showToast(toast: string) : any;
}
declare var android: WebAppInterface;
var button = document.getElementById('button');
button.onclick = ()=>android.showToast('Hello Android!');
Note that the linked Android example names the injected object android:
webView.addJavascriptInterface(new WebAppInterface(this), "android");
And in case the linked example changes or disappears, here is the example WebAppInterface.java:
public class WebAppInterface {
Context mContext;
/** Instantiate the interface and set the context */
WebAppInterface(Context c) {
mContext = c;
}
/** Show a toast from the web page */
#JavascriptInterface
public void showToast(String toast) {
Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show();
}
}
Related
I want to pass a Java class as argument to a Java method.
The method is getKeySpec() of class java.security.KeyFactory:
getKeySpec(Key key, Class<T> keySpec)
The NativeScript Typings for this method is
public getKeySpec(param0: java.security.Key, param1: java.lang.Class<any>): java.security.spec.KeySpec;
How do I pass a java.lang.Class<any> to this method?
I want to pass java.security.spec.X509EncodedKeySpec.
This is my current TypeScript code, which fails at the getKeySpec() call.
function getPublicKey(keyPair: java.security.KeyPair): string {
const kf = java.security.KeyFactory.getInstance("RSA");
let pubKeySpec = kf.getKeySpec(keyPair.getPublic(), java.security.spec.X509EncodedKeySpec);
return pubKeySpec.getEncoded();
}
Like
let pubKeySpec = kf.getKeySpec(keyPair.getPublic(), X509EncodedKeySpec.class);
My application has a webview calling an url and basically all the stuff will be done by the website, but after the user finishes the proccess, it will send an information for the app, like success or invalid.
I want to know how to catch this return value through the webview. Is there a way to do this?
thanks.
You should use a JavascriptInterface to expose one of your Java methods to Javascript on your website.
First, create a class to act as your interface. Any methods you want to expose to Javascript need the #JavascriptInterface annotation:
class MyJavaScriptInterface{
#JavascriptInterface
public void myMethod(boolean success){
//Do something with value
}
}
Then initialize the interface on your WebView:
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.addJavascriptInterface(new MyJavaScriptInterface(), "JSInterface");
Finally, create the Javascript function to call the Java method from your website:
<script>
//Communicate with Javascript Interface
var processComplete = function(success){
//Only call if the interface exists
if(window.JSInterface){
window.JSInterface.myMethod(success);
}
};
</script>
I have this webview:
<textarea name="text" id="textPage" class="text_area"></textarea>
<script language="javascript" charset="utf-8">
//call some method of javascript.
</script>
Is it possible to set text to textarea and get text from textarea.
Set/get data from id(if any method possible) will be appreciated.
After many research i found solution, it might useful in future:
Set Data:
Android:
webView.loadUrl("javascript:setData()");
JS:
function setData(){
//js code
}
Get Data:
Android:
JavascriptInterface jsInterface = new JavascriptInterface(MainActivity.this);
converterWeb.addJavascriptInterface(jsInterface, "Android");//android is a tag.
class:
public class JavascriptInterface {
Context mContext;
JavascriptInterface(Context c) {
mContext = c;
}
public boolean getData(String name) {
Toast.makeText(mContext, "Text: "+name, Toast.LENGTH_SHORT).show();
return true;
}
}
JS:
Android.convertedText(value);//send data in tag.
better option still welcome.
I was wondering if there are any best practice tips for sending custom android intents from QML (or c++ for that matter).
should I create a custom android activity and use the QAndroidJniObject class to call it or are there any better ways?
My intention is to create a simple share URL function from QML to other android apps.
thanks
Extend QtActivity with additional static method:
package org.whatever
public class YourActivity extends org.qtproject.qt5.android.bindings.QtActivity
{
private static YourActivity instance;
YourActivity() {
instance = this;
}
public static void shareUrl(QString url) {
//create intent here
//can use instance object
}
}
On c++ side call shareUrl method using QAndroidJniObject
class QmlInterface : public QObject
{
Q_OBJECT
public:
QmlInterface();
Q_INVOKABLE void shareUrl( QString url );
};
and implementation:
void QmlInterface:: shareUrl( QString url )
{
#ifdef Q_OS_ANDROID
QAndroidJniObject::callStaticMethod( "org/whatever/YourActivity",
"shareUrl",
"(Ljava/lang/String;)V",
QAndroidJniObject::fromString( url ));
#endif
}
Using static method on java side simplifies jni call significantly because you don't have to get Activity instance. Because Activity context is needed to send Intent static instance member object is used on java side.
I am working on an e-learning project using SCROM APIs, but now I got stuck at one point: how to get server-side JavaScript value in my core Android activity IN WEBVIEW from scrom API?
I am trying below code:
public class MyJavaScriptInterface
{ Context mContext;
/** Instantiate the interface and set the context */
MyJavaScriptInterface(Context c) {
mContext = c;
}
/** retrieve the ids */
public void getbookmark(final String bookmarkId) {
webView.loadUrl("javascript:Android.getbookmark(BOOKMARKED_PAGE);");
//getWindow().requestFeature();
}
#SuppressWarnings("unused")
public void showHTML(String html)
{
new AlertDialog.Builder(myApp)
.setTitle("HTML")
.setMessage(html)
.setPositiveButton(android.R.string.ok, null)
.setCancelable(false)
.create()
.show();
}
}
Do I have to take the value of onpagefinished() function of WebView?
You'll want to add a javascript interface:
mWebView.addJavascriptInterface(new MyJavaScriptInterface(getApplicationContent(), "JSInterface");
Add a method in your interface you want to call and ensure you have the #JavascriptInterface annotation so Android makes it callable:
#JavascriptInterface
public void showHTML(String html)
{
new AlertDialog.Builder(myApp)
.setTitle("HTML")
.setMessage(html)
.setPositiveButton(android.R.string.ok, null)
.setCancelable(false)
.create()
.show();
}
Then follow the approach you are doing at the moment of calling a method in javascript:
webView.loadUrl("javascript:Android.getbookmark(BOOKMARKED_PAGE);");
And the javascript method would look something like:
window.Android.getbookmark = function(variable) {
var returnValue = getSomeValue(variable);
if(!window.JSInterface) {
console.error('window.JSInterface not defined - Did you inject the javascript interface in the native app?');
}
window.JSInterface.showHTML(returnValue);
};
Notice the reason we have window.JSInterface is because we added it with that name in:
mWebView.addJavascriptInterface(new MyJavaScriptInterface(getApplicationContent(), "JSInterface");
NOTE: In KitKat it is more efficient to use evaluateJavascript() than loadUrl, simplest form shown below, allow you can pass in a callback to get a return value (Demo in the sample code)
webView.evaluateJavascript("Android.getbookmark(BOOKMARKED_PAGE);", null);
There is a full JS Interface sample here which includes the new API's in KitKat: https://github.com/GoogleChrome/chromium-webview-samples
you can use javascript bridge for your requirement
you can find the source , this too