Я хочу получить возвращаемое значение из Javascript в Android. Я могу сделать это с iPhone, но не с Android. Я использовал loadUrl, но он вернул void вместо объекта. Кто-нибудь может мне помочь?
83
То же, Keith
но более короткий ответ
webView.addJavascriptInterface(this, "android");
webView.loadUrl("javascript:android.onData(functionThatReturnsSomething)");
И реализуем функцию
@JavascriptInterface
public void onData(String value) {
//.. do something with the data
}
Не забудьте удалить onData
из proguard
списка (если у вас включен прогард)
proguard
стороны?document.getElementById("my-div").scrollTop
получить позицию прокруткиSwipeRefreshLayout::canChildScrollUp()
. Я подозреваю, что это может быть из-за того, что звонок звонят слишком много раз за короткий период времени. илиproguard
что я подозреваю, потому что я просто не знаю, что это ..Вот как это сделать:
Добавьте этого клиента в свой WebView:
final class MyWebChromeClient extends WebChromeClient { @Override public boolean onJsAlert(WebView view, String url, String message, JsResult result) { Log.d("LogTag", message); result.confirm(); return true; } }
Теперь в вашем вызове javascript выполните:
webView.loadUrl("javascript:alert(functionThatReturnsSomething)");
Теперь в вызове onJsAlert "сообщение" будет содержать возвращаемое значение.
источник
public boolean onConsoleMessage(ConsoleMessage consoleMessage)
вместо,onJsAlert
а затем в вызове javascript, который вы делаетеwebView.loadUrl("javascript:console.log(functionThatReturnsSomething)");
- таким образом вы оставляете предупреждения JS в покое.WebChromeClient.onConsoleMessage
кажется более чистым, но имейте в виду, что оно не работает с некоторыми устройствами HTC. См. Этот вопрос для получения дополнительной информации.mWebView.addJavascriptInterface(YourObject mYourObject,String yourNameForObject);
, вызывая функциюmWebView.loadUrl("javascript:yourNameForObject.yourSetterMethod(valueToSet)")
Используйте
addJavascriptInterface()
для добавления объекта Java в среду Javascript. Пусть ваш Javascript вызовет метод этого объекта Java для предоставления его «возвращаемого значения».источник
loadUrl("javascript:...")
(API Level 1-18) илиevaluateJavascript()
(API Level 19+), чтобы оценить свой собственный JavaScript в контексте загруженной в данный момент веб-страницы.Вот что я придумал сегодня. Это потокобезопасный, достаточно эффективный и позволяет синхронное выполнение Javascript из Java для Android WebView .
Работает с Android 2.2 и выше. (Требуется commons-lang, потому что мне нужны мои фрагменты кода, переданные в eval () в виде строки Javascript. Вы можете удалить эту зависимость, заключив код не в кавычки, а в
function(){}
)Сначала добавьте это в свой файл Javascript:
function evalJsForAndroid(evalJs_index, jsString) { var evalJs_result = ""; try { evalJs_result = ""+eval(jsString); } catch (e) { console.log(e); } androidInterface.processReturnValue(evalJs_index, evalJs_result); }
Затем добавьте это в свою деятельность Android:
private Handler handler = new Handler(); private final AtomicInteger evalJsIndex = new AtomicInteger(0); private final Map<Integer, String> jsReturnValues = new HashMap<Integer, String>(); private final Object jsReturnValueLock = new Object(); private WebView webView; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); webView = (WebView) findViewById(R.id.webView); webView.addJavascriptInterface(new MyJavascriptInterface(this), "androidInterface"); } public String evalJs(final String js) { final int index = evalJsIndex.incrementAndGet(); handler.post(new Runnable() { public void run() { webView.loadUrl("javascript:evalJsForAndroid(" + index + ", " + "\"" + StringEscapeUtils.escapeEcmaScript(js) + "\")"); } }); return waitForJsReturnValue(index, 10000); } private String waitForJsReturnValue(int index, int waitMs) { long start = System.currentTimeMillis(); while (true) { long elapsed = System.currentTimeMillis() - start; if (elapsed > waitMs) break; synchronized (jsReturnValueLock) { String value = jsReturnValues.remove(index); if (value != null) return value; long toWait = waitMs - (System.currentTimeMillis() - start); if (toWait > 0) try { jsReturnValueLock.wait(toWait); } catch (InterruptedException e) { break; } else break; } } Log.e("MyActivity", "Giving up; waited " + (waitMs/1000) + "sec for return value " + index); return ""; } private void processJsReturnValue(int index, String value) { synchronized (jsReturnValueLock) { jsReturnValues.put(index, value); jsReturnValueLock.notifyAll(); } } private static class MyJavascriptInterface { private MyActivity activity; public MyJavascriptInterface(MyActivity activity) { this.activity = activity; } // this annotation is required in Jelly Bean and later: @JavascriptInterface public void processReturnValue(int index, String value) { activity.processJsReturnValue(index, value); } }
источник
function(){}
? Как разместить jsString{}
?На API 19+, лучший способ сделать это , чтобы позвонить evaluateJavascript на вашем WebView:
webView.evaluateJavascript("foo.bar()", new ValueCallback<String>() { @Override public void onReceiveValue(String value) { // value is the result returned by the Javascript as JSON } });
Связанный ответ с более подробной информацией: https://stackoverflow.com/a/20377857
источник
Решение, предложенное @Felix Khazin, работает, но отсутствует один ключевой момент.
Вызов javascript должен выполняться после
WebView
загрузки веб-страницы в . Добавьте этоWebViewClient
кWebView
, наряду сWebChromeClient
.Полный пример:
@Override public void onCreate(Bundle savedInstanceState) { ... WebView webView = (WebView) findViewById(R.id.web_view); webView.getSettings().setJavaScriptEnabled(true); webView.setWebViewClient(new MyWebViewClient()); webView.setWebChromeClient(new MyWebChromeClient()); webView.loadUrl("http://example.com"); } private class MyWebViewClient extends WebViewClient { @Override public void onPageFinished (WebView view, String url){ view.loadUrl("javascript:alert(functionThatReturnsSomething())"); } @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { return false; } } private class MyWebChromeClient extends WebChromeClient { @Override public boolean onJsAlert(WebView view, String url, String message, JsResult result) { Log.d("LogTag", message); result.confirm(); return true; } }
источник
В качестве альтернативного варианта, использующего индивидуальную схему:
Основное занятие
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { WebView.setWebContentsDebuggingEnabled(true); } final WebView webview = new CustomWebView(this); setContentView(webview); webview.loadUrl("file:///android_asset/customPage.html"); webview.postDelayed(new Runnable() { @Override public void run() { //Android -> JS webview.loadUrl("javascript:showToast()"); } }, 1000); } }
CustomWebView
public class CustomWebView extends WebView { public CustomWebView(Context context) { super(context); setup(); } @SuppressLint("SetJavaScriptEnabled") private void setup() { setWebViewClient(new AdWebViewClient()); getSettings().setJavaScriptEnabled(true); } private class AdWebViewClient extends WebViewClient { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if (url.startsWith("customschema://")) { //parse uri Toast.makeText(CustomWebView.this.getContext(), "event was received", Toast.LENGTH_SHORT).show(); return true; } return false; } } }
customPage.html (находится в свернутых активах)
<!DOCTYPE html> <html> <head> <title>JavaScript View</title> <script type="text/javascript"> <!--JS -> Android--> function showToast() { window.location = "customschema://goto/"; } </script> </head> <body> </body> </html>
источник
Сделать это можно так:
[Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true)] public class MainActivity : AppCompatActivity { public WebView web_view; public static TextView textView; protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); Xamarin.Essentials.Platform.Init(this, savedInstanceState); Window.AddFlags(WindowManagerFlags.Fullscreen); Window.ClearFlags(WindowManagerFlags.ForceNotFullscreen); // Set our view from the "main" layout resource SetContentView (Resource.Layout.main); web_view = FindViewById<WebView>(Resource.Id.webView); textView = FindViewById<TextView>(Resource.Id.textView); web_view.Settings.JavaScriptEnabled = true; web_view.SetWebViewClient(new SMOSWebViewClient()); web_view.LoadUrl("https://stns.egyptair.com"); } public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults) { Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults); base.OnRequestPermissionsResult(requestCode, permissions, grantResults); } } public class SMOSWebViewClient : WebViewClient { public override bool ShouldOverrideUrlLoading(WebView view, IWebResourceRequest request) { view.LoadUrl(request.Url.ToString()); return false; } public override void OnPageFinished(WebView view, string url) { view.EvaluateJavascript("document.getElementsByClassName('notf')[0].innerHTML;", new JavascriptResult()); } } public class JavascriptResult : Java.Lang.Object, IValueCallback { public string Result; public void OnReceiveValue(Java.Lang.Object result) { string json = ((Java.Lang.String)result).ToString(); Result = json; MainActivity.textView.Text = Result.Replace("\"", string.Empty); } }
источник