I'm using a webview in my Android App.
I have 3 buttons 1 for a link to a website one to call a number and one email button.
At first calling my website button worked, http://www.somelink.com .
But my tel: link was not working. So I integrated some code that made my tel: button work.
The problem is that it has made my website or http: button not work?
The html button just does nothing when you click it.
package de.sonae.novolam;
import android.annotation.SuppressLint;
import android.app.Fragment;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebView;
import android.webkit.WebViewClient;
#SuppressLint("SetJavaScriptEnabled")
public class DFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View mainView = (View) inflater.inflate(R.layout.dfragment, container, false);
WebView webView = (WebView) mainView.findViewById(R.id.webview);
webView.getSettings().setJavaScriptEnabled(true);
webView.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView wv, String url) {
if (url.startsWith("tel:")) {
Intent intent = new Intent(Intent.ACTION_DIAL,
Uri.parse(url));
startActivity(intent);
}
return true;
}
});
webView.loadUrl("file:///android_asset/contact.html");
return mainView;
}
public boolean shouldOverrideUrlLoading(WebView webView, String url) {
if( url.startsWith("http:") || url.startsWith("https:") ) {
webView.loadUrl(url);
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity( intent );
}
else if (url.startsWith("mailto:")) {
}
// Otherwise allow the OS to handle it
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity( intent );
return true;
}
}
You have two shouldOverrideUrlLoading methods in your code. The only first one is actually called by a WebView. Move code from second shouldOverrideUrlLoading to the first and it will work.
webView.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView wv, String url) {
if (url.startsWith("tel:")) {
Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse(url));
startActivity(intent);
return true;
} else if( url.startsWith("http:") || url.startsWith("https:") ) {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(intent);
return true;
} else if (url.startsWith("mailto:")) {
// TODO : handle mail url
return true;
}
return false;
}
});
You need to tell the web view when you handled url loading by your self and when you want do delegate handling on it. Simply return true from shouldOverrideUrlLoading when you handled url loading by your own action. Return false otherwise:
webView.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView wv, String url) {
if (url.startsWith("tel:")) {
Intent intent = new Intent(Intent.ACTION_DIAL,
Uri.parse(url));
startActivity(intent);
return true; // we handled the url loading
}
return false; // let WebView handle this event
}
});
The method shouldOverrideUrlLoading should return true if you want to override (i.e., prevent default handling) or false if you want things to work as normal.
#Override
public boolean shouldOverrideUrlLoading(WebView wv, String url) {
if (url.startsWith("tel:")) {
Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse(url));
startActivity(intent);
return true;
}
return false;
}
Related
I am a beginner and building webview app with splash screen in AIED.
I want to add spinner loading for every page loading in webview. I mean when this webview loads after the splash screen, I can see home page of website when I open any other page. While loading that page I want to show spinner in the center of screen. When the page load the spinner should disappear.
I not know where to add the specific code.
Here is mainactivity.java
package com.mystore.mominbaba;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ImageView;
public class MainActivity extends Activity {
//private WebView webView = null;
private WebView mWebView;
private ImageView mSplashView;
private ValueCallback <Uri> mUploadMessage;
public ValueCallback <Uri[]> uploadMessage;
public static final int REQUEST_SELECT_FILE = 100;
private final static int FILECHOOSER_RESULTCODE = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mWebView = (WebView) findViewById(R.id.webview);
mSplashView = (ImageView) findViewById(R.id.splash);
mWebView.getSettings().setJavaScriptEnabled(true); // enable javascript
mWebView.getSettings().setLoadWithOverviewMode(true); //sets Overview to true
mWebView.getSettings().setUseWideViewPort(true); //sets wideviewport deleting whitespsce
mWebView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
mWebView.getSettings().setAllowFileAccess(true);
mWebView.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
mSplashView.setVisibility(View.GONE);
mWebView.setVisibility(View.VISIBLE);
}
});
mWebView.loadUrl("https://www.mominbaba.com");
mWebView.setVisibility(View.GONE);
mSplashView.setVisibility(View.VISIBLE);
mWebView.setWebChromeClient(new WebChromeClient() {
// For 3.0+ Devices (Start)
// onActivityResult attached before constructor
protected void openFileChooser(ValueCallback uploadMsg, String acceptType) {
mUploadMessage = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("image/*");
startActivityForResult(Intent.createChooser(i, "File Browser"), FILECHOOSER_RESULTCODE);
}
// For Lollipop 5.0+ Devices
public boolean onShowFileChooser(WebView mWebView, ValueCallback <Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {
if (uploadMessage != null) {
uploadMessage.onReceiveValue(null);
uploadMessage = null;
}
uploadMessage = filePathCallback;
Intent intent = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
intent = fileChooserParams.createIntent();
}
try {
startActivityForResult(intent, REQUEST_SELECT_FILE);
} catch (ActivityNotFoundException e) {
uploadMessage = null;
return false;
}
return true;
}
//For Android 4.1 only
protected void openFileChooser(ValueCallback <Uri> uploadMsg, String acceptType, String capture) {
mUploadMessage = uploadMsg;
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("image/*");
startActivityForResult(Intent.createChooser(intent, "File Browser"), FILECHOOSER_RESULTCODE);
}
protected void openFileChooser(ValueCallback <Uri> uploadMsg) {
mUploadMessage = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("image/*");
startActivityForResult(Intent.createChooser(i, "File Chooser"), FILECHOOSER_RESULTCODE);
}
});
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (requestCode == REQUEST_SELECT_FILE) {
if (uploadMessage == null)
return;
uploadMessage.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(resultCode, intent));
uploadMessage = null;
}
} else if (requestCode == FILECHOOSER_RESULTCODE) {
if (null == mUploadMessage)
return;
// Use MainActivity.RESULT_OK if you're implementing WebView inside Fragment
// Use RESULT_OK only if you're implementing WebView inside an Activity
Uri result = intent == null || resultCode != MainActivity.RESULT_OK ? null : intent.getData();
mUploadMessage.onReceiveValue(result);
mUploadMessage = null;
}
}
private class xWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && mWebView.canGoBack()) {
mWebView.goBack();
return true;
}
return super.
`onKeyDown` (keyCode, event);
}
}
Here is activity main.xml
<?xml version="1.0" encoding="utf-8"?>
<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">
<ImageView
android:id="#+id/splash"
android:scaleType="fitXY"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:visibility="gone"
android:src="#drawable/image_1"/>
<WebView
android:id="#+id/webview"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="visible"/>
</RelativeLayout>
Big Caveat: This solution won't completely hide the white screen(loading) on websites that has to download and load .js files especially if they are big.
First, you are using onPageFinished incorrectly. onPageFinished is always going to be called after every page load has finished. This means if you are navigating on your website, it will call onPageFinished every after you navigate a URL and the webview has finished loading it.
Here's an idea on how to do this:
First create an HTML page and design on how you want your spinner would look like. Save the HTML template as a string HTMLSpinner.
Then create a second webview and load the HTML template string to it
public WebView spinner;
spinner.loadData(HTMLSpinner, "text/html", "UTF-8");
Then modify your main mWebView.setWebViewClient like this
mWebView.setWebViewClient(new WebViewClient(){
#Override
public void onPageStarted(WebView view, final String url, Bitmap favicon) {
mWebView.setVisibility(View.GONE);
spinner.setVisibility(View.VISIBLE);
// YOUR LANDING PAGE
if(url.equals("https://www.mominbaba.com")){
mWebView.setVisibility(View.GONE);
mSplashView.setVisibility(View.VISIBLE);
}
}
#Override
public void onPageFinished(WebView view, String url) {
mWebView.setVisibility(View.VISIBLE);
spinner.setVisibility(View.GONE);
// YOUR LANDING PAGE
if(url.equals("https://www.mominbaba.com")){
mWebView.setVisibility(View.GONE);
mSplashView.setVisibility(View.VISIBLE);
}
}
});
That should swap the current webview that you see from the main webview to the loader. I have chosen to use a second webview because the asset that was given to was an animated SVG.
I have created a basic Activity with a WebView. I have added a method in the WebView which loads an error.html page from the asset folder when the WebView receives a HTTP error. I wanted to hide the Share menu item when this error.html page was loaded and so, I moved this to a new Activity.
Now, what's happening is, when there's a connectivity error, the default connectivity error of Android loads first and then the Activity transition takes place. Thus, even though the transition is working fine, users can see the deault Android connectivity error page for a few milliseconds. Is there any way in which I can hide that error page completely as such the users can only see my custom error page.
Here's my MainActivity.java:
package com.ananya.brokenhearts;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.webkit.WebChromeClient;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.Toast;
#SuppressWarnings("deprecation")
public class MainActivity extends AppCompatActivity
{
private WebView WebView;
private ProgressBar ProgressBar;
private LinearLayout LinearLayout;
private String currentURL;
#SuppressLint("SetJavaScriptEnabled")
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WebView = findViewById(R.id.webView);
ProgressBar = findViewById(R.id.progressBar);
LinearLayout = findViewById(R.id.layout);
ProgressBar.setMax(100);
WebView.loadUrl("https://www.brokenhearts.ml/index.html");
WebView.getSettings().setJavaScriptEnabled(true);
WebView.getSettings().setUserAgentString("Broken Hearts/1.0");
WebView.setWebViewClient(new WebViewClient()
{
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon)
{
LinearLayout.setVisibility(View.VISIBLE);
super.onPageStarted(view, url, favicon);
}
#Override
public void onPageFinished(WebView view, String url)
{
LinearLayout.setVisibility(View.GONE);
super.onPageFinished(view, url);
currentURL = url;
}
#Override
public void onReceivedError(WebView webview, int i, String s, String s1)
{
Intent intent = new Intent(MainActivity.this, ErrorActivity.class);
startActivity(intent);
finish();
}
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url2)
{
if (url2.contains("www.brokenhearts.ml"))
{
view.loadUrl(url2);
return false;
} else
{
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url2));
startActivity(intent);
return true;
}
}
});
WebView.setWebChromeClient(new WebChromeClient()
{
#Override
public void onProgressChanged(WebView view, int newProgress)
{
super.onProgressChanged(view, newProgress);
ProgressBar.setProgress(newProgress);
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(R.menu.menu, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch (item.getItemId())
{
case R.id.backward:
onBackPressed();
break;
case R.id.forward:
onForwardPressed();
break;
case R.id.refresh:
WebView.reload();
break;
case R.id.share:
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("text/plain");
shareIntent.putExtra(Intent.EXTRA_TEXT,currentURL);
shareIntent.putExtra(Intent.EXTRA_SUBJECT,"Copied URL");
startActivity(Intent.createChooser(shareIntent,"Share URL"));
break;
case R.id.update:
Intent intent = new Intent(MainActivity.this, UpdateActivity.class);
startActivity(intent);
finish();
break;
case R.id.exit:
new AlertDialog.Builder(this,R.style.AlertDialog)
.setIcon(R.drawable.ic_error_black_24dp)
.setTitle("Are you sure you want to exit?")
.setMessage("Tapping 'Yes' will close the app. Tap 'No' to continue using the app")
.setPositiveButton("Yes",
new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface dialog, int which)
{
finish();
}
})
.setNegativeButton("No", null)
.show();
break;
}
return super.onOptionsItemSelected(item);
}
private void onForwardPressed()
{
if (WebView.canGoForward())
{
WebView.goForward();
} else
{
Toast.makeText(this, "Can't go further", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onBackPressed ()
{
if (WebView.canGoBack())
{
WebView.goBack();
} else
{
new AlertDialog.Builder(this,R.style.AlertDialog)
.setIcon(R.drawable.ic_error_black_24dp)
.setTitle("Are you sure you want to exit?")
.setMessage("Tapping 'Yes' will close the app. Tap 'No' to continue using the app")
.setPositiveButton("Yes",
new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface dialog, int which)
{
finish();
}
})
.setNegativeButton("No", null)
.show();
}
}
}
Prior to this, I was directly loading the error.html page in the MainActivity itself when there was an error and thus, the default error page wasn't visible. But, I wanted to hide the Share button when error.html page was loaded. I didn't know how to do and I didn't get any response to that question where I had posted it. Thus, I thought of creating a seperate Activity to load the error.html which can let me hide the Share menu icon.
Also, I've tried to add the WebView.loadUrl("file:///android_asset/error.html"); in the same method before that intent hoping that it'll load before the Activity transition, however, that didn't help. I can still see the default Android connectivity error page.
Just to clarify, this is the default error page that I'm talking about: https://i.stack.imgur.com/bMMHh.png
and there's a custom one that I've made that I'm displaying now in the ErrorActivity.java.
What can I do about this?
Hide the webview when an error occured.
#Override
public void onReceivedError(WebView webview, int i, String s, String s1)
{
WebView.setVisibility(View.GONE);**hide the webview when an error occured**
Intent intent = new Intent(MainActivity.this, ErrorActivity.class);
startActivity(intent);
finish();
}
Regarding hiding the share menu icon, you could always use onPrepareOptionsMenu() to hide your share menu if there is any error flag.
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
menu.findItem(R.id.share).setVisible(!isPageError);
return true;
}
which would require you to have a isPageError boolean set to true in your
#Override
public void onReceivedError(WebView webview, int i, String s, String s1{
isPageError = true;
}
I have my WebViewFragment and of course i want to go back in the site im browsing but i have the error:
The method onBackPressed() is undefined for the type Fragment
Why? I don´t understand that?
What am i doing wrong?
Here´s my full webview code i´m using.
import android.app.Fragment;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.DownloadListener;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
public class WebViewFragment extends Fragment {
WebView webView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Retrieving the currently selected item number
int position = getArguments().getInt("position");
String url = getArguments().getString("url");
// List of rivers
String[] menus = getResources().getStringArray(R.array.menus);
// Creating view corresponding to the fragment
View v = inflater.inflate(R.layout.fragment_layout, container, false);
// Updating the action bar title
getActivity().getActionBar().setTitle(menus[position]);
//Initializing and loading url in webview
webView = (WebView)v.findViewById(R.id.webView);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setLoadsImagesAutomatically(true);
webView.getSettings().setBuiltInZoomControls(true);
webView.loadUrl(url);
webView.setWebChromeClient(new WebChromeClient());
webView.setWebViewClient(new WebViewClient(){
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url){
view.loadUrl(url);
return true;
}
});
webView.setDownloadListener(new DownloadListener() {
public void onDownloadStart(String url, String userAgent,
String contentDisposition, String mimetype,
long contentLength) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url));
startActivity(intent);
}
});
return v;
}
public void onBackPressed() {
if(webView.canGoBack()) {
webView.goBack();
} else {
super.onBackPressed();
}
}}
If i´m using:
public void onBackPressed() {
Fragment webview = getFragmentManager().findFragmentByTag("webview");
if (webview instanceof WebViewFragment) {
boolean goback = ((WebViewFragment)webview).canGoBack();
if (!goback)
super.onBackPressed();
}
}}
I have the errors:
The method canGoBack() is undefined for the type WebViewFragment
The method onBackPressed() is undefined for the type Fragment
Thank you dudes for your help!
Found the solution what is working for me in my fragment.
webView.setOnKeyListener(new OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
WebView webView = (WebView) v;
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
if (webView.canGoBack()) {
webView.goBack();
return true;
}
break;
}
}
return false;
}
});
return v;
I was reading over at the Android development website about using reflections. But I'm really not grasping how to use it. I need this Java file to run on a 1.5 (SDK3) device but just ignore the new code and it works fine on a 2.0 (SDK5) or later phone. I have this Activity (posted below) and it's a simple webview. However, I want to have geolocation enabled (even if it is only for 2.0 and later phones), since these APIs weren't introduced until SDK 5, and I would like the webview to be able to, at the very least, to load on a 1.5 phone rather than just crashing. How do I take my code and set it up using reflections?
package com.my.app;
import com.facebook.android.R;
//NEEDS TO BE IGNORED**********************************************************
import android.webkit.GeolocationPermissions;
import android.webkit.GeolocationPermissions.Callback;
//END**************************************************************************
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.webkit.CookieSyncManager;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;
//GeolocationPermissionsCallback NEEDS TO BE IGNORED**********************************************************
public class Places extends Activity implements GeolocationPermissions.Callback {
private ProgressDialog progressBar;
public WebView webview;
private static final String TAG = "Main";
String geoWebsiteURL = "http://google.com";
#Override
public void onStart()
{
super.onStart();
CookieSyncManager.getInstance().sync();
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
CookieSyncManager.createInstance(this);
CookieSyncManager.getInstance().startSync();
webview = (WebView) findViewById(R.id.webview);
webview.setWebViewClient(new testClient());
webview.getSettings().setJavaScriptEnabled(true);
webview.getSettings().setPluginsEnabled(true);
webview.loadUrl("http://google.com");
progressBar = ProgressDialog.show(Places.this, "", "Loading Page...");
//START GROUP OF CODE THAT NEEDS TO BE IGNORED************************************************************
webview.getSettings().setGeolocationEnabled(true);
GeoClient geo = new GeoClient();
webview.setWebChromeClient(geo);
}
public void invoke(String origin, boolean allow, boolean remember) {
}
final class GeoClient extends WebChromeClient {
#Override
public void onGeolocationPermissionsShowPrompt(String origin,
Callback callback) {
super.onGeolocationPermissionsShowPrompt(origin, callback);
callback.invoke(origin, true, false);
}
//END OF CODE THAT NEEDS TO BE IGNORED************************************************
}
private class testClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
Log.i(TAG, "Processing webview url click...");
view.loadUrl(url);
return true;
}
public void onPageFinished(WebView view, String url) {
Log.i(TAG, "Finished loading URL: " +url);
if (progressBar.isShowing()) {
progressBar.dismiss();
}
if (url.startsWith("mailto:") || url.startsWith("geo:") ||
url.startsWith("tel:")) {
Intent intent = new Intent
(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(intent);
}
}
}
//What's here????
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_BACK) && webview.canGoBack()) {
webview.goBack();
return true;
}
if (keyCode == KeyEvent.KEYCODE_SEARCH) {
Intent z = new Intent(this, Search.class);
startActivity(z);
}
return super.onKeyDown(keyCode, event);
}
public boolean onCreateOptionsMenu (Menu menu) {
super.onCreateOptionsMenu(menu);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected (MenuItem item) {
switch (item.getItemId()) {
case R.id.home:
Intent m = new Intent(this, Home.class);
startActivity(m);
return true;
case R.id.refresh:
webview.reload();
Toast.makeText(this, "Refreshing...", Toast.LENGTH_SHORT).show();
return true;
}
return false;
}
public void onStop()
{
super.onStop();
CookieSyncManager.getInstance().sync();
}
}
Step #1: Do not implement GeolocationPermissions.Callback on the activity. Use some other object for GeolocationPermissions.Callback, one implemented in a public Java class that you would not load if you are running on older versions of the OS.
Step #2: Read the answers and comments on the question you asked previously, which covers what you need to know for the rest. Notably, you would make GeoClient be a public Java class in its own file, so you can avoid loading it on older versions of the OS. Personally, I like the Stephen C answer, and I demonstrate its use here.
I was reading over http://android-developers.blogspot.com/2009/04/backward-compatibility-for-android.html But I'm really not grasping how to ignore certain lines of code. I have this Activity (posted below) and it's a simple webview. However, I want to have geolocation enabled(even if it is only for 2.0 and up phones), since these methods weren't introduced until SDK 5 (android 2.0) and I would like the webview to be able to at the very least be able to load on a 1.5 phone rather than just crashing. Could someone possibly show me how to take this code and make it ignore the lines of code that i pointed out with the starred comments when the users phone SDK is LESS than SDK 5?
package com.my.app;
import com.facebook.android.R;
//NEEDS TO BE IGNORED**********************************************************
import android.webkit.GeolocationPermissions;
import android.webkit.GeolocationPermissions.Callback;
//END**************************************************************************
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.webkit.CookieSyncManager;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;
//GeolocationPermissionsCallback NEEDS TO BE IGNORED**********************************************************
public class Places extends Activity implements GeolocationPermissions.Callback{
private ProgressDialog progressBar;
public WebView webview;
private static final String TAG = "Main";
String geoWebsiteURL = "http://google.com";
#Override
public void onStart()
{
super.onStart();
CookieSyncManager.getInstance().sync();
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
CookieSyncManager.createInstance(this);
CookieSyncManager.getInstance().startSync();
webview = (WebView) findViewById(R.id.webview);
webview.setWebViewClient(new testClient());
webview.getSettings().setJavaScriptEnabled(true);
webview.getSettings().setPluginsEnabled(true);
webview.loadUrl("http://google.com");
progressBar = ProgressDialog.show(Places.this, "", "Loading Page...");
//THIS NEEDS TO BE IGNORED************************************************************
webview.getSettings().setGeolocationEnabled(true);
GeoClient geo = new GeoClient();
webview.setWebChromeClient(geo);
}
public void invoke(String origin, boolean allow, boolean remember) {
}
final class GeoClient extends WebChromeClient {
#Override
public void onGeolocationPermissionsShowPrompt(String origin,
Callback callback) {
super.onGeolocationPermissionsShowPrompt(origin, callback);
callback.invoke(origin, true, false);
}
//END OF CODE THAT NEEDS TO BE IGNORED************************************************
}
private class testClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
Log.i(TAG, "Processing webview url click...");
view.loadUrl(url);
return true;
}
public void onPageFinished(WebView view, String url) {
Log.i(TAG, "Finished loading URL: " +url);
if (progressBar.isShowing()) {
progressBar.dismiss();
}
if (url.startsWith("mailto:") || url.startsWith("geo:") ||
url.startsWith("tel:")) {
Intent intent = new Intent
(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(intent);
}
}
}
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_BACK) && webview.canGoBack()) {
webview.goBack();
return true;
}
if (keyCode == KeyEvent.KEYCODE_SEARCH) {
Intent z = new Intent(this, Search.class);
startActivity(z);
}
return super.onKeyDown(keyCode, event);
}
public boolean onCreateOptionsMenu (Menu menu) {
super.onCreateOptionsMenu(menu);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected (MenuItem item) {
switch (item.getItemId()) {
case R.id.home:
Intent m = new Intent(this, Home.class);
startActivity(m);
return true;
case R.id.refresh:
webview.reload();
Toast.makeText(this, "Refreshing...", Toast.LENGTH_SHORT).show();
return true;
}
return false;
}
public void onStop()
{
super.onStop();
CookieSyncManager.getInstance().sync();
}
}
There are (at least) two possible solutions for your problem:
Different versions for different OS - create different builds of your software for different OS. This is a common approach, a lot of open source projects offer different builds for linux, windows, mac os. Your case is similiar, you could create different builds for android 1.5, 2.0, ...
One version for all Android OS - If you can find a way to detect the version of the OS at runtime, then you can redesign your code to run on different OS. You can add special classes for android 1.6 and 2.0 and make sure, that only the correct classes are loaded.
A quick example for your code:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// ...
progressBar = ProgressDialog.show(Places.this, "", "Loading Page...");
if (isGeolocationAvailable()) {
Android20Util.enableGeolocation(webview);
}
}
Android20Util contains some static methods, like:
public static void enableGeolocation(WebView webview) {
webview.getSettings().setGeolocationEnabled(true);
webview.setWebChromeClient(new GeoClient());
}