英文:
Unable to run javascipt in android
问题
我正在尝试从Android应用程序将URL作为输入传递给JavaScript脚本,并期望从脚本中以字符串形式收到true或false值作为返回。当单独运行JavaScript代码时,它可以正常工作,但当与Android应用程序集成时,我没有从脚本中收到任何数据。不确定JavaScript代码是否在Android环境中正确执行。
public void linkValidation(String url) {
textStatus.setTextColor(ContextCompat.getColor(MainActivity.this, R.color.white));
textStatus.setText(getString(R.string.validating_link));
Pattern profileLinkPattern = Pattern.compile("^https://www.threads.net/@[^/]+$");
Matcher profileMatcher = profileLinkPattern.matcher(url);
if (url.startsWith("https://www.threads.net") || url.startsWith("https://threads.net")) {
if (profileMatcher.matches()) {
textStatus.setText(null);
textStatus.setText(getString(R.string.profile_link));
} else if (url.contains("/post/") || url.contains("threads.net/t/")) {
textStatus.setText(null);
runJavaScriptInWebView(url, result -> {
textStatus.setText(result);
// Show the result as a Toast message
Toast.makeText(MainActivity.this, "Result: " + result, Toast.LENGTH_LONG).show();
});
} else {
textStatus.setText(null);
textStatus.setTextColor(ContextCompat.getColor(MainActivity.this, R.color.orange));
textStatus.setText(getString(R.string.threadlink_invaliddataurl));
}
} else if (((!url.startsWith("https://")) && (url.contains("www.threads.net"))) || ((!url.startsWith("https://") && (url.contains("https://threads.net"))))) {
textStatus.setText(null);
textStatus.setTextColor(ContextCompat.getColor(MainActivity.this, R.color.orange));
textStatus.setText(getString(R.string.threadLink_NoHttps));
} else {
Toast.makeText(MainActivity.this, "Invalid Url", Toast.LENGTH_SHORT).show();
textStatus.setText(null);
textStatus.setTextColor(ContextCompat.getColor(MainActivity.this, R.color.orange));
textStatus.setText(getString(R.string.threadLink_False));
}
}
private void runJavaScriptInWebView(String url, final JavaScriptCallback callback) {
WebView webView = new WebView(getApplicationContext());
webView.getSettings().setJavaScriptEnabled(true);
class JavaScriptInterface {
@JavascriptInterface
public void processResult(String result) {
callback.onResult(result);
}
}
webView.addJavascriptInterface(new JavaScriptInterface(), "androidJSInterface");
webView.setWebChromeClient(new WebChromeClient() {
@Override
public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
Log.d("JavaScriptConsole", consoleMessage.message());
return true;
}
});
String jsCode = "function evaluatePage(url) {" +
" let foundNot = null;" +
" try {" +
" const svgElements = document.querySelector('[aria-hidden=\"true\"][fill=\"none\"]');" +
" if (svgElements) {" +
" foundNot = 'true';" +
" console.log(foundNot);" +
" } else {" +
" foundNot = 'false';" +
" console.log(foundNot);" +
" }" +
" window.androidJSInterface.processResult(foundNot);" +
" } catch (error) {" +
" console.error('Error:', error);" +
" }" +
"}" +
"evaluatePage('" + url + "');";
String htmlContent = "<html><head><script>" + jsCode + "</script></head><body></body></html>";
webView.setWebViewClient(new WebViewClient() {
@Override
public void onPageFinished(WebView view, String url) {
// Handle the result here or in the JavaScriptInterface's processResult method
}
});
webView.loadData(htmlContent, "text/html", "UTF-8");
}
private interface JavaScriptCallback {
void onResult(String result);
}
这是您提供的Java代码的翻译部分。
英文:
I am attempting to pass a URL as input to a JavaScript script from an Android application and expect to receive a true or false value as a string in return from the script. The JavaScript code works fine when run independently, but when integrated with the Android app, I'm not receiving any data from the script. It's uncertain whether the JavaScript code is even executing properly within the Android environment.
public void linkValidation(String url) {
textStatus.setTextColor(ContextCompat.getColor(MainActivity.this, R.color.white));
textStatus.setText(getString(R.string.validating_link));
// Toast.makeText(MainActivity.this, url, Toast.LENGTH_SHORT).show();
// Regex pattern for profile link
Pattern profileLinkPattern = Pattern.compile("^https://www.threads.net/@[^/]+$");
// Regex pattern for post link
// Pattern postWithNoHttps = Pattern.compile("^(?!https:\\/\\/)(.*(?:www\\.)?threads\\.net).*");
// Matcher postWithNoHTTPS_Matcher = postWithNoHttps.matcher(url);
Matcher profileMatcher = profileLinkPattern.matcher(url);
if (url.startsWith("https://www.threads.net") || url.startsWith("https://threads.net")) {
// Toast.makeText(MainActivity.this, "Checked", Toast.LENGTH_SHORT).show();
if (profileMatcher.matches()) {
textStatus.setText(null);
textStatus.setText(getString(R.string.profile_link));
} else if (url.contains("/post/") || url.contains("threads.net/t/")) {
textStatus.setText(null);
// Call the method to run JavaScript in the WebView with the URL
runJavaScriptInWebView(url, result -> {
// Here, 'result' will contain the value of 'foundNot' from JavaScript
textStatus.setText(result);
// Show the result as a Toast message
Toast.makeText(MainActivity.this, "Result: " + result, Toast.LENGTH_LONG).show();
});
} else {
textStatus.setText(null);
textStatus.setTextColor(ContextCompat.getColor(MainActivity.this, R.color.orange));
textStatus.setText(getString(R.string.threadlink_invaliddataurl));
}
} else if (((!url.startsWith("https://")) && (url.contains("www.threads.net"))) || ((!url.startsWith("https://") && (url.contains("https://threads.net"))))) {
textStatus.setText(null);
textStatus.setTextColor(ContextCompat.getColor(MainActivity.this, R.color.orange));
textStatus.setText(getString(R.string.threadLink_NoHttps));
} else {
Toast.makeText(MainActivity.this, "Invailed Url", Toast.LENGTH_SHORT).show();
textStatus.setText(null);
textStatus.setTextColor(ContextCompat.getColor(MainActivity.this, R.color.orange));
textStatus.setText(getString(R.string.threadLink_False));
}
}
private void runJavaScriptInWebView(String url, final JavaScriptCallback callback) {
WebView webView = new WebView(getApplicationContext());
webView.getSettings().setJavaScriptEnabled(true);
// WebView JavaScript interface to receive the result
class JavaScriptInterface {
@JavascriptInterface
public void processResult(String result) {
// Call the callback with the result
callback.onResult(result);
}
}
// Set the JavaScript interface
webView.addJavascriptInterface(new JavaScriptInterface(), "androidJSInterface");
// Set a custom WebChromeClient to capture console logs
webView.setWebChromeClient(new WebChromeClient() {
@Override
public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
// Log the console message to Logcat
Log.d("JavaScriptConsole", consoleMessage.message());
return true;
}
});
// Load the HTML content with JavaScript code in the WebView
String jsCode = "function evaluatePage(url) {" +
" let foundNot = null;" +
" try {" +
" const svgElements = document.querySelector('[aria-hidden=\"true\"][fill=\"none\"]');" +
" if (svgElements) {" +
" foundNot = 'true';" +
" console.log(foundNot);" +
" } else {" +
" foundNot = 'false';" +
" console.log(foundNot);" +
" }" +
" window.androidJSInterface.processResult(foundNot);" + // Pass the result to the JavaScript interface
" } catch (error) {" +
" console.error('Error:', error);" +
" }" +
"}" +
"evaluatePage('" + url + "');"; // Call the function immediately when the page loads
String htmlContent = "<html><head><script>" + jsCode + "</script></head><body></body></html>";
webView.setWebViewClient(new WebViewClient() {
@Override
public void onPageFinished(WebView view, String url) {
// The page is loaded, and evaluatePage() has been called
// At this point, JavaScript execution is already done, and the result is available in foundNot
// You can handle the result here or in the JavaScriptInterface's processResult method
}
});
// Load the HTML content (start JavaScript execution)
webView.loadData(htmlContent, "text/html", "UTF-8");
}
private interface JavaScriptCallback {
void onResult(String result);
}
答案1
得分: 1
我建议尝试使用 Javascript Engine androidx package 来评估JavaScript代码的目的。
以下是显示如何使用它的文档示例:
https://developer.android.com/develop/ui/views/layout/webapps/jsengine
这不仅是解决方案,也是性能更好的选择,因为它不会创建完整的WebView。
Jetpack库JavaScriptEngine提供了一种在不创建WebView实例的情况下应用程序评估JavaScript代码的方法。
对于需要非交互式JavaScript评估的应用程序,使用JavaScript引擎库具有以下优势:
- 低资源消耗,因为无需分配WebView实例。
- 可以在服务中执行(WorkManager任务)。
- 低开销的多个隔离环境,使应用程序能够同时运行多个JavaScript代码片段。
- 通过使用API调用传递大量数据。
英文:
Looking at the purpose why you want to evaluate JavaScript code, I suggest to trying out the Javascript Engine androidx package.
Here is the documentation that shows you some examples how to use it:
https://developer.android.com/develop/ui/views/layout/webapps/jsengine
It's not just a solution and simplification for your problem, but it is also better for performance since it won't create an entire WebView.
> Jetpack library JavaScriptEngine provides a way for an application to
> evaluate JavaScript code without creating a WebView instance.
>
> For applications requiring non-interactive JavaScript evaluation,
> using the JavaScript engine library has the following advantages:
>
> - Lower resource consumption, since there is no need to allocate a
> WebView instance.
>
> - Can be done in a Service (WorkManager task).
>
> - Multiple isolated environments with low overhead, enabling the
> application to run several JavaScript snippets simultaneously.
>
> - Ability to pass large amounts of data by using an API call.
答案2
得分: 0
问题可能是由于缺少Android权限引起的。您的Android应用程序是否具有访问互联网的必要权限?
在您的AndroidManifest.xml文件中,尝试包含以下权限:
<uses-permission android:name="android.permission.INTERNET"/>
英文:
The issue is probably caused by missing Android Permissions. Does your Android application have the necessary permissions to access the internet?
In your AndroidManifest.xml file, try including the following permission:
<uses-permission android:name="android.permission.INTERNET"/>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论