Android cannot open drawer inside onReceivedError - android

I have this code within onCreate:
webView.setWebViewClient(new WebViewClient() {
final ProgressDialog progress = new ProgressDialog(MainActivity.this);
.
.
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
view.loadUrl("file:///android_asset/www/error.html");
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.openDrawer(GravityCompat.START);
progress.dismiss();
// onBackPressed(); // this doesn't open the drawer either
}
});
When there is no internet connection it successfully detects the error and loads error.html. However, it refuses to open the drawer. Also, it closes the progress dialog whether I comment out that line or not. And, when I try calling onBackPressed(), it also fails to open the drawer.
The drawer opens and closes fine when the back button is pressed:
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
drawer.openDrawer(GravityCompat.START);
}
}
Why will the drawer not open inside onReceivedError?

Instead of getting the drawer layout reference (drawer) inside onReceivedError, try by declaring the drawer as instance variable and get the reference at onCreate itself.
I tried and able to open & close the drawer, below is the sample.
public class MainActivity extends Activity {
private DrawerLayout mDrawerLayout;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDrawerLayout = (DrawerLayout)
findViewById(R.id.drawer_layout);
Fragment fragment = new PlanetFragment();
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction().replace(R.id.content_frame,
fragment).commit();
}
public class PlanetFragment extends Fragment {
private WebView webView;
public PlanetFragment() {
// Empty constructor required for fragment subclasses
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.main, container, false);
this.webView = (WebView)rootView.findViewById(R.id.webview);
WebSettings settings = webView.getSettings();
settings.setJavaScriptEnabled(true);
webView.setWebViewClient(new WebViewClient() {
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
public void onPageFinished(WebView view, String url) {
}
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
view.loadUrl("file:///android_asset/www/error.html");
mDrawerLayout.openDrawer(GravityCompat.START);
}
});
webView.loadUrl("http://www.google.com");
return rootView;
}
}
}

Related

I check all the forum but not find a solution | "Open external links of my webview in browser and not in app" does not work

thanks for read my question :) I am not able to solve this problem after check all the forum. I am working on my first webview. Nothing special. It's a webview with progress bar. My code in "shouldOverrideUrlLoading" method is not working. I want that all external links of my site open in browser and not in app, but it does not work. Can anyone please check my code?
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
private WebView wv;
private ProgressBar progressBar;
private FrameLayout frameLayout;
SwipeRefreshLayout swipe;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
frameLayout = (FrameLayout) findViewById(R.id.frameLayout);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
progressBar.setMax(100);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
swipe = (SwipeRefreshLayout) findViewById(R.id.swipe);
swipe.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
String webUrl = wv.getUrl();
wv.loadUrl(webUrl);
}
});
LoadWeb();
}
public void LoadWeb(){
wv = (WebView)findViewById(R.id.webView);
WebSettings settings = wv.getSettings();
settings.setJavaScriptEnabled(true);
wv.loadUrl("example.com");
swipe.setRefreshing(true);
wv.setWebViewClient(new HelpClient());
wv.setWebViewClient(new MyAppWebViewClient());
wv.setWebChromeClient(new WebChromeClient(){
public void onProgressChanged(WebView view, int progress){
frameLayout.setVisibility(View.VISIBLE);
progressBar.setProgress(progress);
if (progress == 100){
frameLayout.setVisibility(View.GONE);
}
super.onProgressChanged(view, progress);
}
});
progressBar.setProgress(0);
wv.setWebViewClient(new WebViewClient(){
public void onPageFinished(WebView view, String url){
swipe.setRefreshing(false);
}
});
}
private class HelpClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url){
view.loadUrl(url);
frameLayout.setVisibility(View.VISIBLE);
return true;
}
}
private class MyAppWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if(Uri.parse(url).getHost().endsWith("example.com")) {
return false;
}
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
view.getContext().startActivity(intent);
return true;
}
}
#Override
public void onBackPressed() {
if(wv.canGoBack()) {
wv.goBack();
} else {
super.onBackPressed();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
return super.onOptionsItemSelected(item);
}
#SuppressWarnings("StatementWithEmptyBody")
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.nav_home) {
wv.loadUrl("example.com");
} else if (id == R.id.nav_facebook) {
try {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("fb://page/idfbpage"));
startActivity(intent);
} catch (Exception e) {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.facebook.com/idfbpage"));
startActivity(intent);
}
} else if (id == R.id.nav_instagram) {
Uri uri = Uri.parse("http://instagram.com/_u/idinstapage");
Intent likeIng = new Intent(Intent.ACTION_VIEW, uri);
likeIng.setPackage("com.instagram.android");
try {
startActivity(likeIng);
} catch (Exception e) {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://instagram.com/idinstapage")));
}
} else if (id == R.id.nav_star) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("market://details?id=idpackage"));
startActivity(intent);
} else if (id == R.id.nav_informazioni) {
wv.loadUrl("example.com/info-app");
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
}
In your method LoadWeb() there is an error because your WebView should have only one WebViewClient and only one WebChromeClient. So what happens is, if you use the method wv.setWebViewClient(new YourWebViewClient()); more than once what happens is that all other methods set before that are ignored because you can set it only once.For your case:
You set the WebViewClient Three (3) times:
wv.setWebViewClient(new HelpClient()); //First time
wv.setWebViewClient(new MyAppWebViewClient()); //Second time
And the last time you set it down in your same method you set another like:
wv.setWebViewClient(new WebViewClient(){
public void onPageFinished(WebView view, String url){
swipe.setRefreshing(false);
}
});
So what happens is that the two previous methods were ignored and the only method that was working was the last one (the third) only. That's why I asked you to put the second method down to setWebClient((new MyAppWebViewClient()); so as to ignore the previous!
THE SOLUTION
Now you know we have to set only one WebViewClient for your webView we have to make only ONE Class that will be used to and do the job of all three other WebViewClient by overriding all the required methods. Make this class inside your activity but oustide your any method (just like how you have done when making in HelpClient() Class). Here is Our Class Please make sure you read the Comments in it!
private class NewWebViewClient extends WebViewClient {
//Now we have only one class to do a job of all the other three!
#Override
public void onPageFinished(WebView view, String url) {
/*I here do whatever you want to do when the page has finished loading! Do it here inside this method and it will work may be control the framelayout visibility For example lets setRefreshing false to our swipe()*/
swipe.setRefreshing(false);
//.....add more methods you want here when the page loading is finished
}
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
/*In this method we are going to tell the android system what kind of link we want and what kind of link we dont want for that what we want we will handle for the extra the browser should do so!*/
if (Uri.parse(url).getHost().endsWith("example.com")) {
//if the code gets here this is your link then right? Lets do whatever we want with our link and logic for example lets set framelayout visible or doing anything this link's host is example.com!
frameLayout.setVisibility(View.VISIBLE);
return false;
} else {
//Ooops This link is not yours lets just open browsers right
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
view.getContext().startActivity(intent);
return true;
}
}
}
After your class is beautiful then lets just set our WebViewClient only ONCE.
wv.setWebViewClient(new NewWebViewClient());
You can just ignore the WebChromeClient because you set it only once you are good. Comment below if you find any difficulties!
I hope removing the this line
wv.setWebViewClient(new MyAppWebViewClient());
will solve the problem for you.
You are using two instances of WebViewClient ,remove one ,
private class MyAppWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
Log.d("TAG",url);
if(Uri.parse(url).getHost().equals("example.com")) {
return false;
}
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
view.getContext().startActivity(intent);//add the brakpoint here
Log.d("TAG","Starting activity");
return true;
}
}
just use this

how could I refresh a webview?

so i made a website which could be turned into mobile app simply by using webview. when the first time i install the apk, it work perfectly well but the problem is after that, the web is just static or it's not loaded anymore.
it just open up the same content like the first time i install it even though i already change the whole website. i don't know if the problem was with the webview or with the android.
i already try made a auto refresh/autoreload function in php but it only work in mobile browser and didn't work in my app...
anyone know any solution?
since i'm a newbie in android developping i'll put the whole code of my main activity
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
//initializing WebView
private WebView mwebView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
//WebView
mwebView = (WebView) findViewById(R.id.myWebView);
WebSettings webSettings = mwebView.getSettings();
webSettings.setJavaScriptEnabled(true);
//improve webView performance
mwebView.getSettings().setRenderPriority(WebSettings.RenderPriority.HIGH);
mwebView.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
mwebView.getSettings().setAppCacheEnabled(true);
mwebView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
webSettings.setDomStorageEnabled(true);
webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
webSettings.setUseWideViewPort(true);
webSettings.setSavePassword(true);
webSettings.setSaveFormData(true);
webSettings.setEnableSmoothTransition(true);
mwebView.loadUrl("http://192.168.94.2/autorefresh/");
//force links open in webview only
mwebView.setWebViewClient(new MyWebviewClient());
}
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
return super.onOptionsItemSelected(item);
}
#SuppressWarnings("StatementWithEmptyBody")
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.nav_home) {
mwebView.loadUrl("http://192.168.94.2/ee1/");
}
if (id == R.id.nav_kolam) {
mwebView.loadUrl("http://192.168.94.2/ee1/listkolam.php");
}
if (id == R.id.nav_pantai) {
mwebView.loadUrl("http://192.168.94.2/ee1/listpantai.php");
}
if (id == R.id.nav_transaksi) {
System.exit(0);
}
if (id == R.id.nav_about) {
System.exit(0);
}
if (id == R.id.nav_keluar) {
System.exit(0);
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
//bikin progress dialog
private class MyWebviewClient extends WebViewClient {
//ProgressDialogue
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (Uri.parse(url).getHost().equals("192.168.94.2")) {
//open url contents in webview
return false;
} else {
//here open external links in external browser or app
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(intent);
return true;
}
}
ProgressDialog pd = null;
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
pd=new ProgressDialog(MainActivity.this);
pd.setTitle("Mohon Tunggu Sebentar");
pd.setMessage("Website Loading..");
pd.show();
super.onPageStarted(view, url, favicon);
}
#Override
public void onPageFinished(WebView view, String url) {
pd.dismiss();
super.onPageFinished(view, url);
}
}
//bikin tombol back halaman
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
if (mwebView.canGoBack()) {
mwebView.goBack();
} else {
finish();
}
return true;
}
}
return super.onKeyDown(keyCode, event);
}}
i'm using native php
The webView caches all the Contents of the Site , so that it doesn't need to download images etc.
For you to get the updations you need to maintain versioning your files and have a cache-control = max-age on yout index.html file
mwebView.loadUrl("about:blank");
mwebView.loadUrl("http://192.168.94.2/ee1/");
Load blank page before loading any new url.
So add mwebView.loadUrl("about:blank"); before all your if-else cases.
May this help!
webView.loadUrl("javascript:window.location.reload(true)");
This may help to reload the webview. Thanks

Logic to use multiple webview in TabLayout to handle memory issue

I have almost 30 webview in a Tablayout. Everything works fine but my app consumes a lot of memory and will just close because of memory issue. This is what I get in log
04-05 21:00:09.458 19720-19801/com.example.choman.webview A/chromium: [FATAL:memory.cc(19)] Out of memory. size=16777216
This is my java file. Basically all the remaining 29 fragments contain the same code with just a change in the url. I am not sure how to handle this.
public class stackOverflow extends Fragment {
private WebView webView;
private ProgressBar progressBar1;
private SwipeRefreshLayout mSwipeRefreshLayout1;
public stackOverflow() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_tab1, container, false);
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
progressBar1 = (ProgressBar) view.findViewById(R.id.progressBar1);
webView = (WebView) view.findViewById(R.id.website_detail_1);
webView.setWebViewClient(new MyAppWebViewClient());
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setDomStorageEnabled(true);
webView.loadUrl("http://www.stackoverflow.com");
WebSettings webSettings = webView.getSettings();
webView.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
webView.getSettings().setAppCacheEnabled(true);
webSettings.setDomStorageEnabled(true);
webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
mSwipeRefreshLayout1 = (SwipeRefreshLayout) view.findViewById(R.id.swipe1);
mSwipeRefreshLayout1.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
webView.loadUrl("http://www.stackoverflow.com");
}
});
if (mSwipeRefreshLayout1.isRefreshing()) {
mSwipeRefreshLayout1.setRefreshing(false);
}
webView.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_BACK) && webView.canGoBack()) {
webView.goBack();
return true;
}
return false;
}
});
}
public class MyAppWebViewClient extends WebViewClient {
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
//view.findViewById(R.id.progressBar1).setVisibility(View.GONE);
Log.i("pageFinished", "yesss");
//progressBar.setVisibility(View.INVISIBLE);
progressBar1.setVisibility(View.GONE);
if (mSwipeRefreshLayout1.isRefreshing()) {
mSwipeRefreshLayout1.setRefreshing(false);
}
}
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
}
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
}
}
Mainactivity
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
public WebView view;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);
tabLayout.addTab(tabLayout.newTab().setText("WebView1").setTag("WebView1"));
//all the way down to .....
tabLayout.addTab(tabLayout.newTab().setText("WebView30").setTag("WebView30"));
final ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
viewPager.setOffscreenPageLimit(6);
final PagerAdapter adapter = new TabPagerAdapter(getSupportFragmentManager(), tabLayout
.getTabCount());
viewPager.setAdapter(adapter);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(
tabLayout));
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
}
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
// int id = item.getItemId();
// //noinspection SimplifiableIfStatement
// if (id == R.id.action_settings) {
// return true;
// }
return super.onOptionsItemSelected(item);
}
#SuppressWarnings("StatementWithEmptyBody")
#Override
public boolean onNavigationItemSelected(MenuItem item) {
ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.WebView1) {
viewPager.setCurrentItem(0);
//all the way down to..30
if (id == R.id.WebView30) {
viewPager.setCurrentItem(30);
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
}
This is the code for TabPagerAdapter
public class TabPagerAdapter extends FragmentStatePagerAdapter
{
int tabCount;
public TabPagerAdapter(FragmentManager fm, int numberOfTabs)
{
super(fm);
this.tabCount = numberOfTabs;
}
#Override
public Fragment getItem(int position)
{
switch (position)
{
case 0:
//
WebViewFragment1 tab1 = new WebViewFragment1();
return tab1;
//all the way to tab 29
webViewFragment30 tab30 = new WebViewFragment30();
return tab30
default:
return null;
}
}
#Override
public int getCount()
{
return tabCount;
}
}
Use ViewPager. ViewPager will hold maximum 3 fragments in memory at any time(without changing the default offscreen page limit). The 3 fragments are the current visible fragment, left and right side fragments to the current fragment.
If you want tabs, you could create a custom View which looks like the system Tabs and add it above the ViewPager. Use PageTransformer with ViewPager to track the ViewPager swipe and scroll the custom Tab accordingly. Then listen to the clicks of Tabs and scroll the ViewPager based on the Tab pressed.
Update:
I totally forgot that we could attach a TabLayout with a ViewPager instead of creating custom Tabs.
tabLayout.setUpWithViewPager(viewpager) will work.
Thanks to #choman
viewPager.setOffscreenPageLimit(6); This line is causing the issue. This line tells the view pager to keep (6+6+1 = 13) pages in memory which should be costly in your case since each page has 6.5 Mb of contents. You need to change it to viewPager.setOffscreenPageLimit(1) to fix the OutOfMemory issue.
Quoting your comment, "I am using only single webview in app but my webpage having 6.5MB size. So it was main reason of app crash".
If your webpage is 6.5MB size, my hunch is that it is because of some large size high quality images. If that is the case, you should consider reducing the size of the images by downscaling/ downsampling the images. Downscaling the images at the server side is much better than doing that in mobile after downloading(waste of bandwidth, CPU, battery).
You can use android:largeHeap="true" to request a larger heap size, but this will not work on any pre Honeycomb devices. On pre 2.3 devices, you can use the VMRuntime class, but this will not work on Gingerbread and above.
it causes because your application need more space to run.
i think it will help you to solve out current problem.
--how to use--
<application
....
android:largeHeap="true" >
thanks
WebView is heavy component.
I would recommend to change your application to work with single webview and changing url in it instead of multiple webview usage.

Access PrgressDialog from a different Activity

I have a MainActivity which loads a Fragment in it's oncreate Method and a Dialog to check for User's Input. This Fragment loads a WebView and a ProgressDialog in it's onPageStarted Method. The Problem is, now Those 2 Dialogs are overlapping each other on App start, So the user has to wait for the ProgressDialog (WebView) to finish, before he can access the InputDialog.
Can I access the ProgressDialog from my MainActivity or can I display the Input Dialog after finishing (dismissing) the ProgressDialog from my MainActivity in any way?
MainActivity oncreate:
public class MainActivity extends AppCompatActivity {
DrawerLayout drawerLayout;
Toolbar toolbar;
ActionBar actionBar;
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
Fragment FirstFragment = new FirstFragment();
Fragment SecondFragment = new SecondFragment();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
String firstrun = preferences.getString("firstrun", null);
String helpread = preferences.getString("helpread", null);
//check for users first time to open the app
//opens the FirstRunActivity if so
if (firstrun == null) {
Intent FirstRunActivity = new Intent(this, FirstRunActivity.class);
startActivity(FirstRunActivity);
}
//check for users first time to open the app
//opens the HelpActivity if so
if (helpread == null) {
new MaterialDialog.Builder(this)
.title("Hilfe Sektion lesen!")
.content("Bitte lies die Hilfe Sektion der App um alle Informationen über die App zu erhalten und Fehler zu vermeiden.")
.positiveText("OK")
.callback(new MaterialDialog.ButtonCallback() {
#Override
public void onPositive(MaterialDialog dialog) {
Intent HelpActivity = new Intent(MainActivity.this, HelpActivity.class);
startActivity(HelpActivity);
}
})
.show();
}
//Replaces/adds the name and the grade of the users preferences to the header of the NavigationDrawer
String name = preferences.getString("name_preference", "");
String grade = preferences.getString("grade_preference", "");
TextView header_username = (TextView) findViewById(R.id.header_username);
TextView header_grade = (TextView) findViewById(R.id.header_grade);
header_username.setText("Name: " + name);
header_grade.setText("Klasse: " + grade);
//initiate the Toolbar/Actionbar and adds the white menu Icon to it
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
actionBar = getSupportActionBar();
actionBar.setHomeAsUpIndicator(R.drawable.ic_menu_white_24dp);
actionBar.setDisplayHomeAsUpEnabled(true);
//initiates the NavigationDrawer
drawerLayout = (DrawerLayout) findViewById(R.id.navigation_drawer_layout);
NavigationView navigationView = (NavigationView) findViewById(R.id.navigation_view);
if (navigationView != null) {
setupNavigationDrawerContent(navigationView);
}
setupNavigationDrawerContent(navigationView);
//initiates the FirstFragment if there is no Saved Instance of the App
if (savedInstanceState == null) {
fragmentTransaction.replace(R.id.main_fragment, FirstFragment);
fragmentTransaction.commit();
}
}
FirstFragment oncreateview:
public class FirstFragment extends Fragment {
private ProgressBar ProgressBar;
private WebView webView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
//Initiate the Fragments Menu
setHasOptionsMenu(true);
View view = inflater.inflate(R.layout.first_fragment, container, false);
//Initiates the FloatingActionButton and it's onClickListener
FloatingActionButton button = (FloatingActionButton) view.findViewById(R.id.fab);
button.setOnClickListener(new View.OnClickListener() {
//Reloads the WebView if the User clicks on the FloatingActionButton
#Override
public void onClick(View v) {
webView.reload();
}
});
webView = (WebView) view.findViewById(R.id.webView);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setLoadWithOverviewMode(false);
webView.getSettings().setUseWideViewPort(true);
webView.getSettings().setSupportZoom(true);
webView.getSettings().setBuiltInZoomControls(true);
webView.getSettings().setDisplayZoomControls(false);
webView.setWebViewClient(new WebViewClient() {
ProgressDialog prDialog;
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
new MaterialDialog.Builder(getActivity())
.title("Es ist etwas schief gelaufen :(")
.content("Es gibt ein Problem mit deiner Internetverbindung.\nBitte lade die Seite Neu oder besuche sie zu einem späteren Zeitpunkt nochmal.")
.positiveText("Ok")
.show();
}
//ProgressBar is Visible on a loading Page
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
prDialog = ProgressDialog.show(getActivity(), null, "Wird geladen, bitte warten...");
}
//PrgressBar is not visible on a finished Page and SnackBar with Hint
#Override
public void onPageFinished(WebView view, String url) {
if (prDialog.isShowing()) {
prDialog.dismiss();
}
Snackbar.make(view, "Hinweiß: 'oops...404 Error' bedeuted: \nEs sind aktuell keine Vertretungen für dich vorhanden.", Snackbar.LENGTH_LONG).show();
}
});
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
String item = preferences.getString("grade_preference", "");
webView.loadUrl("http://www.kantschule-falkensee.de/uploads/dmiadgspahw/vertretung/Druck_Kla_" + item + ".htm");
return view;
}
Yes,you can define a interface like this:
public interface ProgressDialogDismissListener {
void onProgressDialogDisMiss();
}
You can init a interface,and do what you want in the method "onProgressDialogDisMiss",such as start a input dialog.then transmit the reference of that interface to your fragment
Try making your ProgressDialog globally accessible by making it public static in your MainActivity.
Then you can access your ProgressDialog outside your MainAcitivity by just doing MainActivity.myProgressDialog

Displaying progress bar for a webview in fragment view

I am trying to display a progress bar before the webpage appears or loads.I have declared the progressbar in onCreateView method of PlanetFragment which extends fragment I have removed the hearder of the webpage. But the progressbar doesn't appear whatsoever code I write. Please help
This is my MainActivity
public class MainActivity extends Activity {
private DrawerLayout mDrawerLayout;
private ListView mDrawerList;
private ActionBarDrawerToggle mDrawerToggle;
private CharSequence mDrawerTitle;
private CharSequence mTitle;
private String[] mPlanetTitles;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTitle = mDrawerTitle = getTitle();
mPlanetTitles = getResources().getStringArray(R.array.planets_array);
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerList = (ListView) findViewById(R.id.left_drawer);
// set a custom shadow that overlays the main content when the drawer
// opens
mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow,
GravityCompat.START);
// set up the drawer's list view with items and click listener
mDrawerList.setAdapter(new ArrayAdapter<String>(this,
R.layout.drawer_list_item, mPlanetTitles));
mDrawerList.setOnItemClickListener(new DrawerItemClickListener());
// enable ActionBar app icon to behave as action to toggle nav drawer
getActionBar().setDisplayHomeAsUpEnabled(true);
getActionBar().setHomeButtonEnabled(true);
// ActionBarDrawerToggle ties together the the proper interactions
// between the sliding drawer and the action bar app icon
mDrawerToggle = new ActionBarDrawerToggle(this, /* host Activity */
mDrawerLayout, /* DrawerLayout object */
R.drawable.ic_drawer, /* nav drawer image to replace 'Up' caret */
R.string.drawer_open, /* "open drawer" description for accessibility */
R.string.drawer_close /* "close drawer" description for accessibility */
) {
public void onDrawerClosed(View view) {
getActionBar().setTitle(mTitle);
invalidateOptionsMenu(); // creates call to
// onPrepareOptionsMenu()
}
public void onDrawerOpened(View drawerView) {
getActionBar().setTitle(mDrawerTitle);
invalidateOptionsMenu(); // creates call to
// onPrepareOptionsMenu()
}
};
mDrawerLayout.setDrawerListener(mDrawerToggle);
if (savedInstanceState == null) {
selectItem(0);
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
return super.onCreateOptionsMenu(menu);
}
/* Called whenever we call invalidateOptionsMenu() */
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
// If the nav drawer is open, hide action items related to the content
// view
boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);
menu.findItem(R.id.action_websearch).setVisible(!drawerOpen);
return super.onPrepareOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// The action bar home/up action should open or close the drawer.
// ActionBarDrawerToggle will take care of this.
if (mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
// Handle action buttons
switch (item.getItemId()) {
case R.id.action_websearch:
// create intent to perform web search for this planet
Intent intent = new Intent(Intent.ACTION_WEB_SEARCH);
intent.putExtra(SearchManager.QUERY, getActionBar().getTitle());
// catch event that there's no activity to handle intent
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
} else {
Toast.makeText(this, R.string.app_not_available,
Toast.LENGTH_LONG).show();
}
return true;
default:
return super.onOptionsItemSelected(item);
}
}
/* The click listner for ListView in the navigation drawer */
private class DrawerItemClickListener implements
ListView.OnItemClickListener {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
selectItem(position);
}
}
private void selectItem(int position) {
// update the main content by replacing fragments
Fragment fragment = new PlanetFragment();
Bundle args = new Bundle();
args.putInt(PlanetFragment.ARG_PLANET_NUMBER, position);
fragment.setArguments(args);
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.content_frame, fragment).commit();
// update selected item and title, then close the drawer
mDrawerList.setItemChecked(position, true);
setTitle(mPlanetTitles[position]);
mDrawerLayout.closeDrawer(mDrawerList);
}
#Override
public void setTitle(CharSequence title) {
mTitle = title;
getActionBar().setTitle(mTitle);
}
/**
* When using the ActionBarDrawerToggle, you must call it during
* onPostCreate() and onConfigurationChanged()...
*/
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Sync the toggle state after onRestoreInstanceState has occurred.
mDrawerToggle.syncState();
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Pass any configuration change to the drawer toggls
mDrawerToggle.onConfigurationChanged(newConfig);
}
/**
* Fragment that appears in the "content_frame", shows a planet
*/
public static class PlanetFragment extends Fragment {
public static final String ARG_PLANET_NUMBER = "planet_number";
public PlanetFragment() {
// Empty constructor required for fragment subclasses
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_planet,
container, false);
int i = getArguments().getInt(ARG_PLANET_NUMBER);
String planet = getResources()
.getStringArray(R.array.planets_array)[i];
int imageId = getResources().getIdentifier(
planet.toLowerCase(Locale.getDefault()), "drawable",
getActivity().getPackageName());
final WebView webview = ((WebView) rootView
.findViewById(R.id.image));
final ProgressBar progressbar = ((ProgressBar) rootView
.findViewById(R.id.progressbar));
webview.getSettings().setJavaScriptEnabled(true);
final PlanetFragment activity = this;
webview.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
webview.loadUrl("javascript:document.getElementsByClassName('header')[0].style.display=\"none\";");
webview.loadUrl("javascript:document.getElementsByClassName('icon-anon')[0].style.display=\"none\";");
webview.loadUrl("javascript:document.getElementsByClassName('search')[0].style.display=\"none\";");
webview.loadUrl("javascript:document.getElementsByClassName('wh_ad')[0].style.display=\"none\";");
webview.loadUrl("javascript:document.getElementsByClassName('cse_x')[0].style.display=\"none\";");
webview.loadUrl("javascript:document.getElementsByClassName('wh_search')[0].style.display=\"none\";");
webview.loadUrl("javascript:document.getElementsByClassName('wh_ad')[0].style.display=\"none\";");
webview.loadUrl("javascript:document.getElementsByClassName('wh_ad')[0].style.display=\"none\";");
webview.loadUrl("javascript:document.getElementsByClassName('footer_random_button')[0].style.display=\"none\";");
webview.loadUrl("javascript:document.getElementsByClassName('mw-mf-page-left')[0].style.display=\"none\";");
webview.loadUrl("javascript:document.getElementsByClassName('mw-mf-viewport')[0].style.display=\"none\";");
webview.getSettings().setJavaScriptEnabled(false);
}
});
webview.loadUrl(planet);
getActivity().setTitle(planet);
return rootView;
}
}
}
This is my xml layout:
<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"
tools:context=".MainActivity" >
<ProgressBar
android:id="#+id/progressbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="5dp" />
<WebView
android:id="#+id/image"
android:layout_width="wrap_content"
android:layout_height="match_parent" />
Something like this should work. I have not tested it(dont have editor right now). The solution is hiding the webview and showing it at appropriate times.
webview.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
view.setVisibility(View.VISIBLE);
//you might need this
view.bringToFront();
}
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
view.setVisibility(View.GONE);//hide the webview that will display your dialog
}
});
It's because the ProgressBar it's "below" the WebView in your xml (meaning that the first widget declared in xml will be the one at the deepest level, widgets are stacked).
Try to put the ProgressBar below in the xml and hide it when neccessary, like shown below:
<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"
tools:context=".MainActivity" >
<WebView
android:id="#+id/image"
android:layout_width="wrap_content"
android:layout_height="match_parent" />
<ProgressBar
android:id="#+id/progressbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="5dp" />
</RelativeLayout>
Currently the WebView stays in front of your ProgressBar

Categories

Resources