I need your help the app crashes when I click the "log in" button, What have I done wrong? (The app should open a new activity with webview inside)
Thanks for answers,
I have 2 activities,
The main code:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.activity_main);
super.onCreate(savedInstanceState);
LoadPage();
}
public Button Btn;
public void LoadPage(){
Btn = (Button)findViewById(R.id.LoginBtn);
Btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, WebPage.class);
startActivity(intent);
final EditText username = (EditText) findViewById(R.id.LoginTx);
intent.putExtra("Username", username.getText().toString());
final EditText password = (EditText) findViewById(R.id.PasswordTx);
intent.putExtra("Password", password.getText().toString());
}
});
}
The WebPage activity code:
public class WebPage extends AppCompatActivity {
static WebView mWebView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final String user = getIntent().getExtras().getString("Username");
final String pwd = getIntent().getExtras().getString("Password");
setContentView(R.layout.activity_web_page);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
mWebView = (WebView) findViewById(R.id.webView2);
String url = "http://www.webnotes.cz/";
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.loadUrl(url);
mWebView.setWebViewClient(new WebViewClient() {
public void onPageFinished(WebView view, String url) {
view.loadUrl("javascript:document.getElementById('UID0').value = '" +user+ "';document.getElementById('PASS0').value='" +pwd+ "';javascript:document.getElementById('butLogon').click();");
}
});
}
}
In debug:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.erikstoklasa.test, PID: 13544
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.erikstoklasa.test/com.example.erikstoklasa.test.WebPage}: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.os.Bundle.getString(java.lang.String)' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2626)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2695)
at android.app.ActivityThread.access$800(ActivityThread.java:173)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1552)
at android.os.Handler.dispatchMessage(Handler.java:111)
at android.os.Looper.loop(Looper.java:194)
at android.app.ActivityThread.main(ActivityThread.java:5787)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1009)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:804)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.os.Bundle.getString(java.lang.String)' on a null object reference
at com.example.erikstoklasa.test.WebPage.onCreate(WebPage.java:16)
at android.app.Activity.performCreate(Activity.java:6105)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1123)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2579)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2695)
at android.app.ActivityThread.access$800(ActivityThread.java:173)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1552)
at android.os.Handler.dispatchMessage(Handler.java:111)
at android.os.Looper.loop(Looper.java:194)
at android.app.ActivityThread.main(ActivityThread.java:5787)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1009)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:804)
Related
I'm working on an android app. I want to pass some value from my webview to my android application.
I solved this problem successfully by using the solution given in Passing data from java class to Web View html.
The problem that I'm facing is when I'm trying to call MainActivity methods from JavaScriptInterface.java, the methods are not being called or no errors are given.
here's what I have tried so far:
MainActivity act=new MainActivity();
act.myMethod() //This method is available in my activity
but it is not being called.
and
((MainActivity)getActivity).myMethod();
public class MainActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTheme(R.style.AppTheme);
setContentView(R.layout.activity_main);
}
public void myMethod() {
Toast.makeText(this, "Inside MainActivity", Toast.LENGTH_SHORT).show();
}
}
//JavaScriptInterface class
class JavaScriptInterface {
Context mContext;
JavaScriptInterface(Context c) {
mContext = c;
}
/** Show a toast from the web page */
#JavascriptInterface
public void onButtonClick(String toast1, String toast2) {
Toast.makeText(mContext, toast1+" | "+toast2, Toast.LENGTH_SHORT).show(); //THIS IS WORKING
MainActivity act=new MainActivity();
act.myMethod(); //NOT WORKING
}
}
Technically, the myMethod will get called, but since you create the MainActivity yourself, it's not attached to anything.
In general, you shouldn't create a new MainActivity instance this way. To open a new MainActivity, you use an Intent.
In your case, you should have a reference to the original MainActivity instance, and call this method there. Not create a new one in any way, as you already have it running.
An easy way to solve it:
MainActivity.this.myMethod("Hello there")
You don't have to store mContext . You already are inside of MainActivity.
So, the full code would be:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WebView myWebView = findViewById(R.id.webview);
myWebView.loadUrl("http://www.google.com");
myWebView.addJavascriptInterface(new WebAppInterface(), "Android");
}
public void myMethod(String test){
Toast.makeText(this, test, Toast.LENGTH_SHORT).show();
}
public class WebAppInterface {
/** Show a toast from the web page */
#JavascriptInterface
public void showToast(String toast) {
MainActivity.this.myMethod("Hello there");
}
}
}
In fact, I think you can even avoid having the MainActivity.this. , and call myMethod directly.
You are creating another object of MainActivity this is why its not getting displayed. You are passing the activity context to the interface so you can just
((MainActivity)mContext).myMethod();
Sample MainActivity
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WebView myWebView = findViewById(R.id.webview);
myWebView.loadUrl("http://www.google.com");
myWebView.addJavascriptInterface(new WebAppInterface(this), "Android");
}
public void myMethod(String test){
Toast.makeText(this, test, Toast.LENGTH_SHORT).show();
}
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) {
((MainActivity)mContext).myMethod("hello");
}
}
}
Check out android documentation for more info
I have two webviews in my android app one webview deletes content based on given javascript function and other one is remaining same even I give javascript function by id. The main webview working perfectly and other one not and now i may integrating another webview if my second webview works perfectly.
here is my first webview it's working perfectly
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webView = (WebView) findViewById(R.id.webView);
webView.setWebViewClient(new myWebClient());
webView.getSettings().setJavaScriptEnabled(true);
webView.loadUrl("url");
webView.getSettings().setDomStorageEnabled(true)
public class myWebClient extends WebViewClient
{
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
view.loadUrl("javascript:(function() {document.getElementById('mainHeader').style.display='none';" + "document.getElementById('footerRights').style.display='none';" + "document.getElementById('navTrail').style.display='none';" + "document.getElementById('threeColumns').style.display='none';" + " })()");
}
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
}
}
#Override
// This method is used to detect back button
public void onBackPressed() {
if (webView.canGoBack()) {
webView.goBack();
} else {
// Let the system handle the back button
super.onBackPressed();
}
}
}
my second webview
public class webview2 extends AppCompatActivity {
private WebView webVIEW;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_webview);
webVIEW = (WebView) findViewById(R.id.webVIEW);
webVIEW.setWebViewClient(new WebViewClient());
webVIEW.getSettings().setJavaScriptEnabled(true);
webVIEW.loadUrl("example url");
webVIEW.getSettings().setJavaScriptEnabled(true);
webVIEW.getSettings().setDomStorageEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
public class webVIEW extends WebViewClient {
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
view.loadUrl("javascript:(function() { " + "var element = document.getElementById('hplogo');" + "element.parentNode.removeChild(element);" + " })()");
}
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon ) {
super.onPageStarted(view, url, favicon);
}
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
}
#Override
public void onBackPressed(){
if (webVIEW.canGoBack()) {
webVIEW.goBack();
}else {
super.onBackPressed();
}
}
}
webview2.java
its being remaining same no javascript excution now i need to integrate another webview and it also needs the same as first webview
Thanks in Advance
I have solved my question using kotlin class by this i can inject java script in one or more webviews
class webview2 : AppCompatActivity() {
private lateinit var webVIEW: WebView
#SuppressLint("SetJavaScriptEnabled")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_webview)
webVIEW = findViewById<WebView>(R.id.webVIEW) as WebView
webVIEW.settings.javaScriptEnabled = true
webVIEW.webViewClient = object : WebViewClient() {
override fun onPageFinished(view: WebView, url: String) {
injectJS()
}
}
webVIEW.loadUrl("https://example/login")
}
val progressBar = findViewById<ProgressBar>(R.id.progressBar3)
override fun onBackPressed() {
if (webVIEW.canGoBack()) {
webVIEW.goBack();
} else {
super.onBackPressed()
}
}
private fun injectJS() {
val jsContent: String?
jsContent = try {
val inputStream = assets.open("style.js")
val fileContent = inputStream.bufferedReader().use(BufferedReader::readText)
inputStream.close()
fileContent
} catch (e: Exception) {
null
}
jsContent?.let { webVIEW.loadUrl("javascript:($jsContent)()") }
}
}
I need to read text on the button which is located on the website. I tried to parse the page using JSOUP, but JSOUP doesn't see Javascript object. That is why I decide to use WebView to read text. But it doesn't work. I need to return the button text from Javascript to Java. Is it possible?
public class MainActivity extends AppCompatActivity {
WebView mWebView;
Button mButton, mClick;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mWebView = (WebView) findViewById(R.id.web_view);
mButton = (Button) findViewById(R.id.start_URL);
mClick = (Button) findViewById(R.id.click);
}
#Override
protected void onResume() {
super.onResume();
mButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.getSettings().setUseWideViewPort(true);
mWebView.getSettings().setLoadWithOverviewMode(true);
mWebView.getSettings().setDomStorageEnabled(true);
mWebView.setWebViewClient(new PersonalWebView());
mWebView.setWebChromeClient(new PersonalWebChrome());
mWebView.addJavascriptInterface(new JSInterface(), "JSInterface");
mWebView.loadUrl(URL);
mClick.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mWebView.loadUrl("javascript: window.JSInterface.callFromJS('buttonText')");}
}
private class JavaScriptInterface {
#JavascriptInterface
public void callFromJS(String buttonText) {
Log.d("JScript","callFromJS "+ buttonText);
}
}
private class PersonalWebView extends WebViewClient{
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
}
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
}
#Override
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
super.onReceivedError(view, request, error);
}
}
private class PersonalWebChrome extends WebChromeClient {
private PersonalWebChrome() {
super();
}
#Override
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
return super.onJsAlert(view, url, message, result);
}
}
#Override
public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
Log.d("TAG", consoleMessage.message()+" "+consoleMessage.sourceId());
return super.onConsoleMessage(consoleMessage);
}
}
I tried to change code, but it doesn't work:
mClick.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mWebView.addJavascriptInterface(new JSInterface(), "JSInterface");
ValueCallback<String> result = new ValueCallback<String>() {
#Override
public void onReceiveValue(String value) {
Log.d("TAG", value);
}
};
mWebView.evaluateJavascript("javascript: window.JSInterface.callFromJS('buttonText')",result);}}
In the Log I see:
D/TAG: Uncaught TypeError: Cannot read property 'callFromJS' of undefined
This is not the correct way of dealing with injected Java objects:
mWebView.addJavascriptInterface(new JavaScriptInterface(), "javaCallback");
mWebView.loadUrl("javascript:window.javaCallback.callFromJS('buttonText')";
Injected objects only become "visible" on the next page load after calling addJavascriptInterface. Loading javascript: URIs doesn't count as a page load.
Check out the sample from the docs:
webView.addJavascriptInterface(new JsObject(), "injectedObject");
webView.loadData("", "text/html", null);
webView.loadUrl("javascript:alert(injectedObject.toString())");
The loadData in between is what actually makes the object to be inserted. You can as well use loadUrl but it needs to be a real page (from the network, assets, about:blank, whatever), but not a javascript: URI.
The problem should be in trying to call callFromJS method before registering interface. You register the JS interface only on the button click:
mClick.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mWebView.addJavascriptInterface(new JSInterface(), "JSInterface");
}
}
But you try to call the callFromJS immediately.
Instead of doing this, move your mWebView.evaluateJavascript("javascript: window.JSInterface.callFromJS('buttonText')",result); inside onClick()
I m coding a WebView application that should call some javascript functions everytime a page is loaded
This is what I ve done but it doesn't work.
public class MainActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WebView view = (WebView) findViewById(R.id.webView);
WebSettings faller = view.getSettings();
String url = "http://catcheat.net/test/test.html";
faller.setJavaScriptEnabled(true);
view.loadUrl(url);
view.setWebViewClient(new WebViewClient() {
public void onPageFinished(WebView view, String url) {
view.loadUrl("javascript:clickFunction()");
view.setWebViewClient(new WebViewClient() {
public void onPageFinished(WebView view, String url) {
view.loadUrl("javascript:clickFunction2()");
}
}
};
}
}
Everything goes well Untill i reach the clickfunction2(). I can't call this second function
Where I m wrong??
Edit: scrap the answer before, as there is a bigger issue: calling a loadUrl from inside the onPageFinished could cause an infinite loop. Note that one should be careful when invoking loadUrl inside onPageFinished.
Actually, and apart from parenthesis and colons (which you should have seen while trying to compile) the issue may be the order of the loadUrl. These should be invoked after the corresponding setWebViewClient:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WebView view = (WebView) findViewById(R.id.webView);
WebSettings faller = view.getSettings();
String url = "http://catcheat.net/test/test.html";
faller.setJavaScriptEnabled(true);
view.setWebViewClient(new WebViewClient() {
public void onPageFinished(WebView view, String url) {
view.setWebViewClient(new WebViewClient() {
public void onPageFinished(WebView view, String url) {}
});
view.loadUrl("javascript:clickFunction()");
view.loadUrl("javascript:clickFunction2()");
}
});
view.loadUrl(url);
}
The problem is that you have a syntax error.
public class MainActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WebView view = (WebView) findViewById(R.id.webView);
WebSettings faller = view.getSettings();
String url = "http://catcheat.net/test/test.html";
faller.setJavaScriptEnabled(true);
view.loadUrl(url);
view.setWebViewClient(new WebViewClient() {
public void onPageFinished(WebView view, String url) {
view.loadUrl("javascript:clickFunction()");
view.setWebViewClient(new WebViewClient() {
public void onPageFinished(WebView view, String url) {
view.loadUrl("javascript:clickFunction2()");
}
}
});
}
}
It's }); and not };
I have followed this very basic example tutorial for loading a URL in a WebView async:
android-asynctask-example.
However the app force closes when i click 'Load Webpage', with the error:
"Can't create handler inside thread that has not called
Looper.prepare()".
When I remove the line "webView.getSettings().setJavaScriptEnabled(true);", the app works fine, and displays a WebView (obviously with no JavaScript enabled in the WebView).
If i leave that line in, but set enabled to false, the app also works without crashing.
I wish to modify this project, however i need JavaScript enabled, so was wondering if anyone had a clue as to why it was failing?
Any help will be greatly appreciated!
Try it this way,
public class MainActivity extends Activity {
final Context context = this;
WebView webView =null;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
private class LoadWebPageASYNC extends AsyncTask<String, Void, String> {
#Override
protected void onPreExecute(String result) {
webView = (WebView) findViewById(R.id.webView);
webView.getSettings().setJavaScriptEnabled(true);
}
#Override
protected String doInBackground(String... urls) {
webView.loadUrl(urls[0]);
return null;
}
#Override
protected void onPostExecute(String result) {
}
}
public void dummyFunc(View view){
Toast.makeText(MainActivity.this, "Button Clicked", Toast.LENGTH_SHORT).show();
}
public void readWebpage(View view) {
LoadWebPageASYNC task = new LoadWebPageASYNC();
task.execute(new String[] { "http://www.javacodegeeks.com" });
}
}