I'm trying to build an android app, which just consists of a webview. I took the example from android dev site and modified it. But as simple as it looks, every call to findViewById results in a null pointer.
The .java file:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
WebView webView = (WebView) findViewById(R.id.webview);
// returns null pointer
webView.loadUrl("file:///android_asset/index.html");
setContentView(webView);
}
}
The layout file:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:orientation="horizontal"
tools:context=".MainActivity" >
<WebView
android:id="#+id/webview"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
And I put following line into the manifest:
<uses-permission android:name="android.permission.INTERNET" />
I'm puzzled ...
Change to
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mylayout); // muylayout is your layout.xml
WebView webView = (WebView) findViewById(R.id.webview);
// returns null pointer
webView.loadUrl("file:///android_asset/index.html");
}
}
You need to set the content of your layout to the activity before calling findViewById. findViewById looks for a view with the id provided in the current layout inflated.
Just in case the accepted answer is not working. Since i have two different layouts for phone and tablet but only one have WebView which cause findViewById() get null.
Related
My app default language is Spanish (es). I have introduced a webview in XML. Prior to this change, the language is Spanish. After adding the webview, it's automatically showing English. How can I fix this issue or problem?
Thanks for helping in advance.
I already used below code too.
WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setUserAgentString(String.valueOf(Locale.SPANISH));
<WebView
android:id="#+id/webView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="-5dp"
tools:ignore="WebViewLayout" />
You can dynamically add web view and initialize the language again after that.
llDynemic=(LinearLayout)findViewById(R.id.test);
WebView webView = new WebView(getContext());// webview in mainactivity
webView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
webView.setBackgroundColor(Color.TRANSPARENT);
webView.getSettings().setJavaScriptEnabled(true);
webView.loadDataWithBaseURL(null, "<style>img{display: inline;height: auto;max-width: 100%;} a {color: #337ab7;}</style>" + newBody, "text/html", "UTF-8", null);
llDynemic.addView(webView);
// initialize the language here
and it will work
in activity have webView
#Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
init here language again then
setContentView(R.layout.activity_terms_of_use);
After a lot of testing and following the advices from the other answers, I've finally fixed the issue.
Issues with WebView:
WebView have to be loaded dynamically in the activity. Loading from XML file via Activity#setContentView() won't work for the first time and localisation of the entire activity will break. However, subsequent launches or Activity#recreate() will work as expected.
Even if WebView is loaded dynamically, it won't work for the first time. Again, subsequent launches or Activity#recreate() will work properly.
Considering the issues above, the solution involves loading WebView dynamically and then, the immediate recreation of the activity.
ActivityWithWebView.java
public class ActivityWithWebView extends AppCompatActivity {
private WebView webView;
private static boolean firstTime = true;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
setContentView(R.layout.activity_with_web_view);
setSupportActionBar(findViewById(R.id.toolbar));
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) actionBar.setTitle(R.string.instructions);
// WebView has to be loaded dynamically to prevent in-app localisation issue.
webView = new WebView(this);
if (firstTime) {
// Recreate if loaded for the first time to prevent localisation issue.
recreate();
firstTime = false;
return;
}
LinearLayoutCompat webviewWrapper = findViewById(R.id.webview_wrapper);
webView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
webviewWrapper.addView(webView);
// Do other works.
}
}
activity_with_web_view.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?android:colorBackground" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.appcompat.widget.LinearLayoutCompat
android:id="#+id/webview_wrapper"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
I am creating an application in which I have to use webView and display a HTML file saved in application in assets folder. This is my mainActivity code.
public class MainActivity extends Activity {
WebView browser;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
browser = (WebView)findViewById(R.id.wv1);
browser.loadUrl("file:///android_asset/test.htm");
WebSettings webSettings = browser.getSettings();
browser.getSettings().setJavaScriptEnabled(true);
setContentView(browser);
}
}
and this is my xml file
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Test Application"
android:gravity="center_horizontal">
</TextView>
<WebView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/wv1"
android:layout_marginTop="3dp">
</WebView>
whin I am trying to run this application , it goes crash..
can any one please help me to find out what is the mistake i am doing.
You cannot call setContentView(browser) because browser is already a child of another view -- the LinearLayout.
If you don't need the other views, just change the layout xml file and remove them, leaving only the WebView. Otherwise, remove the setContentView(browser) line.
You're using setContentView() twice and supplying the view that already has a parent. That is why it is giving you the error saying call removeView() on the child's parent first. So remove setContentView(browser).
Your code should look like this.
public class MainActivity extends Activity {
WebView browser;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
browser = (WebView)findViewById(R.id.wv1);
browser.loadUrl("file:///android_asset/test.htm");
browser.getSettings().setJavaScriptEnabled(true);
}
}
I have a simple Android app. The layout folder shows an activity_main.xml file and a fragment_main.xml file. In that fragment.xml file I have placed a button that I've named buttonTest.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
tools:context="com.snapvest.thunderbird.app.MainActivity$PlaceholderFragment">
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TEST"
android:id="#+id/buttonTest"
android:layout_gravity="center_horizontal" />
</LinearLayout>
in the MainActivity.java file I'm trying to gain access to that buttonTest.
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
getFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment())
.commit();
}
// Get access to the buttons
final Button buttonTest = (Button)findViewById(R.id.buttonTest);
}
It compiles just fine. But when I run it the buttonTest variable comes back as a null pointer.
Why is it not finding the buttonTest object?
I think I found the solution. MainActivity.java sets up the activity_main.xml which then uses fragment_main.xml as its (initially) single, primary fragment. That's why we are supposed to actually put all of our UI for the activity primarily in fragment_main.xml (and actually put NOTHING in activity_main.xml).
Near the bottom of MainActivity.java there is a section that initializes the fragment_main.xml. And it is THERE that I need to gain access to the buttons and other objects of the UI for the fragment. Such as:
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
// Get access to the buttons
final Button buttonAvailableOptions = (Button)rootView.findViewById(R.id.buttonAvailableOptions);
return rootView;
}
}
Most of that, above, is automatically added by Android Studio. The part starting with "Get access to the button" is mine and is where you set up any access to or processing of the buttons and other UI objects.
The reason why findViewById() is failing to find the button is because setContentView() primes findViewById() to only look in the layout.xml file you gave to setContentView(), and your button is not located in R.layout.activity_main. If your button is located in the Fragment (which it appears to be) then you should be accessing and manipulating it from the Fragment, not the Activity. This ensures that your Activity and Fragment logic stay decoupled, allowing you to re-use the Fragment with different Activities.
You can use like this.
final Button buttonAvailableOptions = getActivity().findViewById(R.id.buttonAvailableOptions);
I'm new to Android (and surely I'm not an expert Java developer), so I'm sorry for the dumb question
I would like to "capture" the id of a textView and to set its text value dynamically,
here is how I'm trying to do this:
public class AndStringTestActivity extends Activity {
/** Called when the activity is first created. */
String abc = "abcabc";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView tv = (TextView)findViewById(R.id.test);
tv.setText(abc);
setContentView(R.layout.main);
}
}
and here is the Xml from which i'm reading the id of the textview i would like to write inside
// main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:id="#+id/test"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</LinearLayout>
the error i receive is the usual Application stopped unexpectedly
Thanks.
Call setContentView before trying to find the TextView. The TextView does not exist before you have called setContentView (which will inflate your XML layout)
Call setContentView(R.layout.main) before you call findViewById().
Suppose I have a webview open:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
main_webv = (WebView) findViewById(R.id.mainwebview);
main_webv.setWebViewClient(new HelloWebViewClient());
main_webv.getSettings().setJavaScriptEnabled(true);
main_webv.getSettings().setSupportZoom(false);
main_webv.addJavascriptInterface(new HelloJavascriptInterface(),"hello");
main_webv.setWebChromeClient(new HelloWebChromeClient());
main_webv.loadUrl(SPLASH);
main_webv.setVisibility( 4 );
setContentView(R.layout.main_list);
main_listv = (ListView) findViewById(R.id.mainlistview);
}
I simply want to create a ListView above this webview (covering it up...but sitll allowing the webview to run). I could toggle the views on and off.
Thanks.
You can use FrameLayout; that way both the Views will be arranged on top of another. You can then toggle their visibility using the View.setVisibility(..) method.
[EDIT: ADDED CODE]
This is my layout XML(weblister.xml):
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<ListView
android:id="#+id/list_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
<WebView
android:id="#+id/webview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</FrameLayout>
Now, I create an Activity which will have both ListView and WebView in its View heirarchy but only one of them would be Visible:
public class WebAct extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.weblister);
//setup listview
ListView listView = (ListView) findViewById(R.id.list_view);
listView.setAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1,
new String[]{"One","Two"}){
});
// setup web view
WebView webView = (WebView) findViewById(R.id.webview);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setSupportZoom(false);
webView.loadUrl("http://www.google.com");
// set visibility
listView.setVisibility(View.INVISIBLE);
webView.setVisibility(View.VISIBLE);
}
}
Note: The code might not be complete but I hope it does convey my point to you.
Yes, setVisibility will probably help you if you want to programmatically switch Views on (View.VISIBLE) and off (VIEW.GONE).
Concerning your comment to Samuhs answer: In Java you don't have multiple inheritance. But ListActivity inherits from Activity so a ListActivity is pretty much the same (and more) as an Activity.
Also, you don't have to use a ListActivity to display ListViews, it simply provides some convenience-stuff for handling list based activities since they are so common.
What exactly is the error you get?