WebView Becoming Null - android

I have a fragment which displays a WebView, in order to retain the website that is being shown I save the state like this:
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
/*Saves the currently displayed webpage and the browser history*/
webView.saveState(outState);
}
Then I restore it like this:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_page_detail,
container, false);
webView = (WebView) rootView.findViewById(R.id.page_detail_webview);
progressBar = (ProgressBar) rootView.findViewById(R.id.op_progress);
webView.setWebChromeClient(new WebChromeClient() {
public void onProgressChanged(WebView view, int progress) {
progressBar.setVisibility(View.VISIBLE);
progressBar.setProgress(progress);
if (progress == 100) {
progressBar.setVisibility(View.GONE);
}
}
});
webView.setWebViewClient(new StockStreamWebViewClient());
webView.getSettings().setBuiltInZoomControls(true);
/*Restores the saved browser history if there is any*/
if (savedInstanceState != null) {
webView.restoreState(savedInstanceState);
} else if (mItem != null) {
webView.loadUrl(mItem.content);
}
return rootView;
}
To allow the user to go back in the WebView I have this code in my Activity:
#Override
public void onBackPressed() {
if (!clientFragment.onBackPressed()) {
super.onBackPressed();
}
}
}
And this code in my Fragment:
public boolean onBackPressed() {
if (webView != null && webView.canGoBack()) {
webView.goBack();
return true;
} else {
return false;
}
}
When I rotate my device the screen draws correctly and the WebView restores it's previous page, but when I press back the WebView is null.
Why is this happening?
Thanks,
ANkh

SimonVT in the #android-dev correctly suggested that I might be making calls to a null or new Fragment from my Activity.
So I added this code to my Activity to save the ID of the Fragment:
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (clientFragment != null) {
outState.putInt(CLIENT_FRAGMENT_ID, clientFragment.getId());
}
}
And this code to restore the reference to the correct Fragment:
if (savedInstanceState != null
&& savedInstanceState.containsKey(CLIENT_FRAGMENT_ID)) {
clientFragment = (PageDetailFragment) getSupportFragmentManager()
.findFragmentById(savedInstanceState.getInt(CLIENT_FRAGMENT_ID));
}
PageDetailFragment is my extended Fragment.
Thanks,
ANkh

Related

WebView save and restore state issue with postUrl

I am using the following components in my application
Activity
Fragment
WebView
Goal - I don't want to reload the webview on orientation change.
Issue - Currently I see the following error on orientation change "Webpage was not available. The webpage at https://fakeurls.org could not be loaded because net::ERR_CACHE_MISS"
Steps to Reproduce
Application was opened in device portrait mode.
Content of given URL was loaded in webview successfully
Device was turned to landscape mode
Webview shows error
Code - Android application makes a post request in a webview to url https://fakeurls.org. Below is the code for MyActivity and MyFragment class
MyFragment.java
public class MyFragment extends Fragment {
private ProgressBar mProgressBar;
private WebView mWebView;
private String mUrl = null;
private String mPostData = null;
public MyFragment() {
// Required empty public constructor
}
public static MyFragment newInstance(#android.support.annotation.NonNull String url, String postData) {
MyFragment MyFragment = new MyFragment();
Bundle bundle = new Bundle();
bundle.putString("URL", url);
bundle.putString("POSTDATA", postData);
MyFragment.setArguments(bundle);
return MyFragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.my_fragment, container, false);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
instantiateWebView(view);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (savedInstanceState != null) {
mWebView.restoreState(savedInstanceState);
} else {
Bundle args = getArguments();
if (args == null) {
return;
}
mUrl = args.getString("URL");
mPostData = args.getString("POSTDATA");
mWebView.postUrl("https://fakeurls.org/", EncodingUtils.getBytes(mPostData, "BASE64"));
}
}
#Override
public void onSaveInstanceState(final Bundle outState) {
super.onSaveInstanceState(outState);
if (mWebView != null) {
mWebView.saveState(outState);
}
}
#Override
public void onDestroy() {
super.onDestroy();
mWebView.destroy();
}
private void instantiateWebView(View view) {
mWebView = (WebView) view.findViewById(R.id.webView);
mWebView.setWebViewClient(new WebViewClient());
mWebView.getSettings().setJavaScriptEnabled(true);
}
}
MyActivity.java
public class MyActivity extends AppCompatActivity {
private MyFragment mMyFragment;
#NonNull
public static Intent createIntent(Context context, String url, String postData) {
return new Intent(context, MyActivity.class).putExtra("URL", url)
.putExtra("POSTDATA", postData);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_link_viewer);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowTitleEnabled(false);
mMyFragment = (MyFragment) getSupportFragmentManager().findFragmentById(R.id.fragment_frame);
if (mMyFragment == null) {
final String url = getIntent().getStringExtra("URL");
final String postData = getIntent().getStringExtra("POSTDATA");
mMyFragment = MyFragment.newInstance(url, postData);
getSupportFragmentManager()
.beginTransaction()
.add(R.id.fragment_frame, mMyFragment)
.commitNow();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void finish() {
mMyFragment.cancelTasks();
super.finish();
}
}
Please let me know how to resolve the issue and not reload the webview but retain display on orientation change. Any help is appreciated.

How to fix On resume method is not getting called in Webview as Fragment in Fragment navigational drawer

I have a webview as fragment which extends fragment class in my fragment navigation drawer. I want to detect the back press of this fragment.
Below is code i m using to detect the back press on the fragment
getView().setFocusableInTouchMode(true);
getView().requestFocus();
getView().setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK){
// handle back button
getActivity().getSupportFragmentManager().beginTransaction().replace(R.id.container,new MyFragment()).commit();
return true;
}
return false;
}
});
In my webview this method is not getting called everytime i pressed back button
public class WebViewFragment extends Fragment {
static View view;
private WebView webView;
private String url;
static int count = 0;
LinearLayout llayout;
MyProgressDialog progressDialog;
public WebViewFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
if (view != null) {
ViewGroup parent = (ViewGroup) view.getParent();
if (parent != null)
parent.removeView(view);
}
try {
((AdvancedActivity) getActivity()).getSupportActionBar().hide();
view = inflater.inflate(R.layout.activity_play_lesson, container, false);
//Get webview
webView = (WebView) view.findViewById(R.id.web_view_play_lesson);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
webView.setWebContentsDebuggingEnabled(true);
}
llayout = (LinearLayout) view.findViewById(R.id.linearLayout);
getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
url = getResources().getString(R.string.myurl);
url = "http://myurl//88";
System.out.println("url for myplay is "+url);
startWebView(url);
} catch (InflateException e) {
}
return view;
}
#SuppressLint("JavascriptInterface")
private void startWebView(String url) {
//Create new webviejijnw Client to show progress dialog
//When opening a url or click on link
webView.setWebViewClient(new WebViewClient() {
/*
IstarProgressDialog progressDialog;
*/
//If you do not use this method url links are opeen in new brower not in webview
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
public void onPageStarted(WebView view, String url, Bitmap favicon) {
if (progressDialog == null) {
// in standard case YourActivity.this
progressDialog = new IstarProgressDialog(getContext());
progressDialog.setMessage("Loading... Please Wait...");
progressDialog.setCancelable(false);
progressDialog.setCanceledOnTouchOutside(false);
progressDialog.show();
}
}
//Show loader on url load
public void onLoadResource(WebView view, String url) {
}
public void onPageFinished(WebView view, String url) {
}
#Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
getActivity().getSupportFragmentManager().beginTransaction().replace(R.id.frame_container,new ErrorFragment()).commit();
}
});
// Javascript inabled on webview
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setAppCacheEnabled(true);
webView.getSettings().setDatabaseEnabled(true);
webView.getSettings().setDomStorageEnabled(true);
webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
webView.getSettings().setGeolocationEnabled(true);
webView.setWebChromeClient(new WebChromeClient() {
public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) {
callback.invoke(origin, true, false);
}
});
webView.loadUrl(url);
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// Save the state of the WebView
webView.saveState(outState);
}
#Override
public void onResume() {
super.onResume();
getView().setFocusableInTouchMode(true);
getView().requestFocus();
getView().setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK){
// handle back button
getActivity().getSupportFragmentManager().beginTransaction().replace(R.id.frame_container,new MyFragment()).commit();
return true;
}
return false;
}
});
wakeLock.acquire();
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d("Webview ", "The onStop() event");
}
}

adding back button support in a activity while using variables of a fragment

public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Fragment_view frag=new Fragment_view();
FragmentManager manager=getFragmentManager();
FragmentTransaction transaction=manager.beginTransaction();
transaction.add(R.id.fragment,frag,"hey");
transaction.commit();
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (inCustomView()) {
hideCustomView();
return true;
}
if ((mCustomView == null) && webView.canGoBack()) {
webView.goBack();
return true;
}
}
return super.onKeyDown(keyCode, event);
}
Now here variables like inCustomView and hidecustomView are defined in another fragment. So how to add this back button support on activity while using variables from a fragment. So I basically want to implement back button support in Android activity while using the defined variables from a fragment.
public class Fragment_view extends Fragment{
private WebView webView;
private FrameLayout customViewContainer;
private WebChromeClient.CustomViewCallback customViewCallback;
private View mCustomView;
private myWebChromeClient mWebChromeClient;
private myWebViewClient mWebViewClient;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View view= inflater.inflate(R.layout.fragment_view, container,false);
customViewContainer = (FrameLayout)view.findViewById(R.id.customViewContainer);
webView = (WebView)view. findViewById(R.id.webView);
mWebViewClient = new myWebViewClient();
webView.setWebViewClient(mWebViewClient);
mWebChromeClient = new myWebChromeClient();
webView.setWebChromeClient(mWebChromeClient);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setAppCacheEnabled(true);
webView.getSettings().setBuiltInZoomControls(true);
webView.getSettings().setSaveFormData(true);
String htmlFile = "file:///" + Environment.getExternalStorageDirectory()
.getPath()
+ "/video_nsta/index.html";
webView.loadUrl(htmlFile);
return view;
}
public boolean inCustomView() {
return (mCustomView != null);
}
public void hideCustomView() {
mWebChromeClient.onHideCustomView();
}
#Override
public void onPause() {
super.onPause();
webView.onPause();
}
#Override
public void onResume() {
super.onResume();
webView.onResume();
}
#Override
public void onStop() {
super.onStop();
if (inCustomView()) {
hideCustomView();
}
}
class myWebChromeClient extends WebChromeClient {
#Override
public void onShowCustomView(View view, int requestedOrientation, CustomViewCallback callback) {
onShowCustomView(view, callback);
}
#Override
public void onShowCustomView(View view,CustomViewCallback callback) {
if (mCustomView != null) {
callback.onCustomViewHidden();
return;
}
mCustomView = view;
webView.setVisibility(View.GONE);
customViewContainer.setVisibility(View.VISIBLE);
customViewContainer.addView(view);
customViewCallback = callback;
}
#Override
public void onHideCustomView() {
super.onHideCustomView();
if (mCustomView == null)
return;
webView.setVisibility(View.VISIBLE);
customViewContainer.setVisibility(View.GONE);
mCustomView.setVisibility(View.GONE);
customViewContainer.removeView(mCustomView);
customViewCallback.onCustomViewHidden();
mCustomView = null;
}
}
class myWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
return super.shouldOverrideUrlLoading(view, url);
}
}
}
it's a matter of properly distributing the back button.
first create a fragment that can handle it:
public abstract class BackButtonFragment extends Fragment{
public boolean onBackPressed(){
return false; // defaults to false
}
}
then you change all your fragments to extend from BackButtonFragment.
Then on your activity you will use the appropriate callback for backbutton (remove the onKeyDown from your activity and use this instead):
#Override public void onBackPressed() {
Fragment f = getFragmentManager().findFragmentById(R.id.fragment);
if(f instanceof BackButtonFragment){
if(((BackButtonFragment)f).onBackPressed())
return;
}
// if fragment didn't use back button do the normal stuff
super.onBackPressed();
}
then inside each one of your fragments you will override the method onBackPressed and return the correct value true or false depending on your needs.

How to fix Android WebView that shows only a link and the android logo

When loading a WebView in an Android App, it shows only a link to the page instead of the website contents next to the android logo on black background. After restarting the app, the content is loaded.
Java Code:
public class MainActivity extends Activity {
private WebView webView;
private String baseUrl = "http://www.example.com";
#SuppressLint("SetJavaScriptEnabled")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webView = (WebView) findViewById(R.id.web_view);
webView.setId(10001);
webView.setBackgroundColor(0xFF000000);
// webView.setScrollBarStyle(SCROLLBARS_OUTSIDE_OVERLAY);
final Activity activity = this;
final ProgressDialog progressDialog = new ProgressDialog(activity);
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.setCancelable(false);
progressDialog.getWindow().setGravity(Gravity.BOTTOM);
hideProgressbarText(progressDialog);
webView.setWebChromeClient(new WebChromeClient() {
public void onProgressChanged(WebView view, int progress) {
progressDialog.show();
progressDialog.setProgress(0);
activity.setProgress(progress * 1000);
progressDialog.incrementProgressBy(progress);
if (progress == 100 && progressDialog.isShowing())
progressDialog.dismiss();
}
});
webView.setWebViewClient(new WebViewClient());
// final ProgressBar progressBar= (ProgressBar)
// findViewById(R.id.progressbar);
WebSettings settings = webView.getSettings();
if (settings != null) {
settings.setJavaScriptEnabled(true);
settings.setDomStorageEnabled(true);
settings.setDefaultZoom(WebSettings.ZoomDensity.MEDIUM);
}
if (savedInstanceState == null) {
webView.loadUrl(baseUrl);
}
}
public void onBackPressed() {
if (webView.isFocused() && webView.canGoBack()) {
webView.goBack();
} else {
super.onBackPressed();
finish();
}
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
private void hideProgressbarText(ProgressDialog progressDialog) {
int currentapiVersion = android.os.Build.VERSION.SDK_INT;
if (currentapiVersion >= android.os.Build.VERSION_CODES.HONEYCOMB) {
progressDialog.setProgressNumberFormat(null);
progressDialog.setProgressPercentFormat(null);
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
webView.saveState(outState);
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
webView.restoreState(savedInstanceState);
}
}
Screenshot:
Seems like what you've got is the error page in case of e.g. page_not_found or DNS_failure. i.e. What you saw is the error messeage or the prompt text, which should be in BLACK color. However you just set your background color as 0xFF000000 (as same the text color) which will hide the prompt text.
Remove the black background and you may see the text. I suppose what's shown now is not your page content but some error prompt from webkit engine.
Use this Website for webview reference they explained good manner
Make sure below
<uses-permission android:name="android.permission.INTERNET" />

Changing fragments and saving web view states - going mad

Ive been trying to do this for the best part of a week and still have no luck.
I have an action bar with tabs (action bar sherlock) and Im switching through the tabs and changing fragments fine.
Each fragment has a webview and Im trying to save the state of the webview so the web page stays on the same page that the user left it on.
Here is my fragment code:
public class FragmentB extends SherlockFragment {
WebView myWebView;
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
myWebView.saveState(outState);
Log.w("///////", "onSaveInstanceState");
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
myWebView.restoreState(savedInstanceState);
Log.w("///////", "onActivityCreated");
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.w("///////", "onCreate");
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View mainView = (View) inflater.inflate(R.layout.frag_b, container, false);
myWebView = (WebView) mainView.findViewById(R.id.webview);
Log.w("///////", "onCreateView");
if (savedInstanceState != null){
myWebView.restoreState(savedInstanceState);
Log.w("///////", "restore!");
}
else{
Log.w("///////", "ELSE!");
myWebView.setWebViewClient(new MyWebViewClient());
myWebView.getSettings().setPluginsEnabled(true);
myWebView.getSettings().setBuiltInZoomControls(false);
myWebView.getSettings().setSupportZoom(false);
myWebView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
myWebView.getSettings().setAllowFileAccess(true);
myWebView.getSettings().setDomStorageEnabled(true);
myWebView.loadUrl("http://www.google.com");
}
//return inflater.inflate(R.layout.frag_b, container, false);
return mainView;
}
public class MyWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.endsWith(".mp4"))
{
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse(url), "video/*");
view.getContext().startActivity(intent);
return true;
}
else {
return super.shouldOverrideUrlLoading(view, url);
}
}
}
}
Any help would be great!
The onSaveInstanceState method of a fragment will only be called when the parent activity needs to save its state; an example of this is when the parent activity is being destroyed/recreated during an orientation change. As a result, this method won't be called when you are simply replacing fragments or switching between them as tabs.
As a workaround for your particular case, you can save the state of your webview in a bundle in the onPause method and restore it in the onActivityCreated method:
// Instance fields
private WebView webView;
private Bundle webViewBundle;
/**
* Save the state of the webview
*/
#Override
public void onPause()
{
super.onPause();
webViewBundle = new Bundle();
webView.saveState(webViewBundle);
}
/**
* Restore the state of the webview
*/
#Override
public void onActivityCreated(Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
if (webViewBundle != null)
{
webView.restoreState(webViewBundle);
}
}
See here for more information as well:
How to save the state of a WebView inside a Fragment of an Action Bar

Categories

Resources