Send image from camera to Android webview - javascript

I have an architecture where I am having a webview in MainActivity of my Android app. A page having a "Take Photo" button loads whenever user opens the app. On clicking "Take Photo" button, javascript will call dispatchTakePictureIntent() method defined in the Android app, which will redirect user to the Camera. Once, the user clicks the photo and submits it, I want to send the photo back to JS which in turn will make a AJAX call to the server to store the image.
I am facing trouble in developing the flow once user submits the photo. In my current implementation, I am able to store the image file locally and retrieve a file path, but I am unable to figure out how to use this file path in JS to get the file and send it on the server. Kindly help me out with this.
I have taken reference from this article: https://developer.android.com/training/camera/photobasics#TaskPath
MainActivity.java
public class MainActivity extends Activity {
private static final String TAG = MainActivity.class.getSimpleName();
private static final String FILE_PATH_PREFIX = "file:";
private String imageFilePath;
private String callbackFunction;
#SuppressLint("SetJavaScriptEnabled")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AndroidPlatform.setUp(this, APPLICATION_NAME);
setContentView(R.layout.activity_main);
webView = (WebView) findViewById(R.id.webview);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setGeolocationEnabled(true);
webView.getSettings().setAppCacheEnabled(true);
webView.getSettings().setDatabaseEnabled(true);
webView.getSettings().setDomStorageEnabled(true);
webView.getSettings().setAllowFileAccess(true);
webView.getSettings().setGeolocationDatabasePath(getFilesDir().getPath());
webView.addJavascriptInterface(this, "Android");
webView.setWebChromeClient(new WebChromeClient());
webView.setWebViewClient(new WebViewClient());
webView.loadUrl("URL to the page having take photo button");
}
#JavascriptInterface
public void dispatchTakePictureIntent(String _callbackFunction) {
this.callbackFunction = _callbackFunction;
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
File photoFile = createImageFile();
if (photoFile != null) {
this.imageFilePath = FILE_PATH_PREFIX + photoFile.getAbsolutePath();
Uri photoURI = FileProvider.getUriForFile(this,
"com.example.fileprovider",
photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
} else {
Toast.makeText(getApplicationContext(), R.string.please_retry, Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(getApplicationContext(), R.string.no_camera_found, Toast.LENGTH_SHORT).show();
}
}
private File createImageFile() {
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "storephoto_" + timeStamp + "_";
File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = null;
try {
image = File.createTempFile(imageFileName,".jpg", storageDir);
} catch (IOException e) {
Log.e(TAG, "Exception in createImageFile:", e);
}
return image;
}
#TargetApi(Build.VERSION_CODES.KITKAT)
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_IMAGE_CAPTURE) {
if(resultCode == RESULT_OK && callbackFunction != null && imageFilePath != null) {
// What to do with imageFilePath?
//
// How to use it in Javascript to read and send image to backend server?
//
// Sample code if we send imageFilePath to JS:
// String callbackModule = String.format(TAKE_PICTURE_JS_MODULE, callbackFunction, imageFilePath);
// webView.evaluateJavascript(callbackModule, null);
}
}
}
}
Javascript
$takePhotoButton.click(function(e) {
e.preventDefault();
Android && Android.dispatchTakePictureIntent("takePhotoCallbackFn");
});
Note: Here it is necessary that user submits the photo through camera only and not via choosing/uploading an existing file.

Related

Android webview href not support in html page

I want to load to a about.html page inside asset folder by clicking a button in index.html inside android webview.
Here's the code:
Button:
About
Java:
WebView browser = (WebView) findViewById(webview);
browser.getSettings().setJavaScriptEnabled(true);
browser.setWebChromeClient(new WebChromeClient());
browser.loadUrl("file:///android_asset/www/index.html");
browser.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return false;
}
});
But the problem is when i click on button it doesn't load about.html but if I add a javascript function with below code it works.. but i want to use href.
Code:
<button onclick="about()">About</button>
<script>
function about() {
location.href = "about.html";
}
</script>
How do I solve it?
write an interface for TagHandler and in your fromHtml method check for the tag and handle it by loading the page
https://developer.android.com/reference/android/text/Html.html
try this code:
private void loadWebView(WebView webView,String htmlString)
{
try {
final String mimeType = "text/html";
final String encoding = "UTF-8";
WebViewClient yourWebClient = new WebViewClient()
{
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
{
// This line we let me load only pages inside Webpage
if ( url.contains("") == true )
// Load new URL Don't override URL Link
return false;
// Return true to override url loading (In this case do nothing).
return true;
}
};
// Get Web view
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setSupportZoom(true);
webView.getSettings().setBuiltInZoomControls(true);
webView.setWebViewClient(yourWebClient);
// Load URL
webView.loadDataWithBaseURL("", htmlString, mimeType, encoding, "");
} catch (Exception e) {
e.printStackTrace();
}
}
use it as:
loadWebView(browser, "file:///android_asset/www/index.html") //pass url

Java Android - Get an Image from a webview

So I load a page of a website and its show on my android APP via webview.
The website have several images on it; let's say the website page contains 3 images:
<img src="pic_mountain.jpg">
<img src="random_image.php">
<img src="pic_mountain_second.jpg">
my question is, how do I get each of the images above, so I can access each of it as Bitmap on my Java Android apps?
Here is working example to get HTML as string which is loaded in webview and how you can get image url from that after you can convert image url to bitmap.
set webview client to your webview like
webview.setWebViewClient(new WebClientClass());
The webview client is given below
public class WebClientClass extends WebViewClient {
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
if (progressDialog != null && progressDialog.isShowing())
progressDialog.dismiss();
wvAboutUs.evaluateJavascript(
"(function() { return ('<html>'+document.getElementsByTagName('html')[0].innerHTML+'</html>'); })();",
new ValueCallback<String>() {
#Override
public void onReceiveValue(String html) {
JsonReader reader = new JsonReader(new StringReader(html));
reader.setLenient(true);
try {
if (reader.peek() != JsonToken.NULL) {
if (reader.peek() == JsonToken.STRING) {
String msg = reader.nextString();
if (msg != null) {
Log.d("HTML", msg);
Pattern p = Pattern.compile("src=\"(.*?)\"");
Matcher m = p.matcher(msg);
if (m.find()) {
Log.d("HTML", m.group(1)); // This will print your image url
}
}
}
}
} catch (IOException e) {
Log.e("TAG", "MainActivity: IOException", e);
} finally {
try {
reader.close();
} catch (IOException e) {
}
}
}
});
}
}

Android WebView offline message for if no internet connetion

I am developing an android apps using WebView. I want to show custom message if device has no internet connection. I am new. I did this code but not show custom message as I write on HTML format. Please help me step bye step. I am using android studio 2.1 Thanks advance
package ideainnovative.bdsoeg;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import com.google.android.gms.appindexing.Action;
import com.google.android.gms.appindexing.AppIndex;
import com.google.android.gms.common.api.GoogleApiClient;
public class web extends AppCompatActivity {
private WebView mywebview;
/**
* ATTENTION: This was auto-generated to implement the App Indexing API.
* See https://g.co/AppIndexing/AndroidStudio for more information.
*/
private GoogleApiClient client;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_web);
mywebview = (WebView) findViewById(R.id.webView);
WebSettings webSettings = mywebview.getSettings();
webSettings.setJavaScriptEnabled(true);
mywebview.loadUrl("http://google.com/");
mywebview.setWebViewClient(new WebViewClient());
// ATTENTION: This was auto-generated to implement the App Indexing API.
// See https://g.co/AppIndexing/AndroidStudio for more information.
client = new GoogleApiClient.Builder(this).addApi(AppIndex.API).build();
}
#Override
public void onBackPressed() {
if(mywebview.canGoBack()){
mywebview.goBack();
} else{
super.onBackPressed();
}
}
#Override
public void onStart() {
super.onStart();
// ATTENTION: This was auto-generated to implement the App Indexing API.
// See https://g.co/AppIndexing/AndroidStudio for more information.
client.connect();
Action viewAction = Action.newAction(
Action.TYPE_VIEW, // TODO: choose an action type.
"web Page", // TODO: Define a title for the content shown.
// TODO: If you have web page content that matches this app activity's content,
// make sure this auto-generated web page URL is correct.
// Otherwise, set the URL to null.
Uri.parse("http://host/path"),
// TODO: Make sure this auto-generated app URL is correct.
Uri.parse("android-app://google.com")
);
AppIndex.AppIndexApi.start(client, viewAction);
}
private void loadError() {
String html = "<html><body><table width=\"100%\" height=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\">"
+ "<tr>"
+ "<td><div align=\"center\"><font color=\"red\" size=\"20pt\">Your device don't have active internet connection</font></div></td>"
+ "</tr>" + "</table></html></body>";
System.out.println("html " + html);
String base64 = android.util.Base64.encodeToString(html.getBytes(),
android.util.Base64.DEFAULT);
mywebview.loadData(base64, "text/html; charset=utf-8", "base64");
System.out.println("loaded html");
}
#Override
public void onStop() {
super.onStop();
// ATTENTION: This was auto-generated to implement the App Indexing API.
// See https://g.co/AppIndexing/AndroidStudio for more information.
Action viewAction = Action.newAction(
Action.TYPE_VIEW, // TODO: choose an action type.
"web Page", // TODO: Define a title for the content shown.
// TODO: If you have web page content that matches this app activity's content,
// make sure this auto-generated web page URL is correct.
// Otherwise, set the URL to null.
Uri.parse("http://host/path"),
// TODO: Make sure this auto-generated app URL is correct.
Uri.parse("android-app://ideainnovative.bdsoeg/http/host/path")
);
AppIndex.AppIndexApi.end(client, viewAction);
client.disconnect();
}
}
Use following method to check internet connection :
public boolean isNetworkAvailable(final Context context) {
final ConnectivityManager connectivityManager = ((ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE));
return connectivityManager.getActiveNetworkInfo() != null && connectivityManager.getActiveNetworkInfo().isConnected();
}
Before loading url to webview check internet connection.
if (isNetworkAvailable(context)) {
mywebview.loadUrl("http://google.com/");
} else {
loadError()
}
And now your activity :
public class web extends AppCompatActivity {
private WebView mywebview;
/**
* ATTENTION: This was auto-generated to implement the App Indexing API.
* See https://g.co/AppIndexing/AndroidStudio for more information.
*/
private GoogleApiClient client;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_web);
mywebview = (WebView) findViewById(R.id.webView);
WebSettings webSettings = mywebview.getSettings();
webSettings.setJavaScriptEnabled(true);
mywebview.setWebViewClient(new WebViewClient());
if (isNetworkAvailable(context)) {
mywebview.loadUrl("http://google.com/");
} else {
loadError()
}
// ATTENTION: This was auto-generated to implement the App Indexing API.
// See https://g.co/AppIndexing/AndroidStudio for more information.
client = new GoogleApiClient.Builder(this).addApi(AppIndex.API).build();
}
#Override
public void onBackPressed() {
if(mywebview.canGoBack()){
mywebview.goBack();
} else{
super.onBackPressed();
}
}
#Override
public void onStart() {
super.onStart();
// ATTENTION: This was auto-generated to implement the App Indexing API.
// See https://g.co/AppIndexing/AndroidStudio for more information.
client.connect();
Action viewAction = Action.newAction(
Action.TYPE_VIEW, // TODO: choose an action type.
"web Page", // TODO: Define a title for the content shown.
// TODO: If you have web page content that matches this app activity's content,
// make sure this auto-generated web page URL is correct.
// Otherwise, set the URL to null.
Uri.parse("http://host/path"),
// TODO: Make sure this auto-generated app URL is correct.
Uri.parse("android-app://google.com")
);
AppIndex.AppIndexApi.start(client, viewAction);
}
private void loadError() {
String html = "<html><body><table width=\"100%\" height=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\">"
+ "<tr>"
+ "<td><div align=\"center\"><font color=\"red\" size=\"20pt\">Your device don't have active internet connection</font></div></td>"
+ "</tr>" + "</table></html></body>";
System.out.println("html " + html);
myWebView.loadDataWithBaseURL(null, html, "text/html", "utf-8", null);
System.out.println("loaded html");
}
#Override
public void onStop() {
super.onStop();
// ATTENTION: This was auto-generated to implement the App Indexing API.
// See https://g.co/AppIndexing/AndroidStudio for more information.
Action viewAction = Action.newAction(
Action.TYPE_VIEW, // TODO: choose an action type.
"web Page", // TODO: Define a title for the content shown.
// TODO: If you have web page content that matches this app activity's content,
// make sure this auto-generated web page URL is correct.
// Otherwise, set the URL to null.
Uri.parse("http://host/path"),
// TODO: Make sure this auto-generated app URL is correct.
Uri.parse("android-app://ideainnovative.bdsoeg/http/host/path")
);
AppIndex.AppIndexApi.end(client, viewAction);
client.disconnect();
}
public boolean isNetworkAvailable(final Context context) {
final ConnectivityManager connectivityManager = ((ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE));
return connectivityManager.getActiveNetworkInfo() != null && connectivityManager.getActiveNetworkInfo().isConnected();
}
}

Get href value from anchor tag in Android WebView when link is clicked

I am loading a webpage in WebView. There is a link in the webpage, which on desktop will download the file, but in the app the link should display a Toast saying the link is disabled for the app.
I am not sure how to get the value from href of the anchor tag, when the link is clicked.
<a class="btn btn-primary" download="http://xx.xxx.com/wp-content/uploads/2015/11/abc-27-15.mp3" href="http://xx.xxx.com/wp-content/uploads/2015/11/abc-27-15.mp3">
<i class="fa fa-download"></i> Download Audio</a>
Can someone share an idea or any sample code on how to do this.
EDIT:1
Here is what I am doing currently:
private static final String URL = "http://xx.xxx.com/wp-content/uploads/";
webView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
WebView.HitTestResult hr = ((WebView) v).getHitTestResult();
String extra = hr.getExtra();
if (extra != null && extra.startsWith(URL) && extra.endsWith(".mp3")) {
Log.d("WebviewActivity", "Extra: " + extra);
Log.d("WebviewActivity", "Contains URL");
return true;
}
}
return false;
}
});
The problem with this approach is:
When i click on the link, i get the url in extra. It works fine till here. But, from next time, no matter where i click on the webview, the same extra is being returned. So even if i click on an image after i click on the url, i get the same url in the extra. Not sure if i doing anything wrong. Or is this the correct approach.
Please let me know if you need any details.
EDIT:2
private Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
// Get link-URL.
String url = (String) msg.getData().get("url");
// Do something with it.
if (url != null) {
Log.d(TAG, "URL: "+url);
}
}
};
webView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
WebView.HitTestResult hr = ((WebView) v).getHitTestResult();
if (hr.getType() == WebView.HitTestResult.SRC_ANCHOR_TYPE) {
Message msg = mHandler.obtainMessage();
webView.requestFocusNodeHref(msg);
}
}
return false;
}
});
webView.loadUrl(mUrl);
}
Now, i get the URL that is clicked in the last action_down event. How to get the current URL?
EDIT 3 (Attempt with webviewclient:
private class MyWebViewClient extends WebViewClient {
private static final String URL = "xx.xxx.com/wp-content/uploads/";
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
if (!isFinishing())
mProgressDialog.show();
}
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
mProgressDialog.dismiss();
}
#Override
public void onReceivedError(WebView view, int errorCode,
String description, String failingUrl) {
super.onReceivedError(view, errorCode, description, failingUrl);
Toast.makeText(WebviewActivity.this,
"Please check your internet " + "connection and try again",
Toast.LENGTH_SHORT).show();
}
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
Log.d("xxx", "Url: " + url);
if(url.contains(URL)) {
Log.d("xxx", "Url Contains: " + URL);
return true;
}
return false;
}
}
mMyWebViewClient = new MyWebViewClient();
webView.setWebViewClient(mMyWebViewClient);
Output in logcat when the link is clicked:
03-01 15:38:19.402 19626-19626/com.xx.xxx D/cr_Ime: [ImeAdapter.java:553] focusedNodeChanged: isEditable [false]
03-01 15:38:19.428 19626-19626/com.xx.xxx D/cr_Ime: [ImeAdapter.java:253] updateKeyboardVisibility: type [0->0], flags [0], show [true],
03-01 15:38:19.428 19626-19626/com.xx.xxx D/cr_Ime: [ImeAdapter.java:326] hideKeyboard
03-01 15:38:19.429 19626-19626/com.xx.xxx D/cr_Ime: [InputMethodManagerWrapper.java:56] isActive: true
03-01 15:38:19.429 19626-19626/com.xx.xxx D/cr_Ime: [InputMethodManagerWrapper.java:65] hideSoftInputFromWindow
Because you are using a WebView and the link is not Java script this is very easy to achieve with a WebViewClient which you can use to monitor your WebView
myWebView.setWebViewClient( new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// check something unique to the urls you want to block
if (url.contains("xx.xxx.com")) {
Toast.make... //trigger the toast
return true; //with return true, the webview wont try rendering the url
}
return false; //let other links work normally
}
} );
It's possible that because your URL ends in .mp3 the file is being treated as a resource. You should also override the shouldInterceptRequest method of the WebViewClient to check this.
#Override
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
String url = request.getUrl().toString();
Log.d("XXX", "Url from API21 shouldInterceptRequest : " + url);
if (url.contains(URL)) {
return new WebResourceResponse("text/html", "UTF-8", "<html><body>No downloading from app</body></html>");
} else {
return null;
}
}
public WebResourceResponse shouldInterceptRequest (WebView view, String url) {
Log.d("XXX", "Url from shouldInterceptRequest : " + url);
if (url.contains(URL)) {
return new WebResourceResponse("text/html", "UTF-8", "<html><body>No downloading from app</body></html>");
} else {
return null;
}
}
Most of the work can be done at the web page side itself. You have to write java script to identify which device is accessing the page (mobile, desktop etc) if its mobile then use java script binding technique to call the native android code to show Toast message.
http://developer.android.com/guide/webapps/webview.html
WebView webView = (WebView) findViewById(R.id.webview);
webView.addJavascriptInterface(new WebAppInterface(this), "Android");
WebAppInterface.java
public class WebAppInterface {
Context mContext;
/** Instantiate the interface and set the context */
WebAppInterface(Context c) {
mContext = c;
}
/** Show a toast from the web page */
#JavascriptInterface
public void showToast(String toast) {
Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show();
}
}
YourHTML Page (this sample got a button click)
<input type="button" value="Say hello" onClick="showAndroidToast('Hello
Android!')" />
<script type="text/javascript">
function showAndroidToast(toast) {
Android.showToast(toast);
}
</script>

Making facebook login work with an Android Webview

I am just trying to implement the facebook login on a WebView in Android. The problem is after I click the facebook button on my HTML page and insert the username and password on Facebook dialog. The url redirect is just giving me a black page.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
WebView webview = new WebView(this);
webview.setWebChromeClient(new WebChromeClient());
webview.getSettings().setPluginState(PluginState.ON);
webview.getSettings().setJavaScriptEnabled(true);
webview.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
webview.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
webview.setWebViewClient(new WebViewClient());
webview.loadUrl("http://peoplehunt.crowdscanner.com/hunt");
setContentView(webview);
This is the Facebook regular javascript API on my HTML page and this function gets called when the facebook button is clicked.
$("#login_facebook").click(function() {
FB.login(function(response) {
//This function should be called
if (response.authResponse) {
FB.api('/me?fields=name,email,picture,id&type=large', function(response) {
//console.log("email "+response.email);
$("#submitHandle").hide();
$("#loader").show();
//console.log('Good to see you, ' + response.picture + '.');
var theUsername = response.name;
theUsername = theUsername.replace(/ /g, '_')+"_"+response.id+"#meetforeal.com";
//console.log(theUsername);
$("input[name=email]").val(encodeURIComponent(response.email));
$("input[name=lastName]").val(encodeURIComponent(response.name));
$("input[name=avatarImage]").val(response.picture);
$("input[name=userName]").val(encodeURIComponent(theUsername));
$("#msg_twitter").fadeIn("slow");
$("#submitHandle").show();
$("#loader").hide();
$("#user").attr("action","/crowdmodule/auth/registerattendeefacebook");
$("#user").submit();
});
} else {
//console.log('User cancelled login or did not fully authorize.');
}
}, {scope: 'email'});
ANY ideas on how to get the response back after the redirect on the Facebook dialog page? THANKS.
I had the same issue on my android application.
The cause of the issue is FB login javascript opens a new page on a new window. Then it tries to close it and send some javascript auth codes back, after login success. WebView is typically "single window only" so it has no place to go back to, hence the blank screen.
Please follow flowing example from my working codes.
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#0099cc"
tools:context=".MyActivity"
android:id="#+id/webview_frame">
<WebView
android:id="#+id/webview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
The Webview of id "webview" is the main view for my content.
Below is my activity codes.
public class MyActivity extends Activity {
/* URL saved to be loaded after fb login */
private static final String target_url="http://www.example.com";
private static final String target_url_prefix="www.example.com";
private Context mContext;
private WebView mWebview;
private WebView mWebviewPop;
private FrameLayout mContainer;
private long mLastBackPressTime = 0;
private Toast mToast;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_urimalo);
// final View controlsView =
// findViewById(R.id.fullscreen_content_controls);
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptCookie(true);
mWebview = (WebView) findViewById(R.id.webview);
//mWebviewPop = (WebView) findViewById(R.id.webviewPop);
mContainer = (FrameLayout) findViewById(R.id.webview_frame);
WebSettings webSettings = mWebview.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setAppCacheEnabled(true);
webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
webSettings.setSupportMultipleWindows(true);
mWebview.setWebViewClient(new UriWebViewClient());
mWebview.setWebChromeClient(new UriChromeClient());
mWebview.loadUrl(target_url);
mContext=this.getApplicationContext();
}
private class UriWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
String host = Uri.parse(url).getHost();
//Log.d("shouldOverrideUrlLoading", url);
if (host.equals(target_url_prefix))
{
// This is my web site, so do not override; let my WebView load
// the page
if(mWebviewPop!=null)
{
mWebviewPop.setVisibility(View.GONE);
mContainer.removeView(mWebviewPop);
mWebviewPop=null;
}
return false;
}
if(host.equals("m.facebook.com"))
{
return false;
}
// Otherwise, the link is not for a page on my site, so launch
// another Activity that handles URLs
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(intent);
return true;
}
#Override
public void onReceivedSslError(WebView view, SslErrorHandler handler,
SslError error) {
Log.d("onReceivedSslError", "onReceivedSslError");
//super.onReceivedSslError(view, handler, error);
}
}
class UriChromeClient extends WebChromeClient {
#Override
public boolean onCreateWindow(WebView view, boolean isDialog,
boolean isUserGesture, Message resultMsg) {
mWebviewPop = new WebView(mContext);
mWebviewPop.setVerticalScrollBarEnabled(false);
mWebviewPop.setHorizontalScrollBarEnabled(false);
mWebviewPop.setWebViewClient(new UriWebViewClient());
mWebviewPop.getSettings().setJavaScriptEnabled(true);
mWebviewPop.getSettings().setSavePassword(false);
mWebviewPop.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
mContainer.addView(mWebviewPop);
WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj;
transport.setWebView(mWebviewPop);
resultMsg.sendToTarget();
return true;
}
#Override
public void onCloseWindow(WebView window) {
Log.d("onCloseWindow", "called");
}
}
}
The key for this issue is onCreateWindow. A new window is created and inserted to the frame layout and removed upon success. I added the removal at shouldOverrideUrlLoading.
Here is an example Android project:
Github: Android_Popup_Webview_handler_example
This is an Android Studio project showing how to handle popups in Android Webview.
Most open Source browsers do not support opening popups.
Popups are especially important in OAuth login used in a lot of websites (e.g., www.feedly.com).
The popups in this project opened in a dialog and can be dismissed by a close button or pressing Back or if the popup window closes itself (like what happens on most login authentication flow).
Regarding the best answer to this question, you just need to implement the onPageFinished method of the WebViewClient class that you use.
public void onPageFinished(WebView view, String url) {
// First, get the URL that Facebook's login button is actually redirecting you to.
// It should be something simulator to https://www.facebook.com/dialog/return/arbiter?relation=opener&close=true
String webUrl = webView.getUrl();
// Pass it to the LogCat so that you can then use it in the if statement below.
Log.d.println(TAG, webUrl);
if (url.startsWith("The url that you copied from the LogCat")) {
// Check whether the current URL is the URL that Facebook's redirecting you to.
// If it is - that's it - do what you want to after the logging process has finished.
return;
}
super.onPageFinished(view, url);
}
It worked just fine for me. Hope it helps you too :)
Override shouldOverrideUrlLoading() in your WebViewClient. Search for shouldOverrideUrlLoading here. Also, there is a parameter you can pass to facebook's login API; I think it's redirect_uri. That should help you recognize when the login is successful and in your shouldOVerrideUrlLoading(), you would just have to detect the url being loaded and if it is the redirect_uri you specified, then just return true in that method and close the webview or whatever you want to when the login is successful.
Above answer is too old and it does not work with latest Facebook sdk version 2.7. After spending 4 hours on it, I have found out few changes in it. Following code will work fine with latest SDK.
Below mentioned is the XML layout file.
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#0099cc"
tools:context=".MainActivity"
android:id="#+id/webview_frame">
<WebView
android:id="#+id/webView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</FrameLayout>
This is the Android Activity code snippet
public class MainActivity extends AppCompatActivity {
private WebView webView;
private WebView mWebviewPop;
private FrameLayout mContainer;
private Context mContext;
private String url = "https://www.YourWebsiteAddress.com";
private String target_url_prefix = "www.YourWebsiteAddress.com";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Get outer container
mContainer = (FrameLayout) findViewById(R.id.webview_frame);
webView = (WebView)findViewById(R.id.webView);
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setDomStorageEnabled(true);
webSettings.setAppCacheEnabled(true);
webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
webSettings.setSupportMultipleWindows(true);
//These two lines are specific for my need. These are not necessary
if (Build.VERSION.SDK_INT >= 21) {
webSettings.setMixedContentMode( WebSettings.MIXED_CONTENT_ALWAYS_ALLOW );
}
//Cookie manager for the webview
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptCookie(true);
webView.setWebViewClient(new MyCustomWebViewClient());
webView.setWebChromeClient(new UriWebChromeClient());
webView.loadUrl("https://www.YourWebsiteAddress.com");
mContext=this.getApplicationContext();
}
#Override
public void onBackPressed() {
if(webView.isFocused() && webView.canGoBack()) {
webView.goBack();
} else {
super.onBackPressed();
}
}
private class MyCustomWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
String host = Uri.parse(url).getHost();
if( url.startsWith("http:") || url.startsWith("https:") ) {
if(Uri.parse(url).getPath().equals("/connection-compte.html")) {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.YourWebsiteAddress.com"));
startActivity(browserIntent);
return true ;
}
if (host.equals(target_url_prefix)) {
if (mWebviewPop != null) {
mWebviewPop.setVisibility(View.GONE);
mContainer.removeView(mWebviewPop);
mWebviewPop = null;
}
return false;
}
if (host.equals("m.facebook.com") || host.equals("www.facebook.com") || host.equals("facebook.com")) {
return false;
}
// Otherwise, the link is not for a page on my site, so launch
// another Activity that handles URLs
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(intent);
return true;
}
// Otherwise allow the OS to handle it
else if (url.startsWith("tel:")) {
Intent tel = new Intent(Intent.ACTION_DIAL, Uri.parse(url));
startActivity(tel);
return true;
}
//This is again specific for my website
else if (url.startsWith("mailto:")) {
Intent mail = new Intent(Intent.ACTION_SEND);
mail.setType("application/octet-stream");
String AdressMail = new String(url.replace("mailto:" , "")) ;
mail.putExtra(Intent.EXTRA_EMAIL, new String[]{ AdressMail });
mail.putExtra(Intent.EXTRA_SUBJECT, "");
mail.putExtra(Intent.EXTRA_TEXT, "");
startActivity(mail);
return true;
}
return true;
}
#Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
Log.d("onReceivedSslError", "onReceivedSslError");
//super.onReceivedSslError(view, handler, error);
}
#Override
public void onPageFinished(WebView view, String url) {
if(url.startsWith("https://m.facebook.com/v2.7/dialog/oauth")){
if(mWebviewPop!=null)
{
mWebviewPop.setVisibility(View.GONE);
mContainer.removeView(mWebviewPop);
mWebviewPop=null;
}
view.loadUrl("https://www.YourWebsiteAddress.com");
return;
}
super.onPageFinished(view, url);
}
}
private class UriWebChromeClient extends WebChromeClient {
#Override
public boolean onCreateWindow(WebView view, boolean isDialog,
boolean isUserGesture, Message resultMsg) {
mWebviewPop = new WebView(mContext);
mWebviewPop.setVerticalScrollBarEnabled(false);
mWebviewPop.setHorizontalScrollBarEnabled(false);
mWebviewPop.setWebViewClient(new MyCustomWebViewClient());
mWebviewPop.getSettings().setJavaScriptEnabled(true);
mWebviewPop.getSettings().setSavePassword(false);
mWebviewPop.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
mContainer.addView(mWebviewPop);
WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj;
transport.setWebView(mWebviewPop);
resultMsg.sendToTarget();
return true;
}
#Override
public void onCloseWindow(WebView window) {
Log.d("onCloseWindow", "called");
}
}
}
My answer is essentially similar to some others here, in that I create a second WebView to host the Facebook login page, rather than attempting to solve the problem with redirects. However, I chose to place the login WebView in its own Fragment, and give it is own dedicated WebViewClient and WebChromeClient subclasses. I think this makes it a little easier to see what role each component plays, and which objects need which settings and behaviors.
I also make use of WebChromeClient.onCloseWindow() to detect when Facebook's JavaScript wants to close the login window. This is much more robust than the approach I originally pursued, from a different answer.
In your Activity layout, you'll have the "primary" WebView, which hosts the comments, and a container for the FacebookWebLoginFragment. The login Fragment is created on-the-fly, when it's needed, and then removed when Facebook's login JavaScript requests that its window be closed.
My Activity layout looks like this:
<include layout="#layout/toolbar_common" />
<FrameLayout
android:id="#+id/main_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="#+id/web_view_fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:overScrollMode="never"
/>
<!-- Used for Facebook login associated with comments -->
<FrameLayout
android:id="#+id/facebook_web_login_fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:overScrollMode="never"
android:visibility="gone"
/>
</FrameLayout>
Within your Activity, you'll need code to show and hide the Facebook web login fragment. I use the Otto event bus, so I have event handlers like the ones below. (Nothing here is specific to this problem; I include this code just to give you a sense of how the login Fragment fits into the overall structure.)
#Subscribe
public void onShowFacebookWebLoginEvent(ShowFacebookWebLoginEvent event) {
FacebookWebLoginFragment existingFragment = getFacebookWebLoginFragment();
if (existingFragment == null) {
mFacebookWebLoginFragmentContainer.setVisibility(View.VISIBLE);
createFacebookWebLoginFragment(event);
}
}
#Subscribe
public void onHideFacebookWebLoginEvent(HideFacebookWebLoginEvent event) {
FacebookWebLoginFragment existingFragment = getFacebookWebLoginFragment();
if (existingFragment != null) {
mFacebookWebLoginFragmentContainer.setVisibility(View.GONE);
FragmentManager fm = getSupportFragmentManager();
fm.beginTransaction()
.remove(existingFragment)
.commit();
}
}
#Nullable
private FacebookWebLoginFragment getFacebookWebLoginFragment() {
FragmentManager fm = getSupportFragmentManager();
return (FacebookWebLoginFragment) fm.findFragmentById(R.id.facebook_web_login_fragment_container);
}
private void createFacebookWebLoginFragment(ShowFacebookWebLoginEvent event) {
FragmentManager fm = getSupportFragmentManager();
FacebookWebLoginFragment fragment = (FacebookWebLoginFragment) fm.findFragmentById(R.id.facebook_web_login_fragment_container);
if (fragment == null) {
fragment = FacebookWebLoginFragment.newInstance(event.getOnCreateWindowResultMessage());
fm.beginTransaction()
.add(R.id.facebook_web_login_fragment_container, fragment)
.commit();
}
}
While the FacebookWebLoginFragment is around, it should be given authority to handle device back-button presses. This is important because the Facebook login flow includes the ability to navigate away from the login page, and the user will expect the back button to return them to login. So, in my Activity, I have this:
#Override
public void onBackPressed() {
boolean handled = false;
FacebookWebLoginFragment facebookWebLoginFragment = getFacebookWebLoginFragment();
if (facebookWebLoginFragment != null) {
handled = facebookWebLoginFragment.onBackPressed();
}
if (!handled) {
WebViewFragment fragment = getWebViewFragment();
if (fragment != null) {
handled = fragment.onBackPressed();
}
}
if (!handled) {
finish();
}
}
The layout for FacebookWebLoginFragment is extremely simple:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<WebView
android:id="#+id/web_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</FrameLayout>
Here's the FacebookWebLoginFragment code. Note that it relies on a subclass of WebChromeClient to detect when the Facebook login JavaScript is ready to close the window (i.e., remove the fragment). Note also that there is no direct communication between this login WebView and the primary WebView, which contains the comments UI; the auth token is passed along via a third-party cookie, which is why you have to be sure to enable third-party cookie support on your primary WebView.
import android.graphics.Bitmap;
import android.net.Uri;
import android.net.http.SslError;
import android.os.Bundle;
import android.os.Message;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.SslErrorHandler;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.FrameLayout;
import butterknife.Bind;
import butterknife.ButterKnife;
/**
* Hosts WebView used by Facebook web login.
*/
public class FacebookWebLoginFragment extends BaseFragment {
private static final String LOGTAG = LogHelper.getLogTag(FacebookWebLoginFragment.class);
#Bind(R.id.web_view) WebView mFacebookLoginWebView;
private WebChromeClient mFacebookLoginWebChromeClient;
private Message onCreateWindowResultMessage;
public static FacebookWebLoginFragment newInstance(Message onCreateWindowResultMessage) {
FacebookWebLoginFragment fragment = new FacebookWebLoginFragment();
fragment.onCreateWindowResultMessage = onCreateWindowResultMessage;
return fragment;
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.frag_facebook_web_login, container, false);
ButterKnife.bind(this, rootView);
return rootView;
}
#Override
public void onViewCreated(View v, #Nullable Bundle savedInstanceState) {
super.onViewCreated(v, savedInstanceState);
mFacebookLoginWebView.setVerticalScrollBarEnabled(false);
mFacebookLoginWebView.setHorizontalScrollBarEnabled(false);
mFacebookLoginWebView.setWebViewClient(new FacebookLoginWebViewClient());
mFacebookLoginWebView.getSettings().setJavaScriptEnabled(true);
mFacebookLoginWebView.getSettings().setSavePassword(false);
mFacebookLoginWebView.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
mFacebookLoginWebChromeClient = makeFacebookLoginWebChromeClient();
mFacebookLoginWebView.setWebChromeClient(mFacebookLoginWebChromeClient);
WebView.WebViewTransport transport = (WebView.WebViewTransport) onCreateWindowResultMessage.obj;
transport.setWebView(mFacebookLoginWebView);
onCreateWindowResultMessage.sendToTarget();
onCreateWindowResultMessage = null; // This seems to eliminate a mysterious crash
}
#Override
public void onDestroy() {
mFacebookLoginWebChromeClient = null;
super.onDestroy();
}
/**
* Performs fragment-specific behavior for back button, and returns true if the back press
* has been fully handled.
*/
public boolean onBackPressed() {
if (mFacebookLoginWebView.canGoBack()) {
mFacebookLoginWebView.goBack();
} else {
closeThisFragment();
}
return true;
}
private void closeThisFragment() {
EventBusHelper.post(new HideFacebookWebLoginEvent());
}
class FacebookLoginWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// Only allow content from Facebook
Uri uri = Uri.parse(url);
String scheme = uri.getScheme();
if (scheme != null && (TextUtils.equals(scheme, "http") || TextUtils.equals(scheme, "https"))) {
if (UriHelper.isFacebookHost(uri)) {
return false;
}
}
return true;
}
}
private WebChromeClient makeFacebookLoginWebChromeClient() {
return new WebChromeClient() {
#Override
public void onCloseWindow(WebView window) {
closeThisFragment();
}
};
}
}
Now, the trickiest bit is making the changes necessary to your existing WebView, since it's likely you've already got a fair amount of code in place around it, and you'll need to make sense of what needs to change.
First, make sure you have JavaScript enabled, and that it supports multiple windows.
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setSupportMultipleWindows(true);
You do not need to call setJavaScriptCanOpenWindowsAutomatically(true).
Looking at some of the other answers, you might think you need to monkey with the WebViewClient that's assigned to your WebView, and override shouldOverrideUrlLoading(). This is not necessary. What's important is the WebChromeClient, which needs to override onCreateWindow().
So... next, assign a custom WebChromeClient subclass to your WebView:
mWebView.setWebChromeClient(new WebChromeClient() {
#Override
public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg) {
String url = null;
Message href = view.getHandler().obtainMessage();
if (href != null) {
view.requestFocusNodeHref(href);
url = href.getData().getString("url");
}
LogHelper.d(LOGTAG, "onCreateWindow: " + url);
// Unfortunately, url is null when "Log In to Post" button is pressed
if (url == null || UriHelper.isFacebookHost(Uri.parse(url))) {
// Facebook login requires cookies to be enabled, and on more recent versions
// of Android, it's also necessary to enable acceptance of 3rd-party cookies
// on the WebView that hosts Facebook comments
CookieHelper.setAcceptThirdPartyCookies(mWebView, true);
EventBusHelper.post(new ShowFacebookWebLoginEvent(resultMsg));
} else {
LogHelper.d(LOGTAG, "Ignoring request from js to open new window for URL: " + url);
}
return true;
}
});
You'll notice this is the second call to UriHelper.isFacebookHost(). I don't have a bullet-proof approach to determining this, but here's what I do:
public static boolean isFacebookHost(Uri uri) {
if (uri != null && !TextUtils.isEmpty(uri.getHost())) {
String host = uri.getHost().toLowerCase();
return host.endsWith("facebook.com") || host.endsWith("facebook.net");
}
return false;
}
You'll also notice the call to CookieHelper.setAcceptThirdPartyCookies(). Here's the code for that:
public static void setAcceptThirdPartyCookies(WebView webView, boolean accept) {
CookieManager cookieManager = CookieManager.getInstance();
// This is a safeguard, in case you've disabled cookies elsewhere
if (accept && !cookieManager.acceptCookie()) {
cookieManager.setAcceptCookie(true);
}
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
cookieManager.setAcceptThirdPartyCookies(webView, accept);
}
}
One more thing that trips some people up is the configuration of "Valid OAuth redirect URIs" in the Facebook dev settings. If you see an error like this in your logs:
URL Blocked: This redirect failed because the redirect URI is not whitelisted in the app’s Client OAuth Settings. Make sure Client and Web OAuth Login are on and add all your app domains as Valid OAuth Redirect URIs.
... then you'll want to check out this answer: https://stackoverflow.com/a/37009374
Have fun! A complicated solution to what seems like a pretty simple problem. On the positive side, Android has given developers a ton of control here.
This code works for me! I have a LIKE, SHARE, Comments button on my page.
private lateinit var myWebView: WebView;
private val target_url = "https://www.webkomph.com"
private val target_url_prefix = "webkomph.com"
private var mContext: Context? = null
private var mWebviewPop: WebView? = null
private var mContainer: ConstraintLayout? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
val cookieManager = CookieManager.getInstance();
cookieManager.setAcceptCookie(true)
myWebView = findViewById(R.id.webkom_site);
mContainer = findViewById(R.id.webview_frame);
val webkomBlue = Color.parseColor("#1c71bc")
myWebView.setBackgroundColor(webkomBlue);
myWebView.background
val webSettings = myWebView.settings;
webSettings.setJavaScriptEnabled(true);
webSettings.setAppCacheEnabled(true);
webSettings.javaScriptCanOpenWindowsAutomatically = true;
webSettings.setSupportMultipleWindows(true)
myWebView.setWebViewClient(UriWebViewClient())
myWebView.setWebChromeClient(UriChromeClient())
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
cookieManager.setAcceptThirdPartyCookies(myWebView, true)
}
myWebView.loadUrl(target_url);
mContext = this.applicationContext
}
override fun onBackPressed() {
if (myWebView.canGoBack()) {
myWebView.goBack()
} else {
super.onBackPressed()
}
}
inner class UriWebViewClient : WebViewClient() {
override fun shouldOverrideUrlLoading(
view: WebView,
url: String
): Boolean {
val host = Uri.parse(url).host
//Log.d("shouldOverrideUrlLoading", url);
if(host == null || host == target_url_prefix) {
// This is my web site, so do not override; let my WebView load
// the page
if (mWebviewPop != null) {
mWebviewPop!!.setVisibility(View.GONE)
mContainer?.removeView(mWebviewPop)
mWebviewPop = null
}
return false
}
if (host == "m.facebook.com" || host == "www.facebook.com" || url.contains("ret=login")) {
return false
}
// Otherwise, the link is not for a page on my site, so launch
// another Activity that handles URLs
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
startActivity(intent)
return true
}
override fun onPageFinished(view: WebView?, url: String) {
// Facebook redirects to this url once a user has logged in, this is a blank page so we override this
// http://www.facebook.com/connect/connect_to_external_page_widget_loggedin.php?............
if (url.contains("plugins/close_popup.php?reload") || url.contains("dialog/close_window") || url.contains("facebook.com/dialog/plugin.optin?")) {
if(mWebviewPop != null){
mWebviewPop!!.visibility = View.GONE
mContainer!!.removeView(mWebviewPop)
mWebviewPop = null
if(myWebView != null && (url.contains("dialog/close_window") || url.contains("facebook.com/dialog/plugin.optin?"))){
myWebView?.reload();
}
}
return
}
super.onPageFinished(view, url)
}
override fun onReceivedSslError(
view: WebView, handler: SslErrorHandler,
error: SslError
) {
Log.d("onReceivedSslError", "onReceivedSslError")
//super.onReceivedSslError(view, handler, error);
}
}
inner class UriChromeClient : WebChromeClient() {
override fun onCreateWindow(
view: WebView, isDialog: Boolean,
isUserGesture: Boolean, resultMsg: Message
): Boolean {
mWebviewPop = WebView(mContext)
mWebviewPop!!.setVerticalScrollBarEnabled(false)
mWebviewPop!!.setHorizontalScrollBarEnabled(false)
mWebviewPop!!.setWebViewClient(UriWebViewClient())
mWebviewPop!!.getSettings().setJavaScriptEnabled(true)
mWebviewPop!!.getSettings().setSavePassword(false)
mWebviewPop!!.layoutParams = FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
mContainer?.addView(mWebviewPop)
val transport = resultMsg.obj as WebViewTransport
transport.webView = mWebviewPop
resultMsg.sendToTarget()
return true
}
override fun onCloseWindow(window: WebView) {
Log.d("onCloseWindow", "called")
}
}
Try moving your webview to xml layout file. The blank page error was caused due to js script fail while redirecting oAuth login to authorization acceptance page. You can overcome this issue by moving your webview into xml layout.
Probably not an always viable answer, but another option is to switch from "popup then JS" style OAuth login to the non-popup "redirect_uri" OAUth style, where it sends them to the login page, then after success/failure they get sent to "some uri err other" (ex: another page on your own website) that completes the authentication. FWIW.
FWIW where facebook says "if you're doing WebView redirect them to https://www.facebook.com/connect/login_success.html" my hunch is that that's for the case of (only having a single WebView and) using OAuth to login, so they'd add some auth params to the login_success.html that you could then glean, so not the normal web flow...
Another possibility might be to override the javascript postMessage function so you can capture what it was about to return to the parent window.

Categories

Resources