My app uses a WebView, and users sometimes adjust the zoom level to make the text larger. However the zoom level setting is lost when the Activity is closed and another one started.
I can't see how to get and set the zoom level programatically on WebView, can anyone suggest a way this could be done?
its me Jorge from Grupo Reforma, this is my implementation using SharedPreferences..
static final String PREFS_Zoom = "PREFS_Zoom";
private String zoomlevel;
private int Default_zoomlevel=100;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mWebView = (WebView) findViewById(R.id.webview);
GetZoom();
mWebView.setInitialScale(Default_zoomlevel);
FrameLayout mContentView = (FrameLayout) getWindow().getDecorView().findViewById(android.R.id.content);
View zoom = mWebView.getZoomControls();
mContentView.addView(zoom, ZOOM_PARAMS);
zoom.setVisibility(View.VISIBLE);
WebSettings webSettings = mWebView.getSettings();
webSettings.setSavePassword(false);
webSettings.setSaveFormData(false);
webSettings.setJavaScriptEnabled(true);
webSettings.setSupportZoom(true);
mWebView.loadUrl("http://www.elnorte.com");
}
private void GetZoom(){
try{
SharedPreferences settings = getSharedPreferences(PREFS_Zoom,0);
zoomlevel = settings.getString("zoom_level","");
if (zoomlevel.length() >0)
Default_zoomlevel = Integer.parseInt(zoomlevel);
else
Default_zoomlevel =100;
}catch(Exception ex){
Log.e("******ZOOM ! ", "Exception GetZoom() ::"+ex.getMessage());
}
}
private void SaveZoom(){
try{
SharedPreferences settings = getSharedPreferences(PREFS_Zoom,0);
SharedPreferences.Editor editor = settings.edit();
Default_zoomlevel = (int) (mWebView.getScale() *100);
editor.putString("zoom_level",""+ Default_zoomlevel);
editor.commit();
}catch(Exception ex){
Log.e("******ZOOM ! ", "Exception SaveZoom() ::"+ex.getMessage());
}
}
public void finish() {
SaveZoom();
super.finish();
}
I hope this help
The answer Jorge gave is spot on, except that SaveZoom ideally should not be called on finish() (which is when the activity is destroyed). A better zoom preference saving approach would be to extend the WebView's WebViewClient, and override onScaleChanged(). So continuing Jorge's onCreate method:
public void onCreate(Bundle savedInstanceState)
{
....
class MyWebViewClient extends WebViewClient
{
#Override
public void onScaleChanged(WebView wv, float oldScale, float newScale)
{
SaveZoom();
}
}
mWebView.setWebViewClient(new MyWebViewClient());
}
Perhaps you could try:
http://d.android.com/reference/android/webkit/WebSettings.html#setDefaultZoom(android.webkit.WebSettings.ZoomDensity)
&
http://d.android.com/reference/android/webkit/WebSettings.html#getDefaultZoom()
I haven't tried it myself but that looks like it might work
Related
I'm searching for a while how to run my WebView forever. When the android function onPause() / onResume() is called. My WebView starts again.
I want the WebView to go on. Maybe the best to explane by an simple HTML example:
<html><head><title>Webview test Android</title></head>
<body>
<h1><div id="counter"></div></h1>
<script>
var counter = 0;
document.getElementById("counter").innerHTML = counter;
setTimeout(function(){ count(); }, 1000);
function count() {
counter++;
document.getElementById("counter").innerHTML = counter;
console.log("counter: " + counter);
setTimeout(function(){ count(); }, 1000);
}
</script>
</body>
</html>
What I want in the app behaviour is:
> Open the app
+ Html page starts counting
> Press the home button / multitask button
+ Html page is still counting (or doing other stuff)
> Get back to the app
+ Html page is still counting and dont reload.
First I uses my own code for WebView. But with a lot of android versions, I used a chromium-webview example from github
I looked into android WebView methods, but I cant figure a solution. I tried also mWebView.onPause(), mWebView.onResume()... With no results. Maybe someone can bring me in the right direction.
This is are the main functions:
private WebView mWebView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.v("main"," create ");
setContentView(R.layout.activity_main);
mWebView = (WebView) findViewById(R.id.activity_main_webview);
mWebView.addJavascriptInterface(new NotificationBindObject(getApplicationContext()), "NotificationBind");
mWebView.getSettings().setDomStorageEnabled(true); // use localstorage
setUpWebViewDefaults(mWebView);
if (savedInstanceState != null) {
mWebView.restoreState(savedInstanceState);
}
if(mWebView.getUrl() == null) {
mWebView.loadUrl("file:///android_asset/www/index.html");
}
}
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save the WebView state (including history stack)
mWebView.saveState(savedInstanceState);
// Always call the superclass so it can save the view hierarchy state
super.onSaveInstanceState(savedInstanceState);
}
Update
Almost there... I made a Service that runs the WebView.
public class TestService extends Service {
private static WebView w;
private static MainActivity ma;
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
}
public static void setMain(MainActivity a) {
ma = a;
Log.e("main", " setData " );
setView();
}
private static void setView() {
w = (WebView) ma.findViewById(R.id.webView);
Log.e("main", " setData ");
w.getSettings().setDomStorageEnabled(true); // use localstorage
w.getSettings().setJavaScriptEnabled(true);
//ma.setUpWebViewDefaults(w);
w.loadUrl("file:///android_asset/www/index.html");
}
}
MainActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.v("main"," create ");
if (savedInstanceState == null) {
setContentView(R.layout.activity_main);
Intent i = new Intent(MainActivity.this, TestService.class);
TestService.setMain(this);
MainActivity.this.startService(i);
} else {
...
}
...
}
Now when I see the console.log("counter" + counter); logging in Eclipse. The only problem is that the WebView in the layout is gone now when I'm back...
Android: someone help:
I notice this kind of question has been asked before by other people but the answers have not been useful to my my case; I need to launch a new activity from an inner
class but all I get is the error bellow:
04-05 15:00:43.851: E/AndroidRuntime(3288): Caused by: java.lang.InstantiationException: com.school.School$StudentProfile
Here is my code snippet:
public class School extends Activity{
ProgressDialogue progressDialogue;
protected WebViewTask _webTask;
String path = "http://www.school.com/student/";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.school);
progressDialogue = new ProgressDialogue(School.this);
_webTask = new WebViewTask();
_webTask.execute();
}
//rest of the code
/** The inner class */
public class StudentProfile {
Context context;
/** Instantiate the interface and set the context */
public StudentProfile(Context c) {
context=c;
}
/** launch student activity */
public void lauchProfile() {
School.this.startActivity(new Intent(School.this, StudentProfile.class));
//Intent intent = new Intent(School.this, StudentProfile.class);
//startActivity(intent);
}
}
void webView(){
String url = path +"student.php";
WebView wv = (WebView) findViewById(R.id.trivia_webview);
WebSettings webSettings = wv.getSettings();
webSettings.setJavaScriptEnabled(true);
wv.addJavascriptInterface(new StudentProfile (this), "Student");
wv.loadUrl(url);
wv.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// open URL in the web view itself
if (url.contains(url))
return super.shouldOverrideUrlLoading(view, url);
// open URL in an external web browser
else {
return true;
}
}
});
}
// rest of the code
NOTE: there is a 'student' button on the web view that is supposed to launch the StudentProfile activity.
Your StudentProfile is not an Activity, so you can not start it that way. It needs to be a separate class, and declared in AndroidManifest.xml.
I want to get html source code in c# (mono for android)
I add webview in my project. webview name is web.
my code:
WebView webView;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main); webView.Settings.JavaScriptEnabled = true;
webView.Settings.SetSupportZoom(true);
webView.Settings.BuiltInZoomControls = true;
webView.Settings.LoadWithOverviewMode = true; //Load 100% zoomed out
webView.ScrollBarStyle = ScrollbarStyles.OutsideOverlay;
webView.ScrollbarFadingEnabled = true;
webView.VerticalScrollBarEnabled = true;
webView.HorizontalScrollBarEnabled = true;
webView.SetWebViewClient(new AwesomeWebClient());
webView.SetWebChromeClient(new AwesomeWebChromeClient(this));
webView.LoadUrl(#"http://www.google.com");
}
private class AwesomeWebClient : WebViewClient { }
private class AwesomeWebChromeClient : WebChromeClient
{
private Activity mParentActivity;
private string mTitle;
private string username;
private string password;
private string oldurl="";
public AwesomeWebChromeClient(Activity parentActivity)
{
mParentActivity = parentActivity;
mTitle = parentActivity.Title;
}
public override void OnProgressChanged(WebView view, int newProgress)
{
mParentActivity.Title = string.Format("Loading {0}%", newProgress);
mParentActivity.SetProgress(newProgress * 100);
if (newProgress==100) mParentActivity.Title=mTitle;
}
}
I open www.google.com in webview component and I want to see html source code
I don't believe that there is a way to obtain the HTML from the WebView.
Instead, you should grab the HTML yourself with a WebRequest, e.g. this handy StackOverflow answer.
I'm sharing some variables accross activities by using a class like this :
public class Globals {
static Boolean hint1_graph_type_switcher;
static Boolean hint2_stockview_valuation;
other variables ...
}
then I'm using these variables anywhere across my multiple activites with ...
if (Globals.hint2_stockview_valuation == false) {
....
}
pretty basic and it was working fine untill ...
I introduced some webview stuff like this:
//-----------------------------------------------------------
// open a webview with the NEWS when the more_arrow is clicked :
mNews.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String news_URL = "http://us.m.yahoo.com/w/yfinance/symbolheadlines/"+ ticker + "/?.intl=us&.lang=en";
Intent news_Webview_intent = new Intent(Chart_View.this, News_Webview.class);
news_Webview_intent.putExtra("NEWS_URL", news_URL);
startActivity(news_Webview_intent);
}
});
//-----------------------------------------------------------
and here's the News_Webview.class:
public class News_Webview extends Activity {
//
// http://www.chrisdanielson.com/tag/progressdialog/
//
String news_URL;
private WebView webview;
private ProgressDialog progressBar;
private static final String TAG = "Hub";
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.webview_news);
this.webview = (WebView)findViewById(R.id.webView);
Bundle extras = getIntent().getExtras();
if (this.getIntent().getExtras()!=null){
news_URL = extras.getString("NEWS_URL");
}
WebSettings settings = webview.getSettings();
settings.setJavaScriptEnabled(true);
webview.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);
final AlertDialog alertDialog = new AlertDialog.Builder(this).create();
progressBar = ProgressDialog.show(News_Webview.this, "", "Loading...");
webview.setWebViewClient(new WebViewClient() {
public boolean shouldOverrideUrlLoading(WebView view, String url) {
//Log.i(TAG, "Processing webview url click...");
Intent viewIntent = new Intent("android.intent.action.VIEW", Uri.parse(url));
startActivity(viewIntent);
return true;
}
public void onPageFinished(WebView view, String url) {
//Log.i(TAG, "Finished loading URL: " +url);
if (progressBar.isShowing()) {
progressBar.dismiss();
}
}
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
Log.e(TAG, "Error: " + description);
Toast.makeText(News_Webview.this, "Oh no! " + description, Toast.LENGTH_SHORT).show();
alertDialog.setTitle("Error");
alertDialog.setMessage(description);
alertDialog.setButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
return;
}
});
alertDialog.show();
}
});
webview.loadUrl(news_URL);
}
}
the problem now is that, when it "comes back" from this Activity, it looks like my Globals variables have disappeared ???
if (Globals.hint2_stockview_valuation == false) {
fires an error :
06-23 12:14:03.443:
ERROR/AndroidRuntime(2611): Caused by:
java.lang.NullPointerException
2 questions then :
Should I use something else than this "Global" class to share variables across activities ? Is it just bad practice to do this ?? I know that I can use the preferences but I thought it was quicker to do it this way (no need to "read" the preferences everytime I start a new activity ...
Any idea on WHY this is happening ? Should I "get back" my savedInstanceState in some way when my activity returns from the News_Webview.class ???
As always, thank you for your help.
H.
U could use intent.putExtra() for inter-activity interaction...
One thing(just for diagnostics) i would suggest is initializing the static variables to some value and then run the App... i suppose your global class is getting re-initialized when the intent started activity returns back...
I have used global variables, but in my case i kept them in an activity which never died. All other activities came after it and it worked perfectly fine...
The NullPointerException is bubbling up from the android runtime and has nothing to do with your Globals type.
I would like to integrate Twitter into my Android application so that I can post messages to Twitter.
This is how I do it
First i made a Dialog for the webview
Twitter_Dialog.java
public class Twitter_Dialog extends Dialog
{
static final int BLUE = 0xFF6D84B4;
static final float[] DIMENSIONS_DIFF_LANDSCAPE =
{ 20, 60 };
static final float[] DIMENSIONS_DIFF_PORTRAIT =
{ 40, 60 };
static final FrameLayout.LayoutParams FILL = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT);
static final int MARGIN = 4;
static final int PADDING = 2;
static final String DISPLAY_STRING = "touch";
private String mUrl;
private ProgressDialog mSpinner;
private WebView mWebView;
private LinearLayout mContent;
private TextView mTitle;
public Twitter_Dialog(Context context, String url)
{
super(context);
mUrl = url;
}
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
mSpinner = new ProgressDialog(getContext());
mSpinner.requestWindowFeature(Window.FEATURE_NO_TITLE);
mSpinner.setMessage("Loading...");
mContent = new LinearLayout(getContext());
mContent.setOrientation(LinearLayout.VERTICAL);
setUpTitle();
setUpWebView();
Display display = getWindow().getWindowManager().getDefaultDisplay();
final float scale = getContext().getResources().getDisplayMetrics().density;
int orientation = getContext().getResources().getConfiguration().orientation;
float[] dimensions = (orientation == Configuration.ORIENTATION_LANDSCAPE) ? DIMENSIONS_DIFF_LANDSCAPE : DIMENSIONS_DIFF_PORTRAIT;
addContentView(mContent, new LinearLayout.LayoutParams(display.getWidth() - ((int) (dimensions[0] * scale + 0.5f)), display.getHeight() - ((int) (dimensions[1] * scale + 0.5f))));
}
private void setUpTitle()
{
requestWindowFeature(Window.FEATURE_NO_TITLE);
Drawable icon = getContext().getResources().getDrawable(R.drawable.twitter_icon);
mTitle = new TextView(getContext());
mTitle.setText("Website");
mTitle.setTextColor(Color.WHITE);
mTitle.setTypeface(Typeface.DEFAULT_BOLD);
mTitle.setBackgroundColor(BLUE);
mTitle.setPadding(MARGIN + PADDING, MARGIN, MARGIN, MARGIN);
mTitle.setCompoundDrawablePadding(MARGIN + PADDING);
mTitle.setCompoundDrawablesWithIntrinsicBounds(icon, null, null, null);
mContent.addView(mTitle);
}
private void setUpWebView()
{
mWebView = new WebView(getContext());
mWebView.setVerticalScrollBarEnabled(false);
mWebView.setHorizontalScrollBarEnabled(false);
mWebView.setWebViewClient(new Twitter_Dialog.DialogWebViewClient());
mWebView.getSettings().setJavaScriptEnabled(true);
System.out.println(" mURL = "+mUrl);
mWebView.loadUrl(mUrl);
mWebView.setLayoutParams(FILL);
mContent.addView(mWebView);
}
private class DialogWebViewClient extends WebViewClient
{
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
{
view.loadUrl(url);
return true;
}
#Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl)
{
super.onReceivedError(view, errorCode, description, failingUrl);
Twitter_Dialog.this.dismiss();
}
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon)
{
super.onPageStarted(view, url, favicon);
mSpinner.show();
}
#Override
public void onPageFinished(WebView view, String url)
{
super.onPageFinished(view, url);
String title = mWebView.getTitle();
if (title != null && title.length() > 0){
mTitle.setText(title);
if(title.equals("Twitter")){
//This will close the Dialog after tweeting
Twitter_Dialog.this.dismiss();
}
}
mSpinner.dismiss();
}
}
}
//And then into your Main.java
public class Main extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
new Twitter_Dialog(Main.this,"http://twitter.com/?status="+Uri.encode("Twitter Post")).show();
}
}
In addition to d.'s solid choices, you could:
Use ACTION_SEND Intents with createChooser(), and if the user has a Twitter application installed (Twidroid) they can use it to update their status
Use an existing Twitter Java API, like JTwitter
Everything you need to know about communicating with Twitter is here.
For sending HTTP requests from your application, check out this guide.
You can use Twitter Helper for integrating Twitter into your Android app. Its very simple.
Try with this simple client TwitterEasyClient
Just add permissions in your manifest
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
And use it in this way:
//setup
TwitterDialogFragment twitterDialog = new TwitterDialogFragment.Builder("message","url.com") //
.callbackUrl("http://www.website.com") //
.consumerKey("XXXXXXXXXXXXXXXXXXXXXX") //
.consumerSecret("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX") //
.urlOAuth("oauth_verifier") //
.build();
//show the dialog
twitterDialog.show(getSupportFragmentManager(), TwitterDialogFragment.class.getSimpleName());
Always go for the latest technologies as twitter integration can be done easily using Twitter4j, also the APIs provided by twitter does change from time to time. Twiter sdk would a good option. U can find the details for it here for twitter4j.
For some people who want to use twitter4j and DialogFragment also support orientation changing check out my gist
https://gist.github.com/zeroarst/10071064adcf171277f9