Xamarin Not allowed to load local resource file - javascript

I have trouble with load page File.html. I want to load my map in html but emulator not shows. I got error :
" [INFO:CONSOLE(0)] "Not allowed to load local resource: file:///android_asset/HTMLPage1.html", source: data:text/html,chromewebdata (0) "
" I/chromium(11080): [INFO:CONSOLE(0)] "Not allowed to load local resource: file:///android_asset/webkit/android-weberror.png", source: data:text/html,chromewebdata (0) "
On emulator page shows "WebPage not available"
Xaml file:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:Mapaht"
x:Class="Mapaht.Mapahet">
<WebView
x:Name="webviewjava"></WebView>
</ContentPage>
Page file
public Mapahet()
{
InitializeComponent();
webviewjava.Source = "file:///android_asset/HTMLPage1.html";
}

I have trouble with load page File.html.
Doing the following steps and it works fine on my side :
XAML :
<WebView
x:Name="webviewjava"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"
/>
Interface in your PCL :
public interface IBaseUrl
{
string Get();
}
Implement this interface in Android :
[assembly: Dependency(typeof(BaseUrl_Android))]
namespace FormsWebview.Droid
{
public class BaseUrl_Android : IBaseUrl
{
public string Get()
{
return "file:///android_asset/";
}
}
}
Load local resource file in Assets folder :
public MainPage()
{
InitializeComponent();
var baseUrl = DependencyService.Get<IBaseUrl>().Get();
string Url = $"{baseUrl}local.html";
webviewjava.Source = Url;
}

You are getting the WebView before setting the Content view so the wv is probably null.
protected override void OnCreate (Bundle savedInstanceState)
{
base.OnCreate (savedInstanceState);
SetContentView (Resource.Layout.webview);
WebView wv;
wv = FindViewById<WebView>(Resource.Id.webviewjava);
wv.LoadUrl("file:///android_asset/HTMLPage1.html");
}
}
You need to have permissions in AndroidMainfest.xml file that has access to the internet:
<uses-permission android:name="android.permission.INTERNET" />

Related

How to Replace Webpage Not Available Page To Custom Page? (WEBVIEW)

I want to change page from Webpage not Available or ERR_NAME_NOT_RESOLVED
to My Page "No Internet Connection"?
and with a refresh button to back online if online or connected internet again, and if didn't connect just stay in Page No Internet Connection.
Look like a page HTML not default notif page android.
I'm using a Android Studio with Kotlin
This is MyActivity
class MainActivity : AppCompatActivity() {
internal var webView: WebView? = null
private var mCM: String? = null
private var mUM: ValueCallback<Uri>? = null
private var mUMA: ValueCallback<Array<Uri?>>? = null
//select whether you want to upload multiple files (set 'true' for yes)
private val multiple_files = false
#SuppressLint("SetJavaScriptEnabled", "WrongViewCast")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
webView = findViewById(R.id.ifView) as WebView
assert(webView != null)
val webSettings = webView!!.settings
webSettings.javaScriptEnabled = true
webSettings.allowFileAccess = true
if (Build.VERSION.SDK_INT >= 21) {
webSettings.mixedContentMode = 0
webView!!.setLayerType(View.LAYER_TYPE_HARDWARE, null)
}
else {
webView!!.setLayerType(View.LAYER_TYPE_SOFTWARE, null)
}
webView!!.webViewClient = Callback()
webView!!.loadUrl("http://xxx.xxx.xxx") //add your test web/page address here
webView!!.setWebChromeClient(object : WebChromeClient()
}
This is my code Callback
inner class Callback : WebViewClient() {
override fun onReceivedError(view: WebView, errorCode: Int, description: String, failingUrl: String) {
Toast.makeText(applicationContext, "Failed loading app!", Toast.LENGTH_SHORT).show()
}
}
For sure, my apps want load offline page where webview offline to notif the apps didn't connect internet, and connect again to the internet showing online page when webview online
Replace default WebChromeClient with your custom CustomWebviewClient as below
webView!!.setWebViewClient(object : CustomWebviewClient()
then create this custom WebViewClient
inner class CustomWebviewClient : WebViewClient() {
override fun onPageStarted(view: WebView, url: String, favicon: Bitmap) {
super.onPageStarted(view, url, favicon)
}
override fun onPageFinished(view: WebView, url: String) {
super.onPageFinished(view, url)
}
override fun onReceivedError(view: WebView, request: WebResourceRequest, error: WebResourceError) {
super.onReceivedError(view, request, error)
if (noInternetConnection()) {
loadNoInternetErrorView()
} else {
loadErrorMessageView()
}
}
}
whenever your WebView fails to load page it calls onReceivedError callback there you can show error layout. For error view you can create error layout within your layout with initial visiblity View.GONE and make it visible when error occurrs.
Changes to your XML file
<WebView
android:id="#+id/webView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<LinearLayout
android:id="#+id/error_screen"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Textview
android:id="#+id/error_msg" />
................
<ImageView
android:id=:"#+id/error_icon/>
//error view
</LinearLayout>
In loadErrorMessageView you can do this
loadErrorMessageView() {
webview.setVisibility(View.GONE);
error_screen.setVisibility(View.VISIBLE);
error_msg.setText("Some error Occurred");
}
Similarly you can do for NoInternet case maybe you can show "No internet message" than "Some error occurred" I hope this clears your doubt

Passing value from java to Javascript

I'm making an Android app using webview.
The app can print out receipts. What I want to do is when the printer is not working, alert box shows up to tell the printer isn't working, and return false to the form's onsubmit event to prevent form from being submitted.
Java code:
public class JSKicker {
#JavascriptInterface
public void callPrint(final String argumet) {
Thread thread = new Thread(new Runnable() {
public void run() {
int nRtn;
connectionNum = myPrinter.Connect("000.000.0.000");
if(connectionNum < 0){ //Printer not working
webview.post(new Runnable() {
#Override
public void run() {
String script = "alert('Printer Error'); return printer_connection = false;";
webview.evaluateJavascript(script, new ValueCallback<String>() {
#Override
// I can't figure out what to do here...
});
}
});
}else{ //Printer is working properly
connectionNum = myPrinter.SetLocale(8);
strText = argument;
nRtn = myPrinter.PrintText(strText, "SJIS");
nRtn = myPrinter.PaperFeed(64);
nRtn = myPrinter.CutPaper(1);
myPrinter.Disconnect();
}
}
});
thread.start();
}
JavaScript in header:
<script type="text/javascript">
function gate(){
jQuery.ajax({
url:'/cart_info.php',
type:'GET'
})
.done( (data) => {
window.JSKicker.callPrint(data);
})
if (printer_connection = false) {
return false;
}else{
return true;
}
}
</script>
HTML form tag:
<form method="post" id="order_form" onsubmit="return gate();">
How can I get this work?
Could you do it thru WebView.evaluateJavascript()?
https://developer.android.com/reference/android/webkit/WebView.html#evaluateJavascript(java.lang.String,%20android.webkit.ValueCallback%3Cjava.lang.String%3E)
So with that you could send simple CustomEvent to document in WebView
webView.evaluateJavascript("document.dispatchEvent(new Event('printer_error', { details: "No printer found!" }));");
and in JavaScript you can hook listener for your custom event to react.
document.addEventListener('printer_error', e => alert(e.details));
Didn't test this so might be that at least evaluateJavascript() needs callback function.
WebSocket can solve your problem.
WebSockets provide a persistent connection between a client and server that both parties can use to start sending data at any time. The client establishes a WebSocket connection through a process known as the WebSocket handshake.
Its very straight forward and easy to implement.
You can follow referrer links for more details:-
JAVA WebSocket:- WebSocket using Spring Boot, WebSocket using Simple JEE
Browser WebSocket(JavaScript):- WebSocket API
In Android ,if you want webview pass value to JavaScript.
First,you need to set the webview enable the JavaScript,
private WebView mWebView;
void onCreate(){
mWebView = findViewById(R.id.webview);
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setSupportZoom(false);
}
And ,in you want do some thing code
if(connectionNum < 0){ //Printer not working
// I need to do something here to send a message that the printer isn't working to JS.
//In thread can not use mWebView,should send message to MainThread to do
// mWebView.loadUrl("javascript:javaCall()");
Message msg = new Message();
msg.what = 1;
myHandler.sendMessage(msg);
//myHandler can be your MainThread send to here
}
And where the mWebView created in your code, be in main thread ,you can use the
Handler to deal with the message sended to here.
private Handler myHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
// this 1 is just thread send to here
if (msg.what == 1) {
//and here can do the webview UI method
mWebView.loadUrl("javascript:javaCall()");
}
}
};
the javaCall() is where you JacaScript invoke method,in javaScript you can writre like this:
<script language="javascript">
function javaCall(){
alert("Printer Error");
//other thing you can do
}
</script>
if you have problem ,you can refer to the official document.
public void loadUrl (String url)
Loads the given URL.
Also see compatibility note on evaluateJavascript(String, ValueCallback).
webview use link

Android - Error loading local js in application

I have an application which is basically a webview app. The website is based on angular js. Problem is the website takes a lot of time to start rendering. So I tried loading js from the asset folder. I used WebResourceResponse in my webviewclient
#Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
if(url.startsWith("https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.1/angular.min.js")){
return loadFromAssets(url, "angular.min.js", "application/javascript", "");
}
return null;
}
private WebResourceResponse loadFromAssets( String url,
String assetPath, String mimeType, String encoding){
AssetManager assetManager = this.activity.getAssets();
InputStream input = null;
try {
Log.d(LOG_TAG, "Loading from assets: " + assetPath);
input = assetManager.open("/" + assetPath);
WebResourceResponse response =
new WebResourceResponse(mimeType, encoding, input);
return response;
} catch (IOException e) {
Log.e("WEB-APP", "Error loading " + assetPath + " from assets: " +
e.getMessage(), e);
}
return null;
}
But I keep getting the filenotfound exception
07-26 17:19:21.662 20883-21536/com.exun.brinjal D/﹕ Loading from assets: angular.min.js
07-26 17:19:21.663 20883-21536/com.exun.brinjal E/WEB-APP﹕ Error loading angular.min.js from assets: /angular.min.js
java.io.FileNotFoundException: /angular.min.js
at android.content.res.AssetManager.openAsset(Native Method)
at android.content.res.AssetManager.open(AssetManager.java:335)
at android.content.res.AssetManager.open(AssetManager.java:309)
at com.exun.brinjal.HelloWebViewClient.loadFromAssets(HelloWebViewClient.java:85)
at com.exun.brinjal.HelloWebViewClient.shouldInterceptRequest(HelloWebViewClient.java:37)
at com.android.webview.chromium.WebViewContentsClientAdapter.shouldInterceptRequest(WebViewContentsClientAdapter.java:283)
at com.android.org.chromium.android_webview.AwContents$IoThreadClientImpl.shouldInterceptRequest(AwContents.java:244)
at dalvik.system.NativeStart.run(Native Method)
07-26 17:19:21.666 20883-21536/com.exun.brinjal D/﹕ Loading from assets: angular-route.min.js
07-26 17:19:21.669 20883-21536/com.exun.brinjal E/WEB-APP﹕ Error loading angular-route.min.js from assets: /angular-route.min.js
java.io.FileNotFoundException: /angular-route.min.js
at android.content.res.AssetManager.openAsset(Native Method)
at android.content.res.AssetManager.open(AssetManager.java:335)
at android.content.res.AssetManager.open(AssetManager.java:309)
at com.exun.brinjal.HelloWebViewClient.loadFromAssets(HelloWebViewClient.java:85)
at com.exun.brinjal.HelloWebViewClient.shouldInterceptRequest(HelloWebViewClient.java:40)
at com.android.webview.chromium.WebViewContentsClientAdapter.shouldInterceptRequest(WebViewContentsClientAdapter.java:283)
at com.android.org.chromium.android_webview.AwContents$IoThreadClientImpl.shouldInterceptRequest(AwContents.java:244)
at dalvik.system.NativeStart.run(Native Method)
I have tried to change assetManager.open("/" + assetPath); to file:/// and /assets but it doesn't help. All the js and css files I need are in the assets folder. I also want to know how will I get to load all those files also.
After some brainstorming, the answer was to remove "/" from assetManager.open("/" + assetPath);
So finally just put assetManager.open(assetPath); in the code and voila!

Android: Android 4.4.4 WebView upload image, but JavaScript check file type error

I use Android WebView to show a web server's web page in Android 4.4.4.
But at the server side, JavaScript check for the image file type fails. So I cannot upload my image.
But without changing the server side code, I can upload image successfully in iOS WebView and on desktop using the same image file.
The following is my Server side JavaScript image checker code
var check_file = function (file) {
if (file.size > 1048576 * 10) {
upload_err_hdlr(413);
return false;
}
alert("Before Check");
if (!file.type.match(/image\/(jpeg|png|gif|jpg)/)) {
alert("Check fail");
upload_err_hdlr(415);
return false;
}
alert("Check successfully");
return true;
};
after I upload the image via Android 4.4.4 WebView, it shows an alert dialog
1. Before Check
2. Check fail
The following is my Android code
public class MainActivity extends Activity {
private static final int FILE_CHOOSER_RESULT_CODE = 1;
WebView mWebView;
private ValueCallback<Uri> mUploadMessage;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mWebView = (WebView) findViewById(R.id.webview);
mWebView.setWebViewClient(new CustomWebViewClient());
mWebView.setWebChromeClient(new WebChromeClient() {
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture){
mUploadMessage = uploadMsg;
Intent intent = new Intent(Intent.ACTION_PICK,android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, FILE_CHOOSER_RESULT_CODE);
}
});
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
CookieManager.setAcceptFileSchemeCookies(true);
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptCookie(true);
mWebView.loadUrl("http://192.168.1.30:5000/dashboard");
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
if(requestCode == FILE_CHOOSER_RESULT_CODE) {
if(mUploadMessage == null)
return;
Uri result = intent == null || resultCode != RESULT_OK ? null : intent.getData();
Log.d("Ting", "after result:" + result);
mUploadMessage.onReceiveValue(result);
mUploadMessage = null;
}
}
private class CustomWebViewClient extends WebViewClient {
}
}
The Android log "Ting" shows:
02-02 11:44:14.782 12456 12456 D Ting : after result:content://media/external/images/media/12255
The Uri is content://media/external/images/media/12255
This is the uploaded fail image
Anyone has any idea?
Thanks in advance.
Eric
======================
Additional Information:
I print the file content in JavaScript.
alert(JSON.stringify(file));
And the shows
{"webkitRelativePath":"","lastModified Date":"2015-01-17T10:04:30.000Z","name":"12255","type":"","size":2369496}
It seems that the uploaded image file has no "type" attribute.
Anyone knows why?
Thanks.
it's because file type isn't supported in Mobile browsers ,
check File type Support
You can try to check the file type using Regular expression :
if((/\.(gif|jpg|jpeg|tiff|png)$/i).test("filename")) {
// the file is an image
} else {
//file type is different than (JPEG,PNG,GIF,TIFF)
}

android webview javascript not working with loadDataWithBaseUrl

I am trying to load data into android webview using
webview.loadDataWithBaseURL("", htmlcontent, "text/html", null, "");
a method returns htmlContent from a StringBuilder which populates html data.
I have enabled javascript and set webChromeClient as follows
webview.getSettings().setJavaScriptEnabled(true);
webview.setWebChromeClient(new WebChromeClient());
webview.addJavascriptInterface(new JSClass(), "Android");
my interface to javascript:
class JSClass {
public void getHTMLContent(String html)
{
Log.i(Global.TAG, "HTMLContentReceived: "+html);
}
}
and my javascript in html page:
<script type="text/javascript">
var ele = document.getElementsByClassName('test');
for(var i=0;i<ele.length;i++){
ele[i].onclick = function(){
window.Android.getHTMLContent(this.innerHTML);
}
}
</script>
but somehow the javascript is not returning any value.
It works fine with loadData(url) where url is a simple webpage in assets folder
Please help
Thanks in advance
You don't have any baseURL to use, since you're loading a dynamical generated HTML.
For this reason webview.loadData(htmlcontent, "text/html", null); should be more than enough.
Javascripts don't throw any exceptions in Java code. Remember that JS is not that type-safe/strict as Java code ... My way of doing is to put logs between sensitive Javascript calls to see if that line passes and to check values. Since you didn't provide the HTML, I would setup the WebChomeClient and override the onConsoleMessage:
webview.setWebChromeClient(new MyChromeClient());
private class MyChromeClient extends WebChromeClient {
#Override
public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
String message = consoleMessage.message() + " -- line " + consoleMessage.lineNumber();
switch (consoleMessage.messageLevel()) {
case ERROR:
logErrorMessage(message);
break;
default:
logInfoMessage(message);
break;
}
return true;
}
private void logInfoMessage(String message) {
Log.i("JSTag", message);
}
private void logErrorMessage(String message) {
Log.e("JSTag", message);
}
}
From your JavaScript you would then call for example: console.log('check my value:' + (ele != null)). More info on this here.
Looking at your JavaScript code, I can't understand to what points this.innerHTML.

Categories