load intent inside shouldOverrideUrlLoading - android

I have a real big problem implementing loading a intent from inside shouldOverrideUrlLoading.
I believe it has to do with the way i have structured my application.
Here is my code:
VariablesStorage.class
public class VariablesStorage
{
private static VariablesStorage instance;
public static Context webViewContext;
public WebView webView;
public static void initInstance()
{
if (instance == null)
{
// Create the instance
instance = new VariablesStorage();
}
}
public static VariablesStorage getInstance()
{
// Return the instance
return instance;
}
private VariablesStorage()
{
}
public void loadWebView() {
webView.getSettings().setJavaScriptEnabled(true);
if (isOnline())
{
webView.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.startsWith("inapp://")) {
Intent intent = new Intent(this,profilepictureview.class);
intent.putExtra("img",Uri.parse(url).getHost().toString());
startActivity(intent);
}else
{
view.getContext().startActivity(
new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
}
return true;
}
#Override
public void onReceivedError( WebView view, int errorCode, String description, String failingUrl)
{
}
#Override
public void onPageFinished(WebView view, String url) {
if(mProgress.isShowing()) {
mProgress.dismiss();
}
}
});
webView.loadUrl(Url);
}else
{
webView.loadData(customHtml, "text/html;charset=utf-8", "UTF-8");
}
}
}
and my webview activity where i call VariablesStorage.getInstance().loadWebView();
WebViewActivity.class
public class WebViewActivity extends Activity {
SharedPreferences pref;
TextView textView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.webviewtab);
VariablesStorage.getInstance().webViewContext = this;
VariablesStorage.getInstance().webView = (WebView) findViewById(R.id.webView);
VariablesStorage.getInstance().loadWebView();
}
So when i am adding this code inside shouldOverrideUrlLoading
Intent intent = new Intent(this,profilepictureview.class);
intent.putExtra("img",Uri.parse(url).getHost().toString());
startActivity(intent);
i am getting this error:
The constructor Intent(new WebViewClient(){}, Class<profilepictureview>) is undefined
Any help implementing this one?
Thanks.

As the error says, Intent doesn't have a constructor that takes WebViewClient(){} as a parameter which is what this is referring to in this situation. See Intent Constructors
What you probably want is
Intent intent = new Intent(webViewContext,profilepictureview.class);
but you will want to initialize webViewContext first.
Edit
startActivity also, needs a Context. Try this
webViewContext.startActivity(intent);

Keeping a static reference to an activity's context is going to cause you problems. All views (including WebView) have getContext(), so use view.getContext() rather than 'this' or 'webViewContext' when creating the Intent.
Also, you're trying to start an activity named 'profilepictureview', which sounds more like a View rather than an Activity?

Related

(Xamarin - Android) Call a public method in the Activity class from another class?

I develop an app on Xamarin. I try to hide image when webview page loaded. I try different methods like call public function or access imageview from another class.
I read This but it doesn't work on Xamarin.
So I try something that
[Activity(Label = "XamarinWebView", Theme = "#android:style/Theme.Black.NoTitleBar", MainLauncher = true)]
public class MainActivity : Activity
{
WebView app_view = null;
WebSettings app_web_settings = null;
WebChromeClient web_client;
MyWebViewClient my_web_client;
ImageView my_splash = null;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.Main);
app_view = FindViewById(Resource.Id.webViewapp) as WebView;
my_web_client = new MyWebViewClient(this.ApplicationContext);
app_view.SetWebViewClient(my_web_client);
string app_url = "file:///android_asset/app_pages/test.html";
app_view.LoadUrl(app_url);
my_splash = FindViewById(Resource.Id.imageSplash) as ImageView;
my_splash.SetImageDrawable(GetDrawable(Resource.Drawable.splash));
}
public void HideSplash()
{
my_splash.Visibility = ViewStates.Gone;
}
}
In this class I can get WebView page loading status.
public class MyWebViewClient : WebViewClient
{
Context context;
public MyWebViewClient(Context _context) {
this.context = _context;
}
public override void OnPageStarted(WebView view, string url, Android.Graphics.Bitmap favicon)
{
base.OnPageStarted(view, url, favicon);
}
public override void OnPageFinished(WebView view, string url)
{
base.OnPageFinished(view, url);
**I need to change visible my_splash**
}
}
With Jason's advice I try something that and it works.
public class MainActivity : Activity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
.
.
.
my_web_client = new MyWebViewClient(this);
.
.
.
}
public void HideSplash()
{
my_splash.Visibility = ViewStates.Gone;
}
}
public class MyWebViewClient : WebViewClient
{
MainActivity act;
public MyWebViewClient(MainActivity activity)
{
this.act = activity;
}
public override void OnPageFinished(WebView view, string url)
{
base.OnPageFinished(view, url);
act.Hide_Splash();
}
}
A much easier approach to getting the activity from another class, which is also less error-prone and less likely to cause memory leaks would be to get the activity from the view context.
In your MyWebViewClient class:
public override void OnPageFinished(WebView view, string url)
{
base.OnPageFinished(view, url);
(view.Context as MainActivity).HideSplash();
}
Or if you're not sure if the context will always be MainActivity you could use pattern matching which covers the null check:
public override void OnPageFinished(WebView view, string url)
{
base.OnPageFinished(view, url);
if(view.Context is MainActivity mainActivity)
{
mainActivity.HideSplash();
}
}
Using an approach like this is much easier to maintain down the road.

How to restrict to call shouldOverrideUrlLoading when first time webview loading in fragment

In my app, there are four tabs and in the second tab, I am trying to load webview...
after disable shouldOverrideUrlLoading it perfectly load webview in fragment...
but with shouldOverrideUrlLoading method, it redirects on new activity...
But what I want is to load webview first on fragment and after clicking on any content link it should be redirected on new activity
private void setUpWebView() {
WebSettings ws = webView.getSettings();
ws.setJavaScriptEnabled(true);
ws.setAllowFileAccess(true);
webView.setScrollContainer(false);
webView.setWebViewClient(new WebViewClient());
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
mContext = context;
}
private class WebViewClient extends android.webkit.WebViewClient{
#Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request)
{
Intent intent = new Intent(getContext(),WebViewShowActivity.class);
startActivity(intent);
return true;
}
}
You can check condition
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request)
{
if (view.getUrl()!=baseUrl) {
Intent intent = new Intent(getContext(), WebViewShowActivity.class);
startActivity(intent);
return true;
}else {
return false;
}
}
To load url in webview you should load it in webview object returned in callback that is "view" and to open clicked links from webview content you should check request and load that in new activity.
webview.setWebViewClient(new WebViewClient() {
public boolean shouldOverrideUrlLoading(WebView view, String request) {
if (request != null && request.toString().startsWith("http://")) { //comparison params is upto your requirements
Intent intent = new Intent(MainActivity.this, secondactivity.class);
startActivity(intent);
return true;
}
return super.shouldOverrideUrlLoading(view, request);
}
});
public class WebViewJavaScriptInterface {
public Context context;
public WebViewJavaScriptInterface(Context context) {
this.context = context;
}
#JavascriptInterface
public void openPost(String url,String posttitle) {
String postUrl = "https://google.in"+url;
String postTitle = posttitle;
Log.d("POSTURL",postUrl);
Intent intent = new Intent(getContext(), WebViewShowActivity.class);
intent.putExtra("linkUrl",postUrl);
intent.putExtra("postTitle",postTitle);
startActivity(intent);
}
#JavascriptInterface
public void openVideo(String url) {
String youtubeUrl = url;
Log.d("YoutubeURL",youtubeUrl);
ForTrainertUtil.playPostVideoForYoutubeID(context,youtubeUrl);
}
}
this is how we can handle click event from web page through JavaScript..
when I click on a specific content of web page it handle associate method in android.

Activity finishes too quickly when loading for the first time at first launch

Am using this code to make an Activity load only when the app is launched for the first time but am having an issue, the Activity that is supposes to launch for the first time is a WebView, and while the WebView is loading the Activity finishes too quickly. This is the code am using to make the Activity load for the first time.
count = readSharedPreferenceInt("cntSP","cntKey");
if(count==0){
Intent intent = new Intent();
intent.setClass(MainActivity.this, TemporaryActivity.class);
startActivity(intent);
count++;
writeSharedPreference(count,"cntSP","cntKey");
}
//Read from Shared Preferance
public int readSharedPreferenceInt(String spName,String key){
SharedPreferences sharedPreferences = getSharedPreferences(spName,Context.MODE_PRIVATE);
return tempInt = sharedPreferences.getInt(key, 0);
}
//write shared preferences in integer
public void writeSharedPreference(int ammount,String spName,String key ){
SharedPreferences sharedPreferences = getSharedPreferences(spName, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putInt(key, ammount);
editor.commit();
}
This is the code for the activity that loads for the first time
public class Reg_Status extends AppCompatActivity {
Context a;
private ProgressBar pBar;
/* renamed from: com.partners.app.Confmap.1 */
class C01561 extends WebViewClient {
C01561() {
}
public boolean shouldOverrideUrlLoading(WebView view, String url) {
return false;
}
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
Reg_Status.this.pBar.setVisibility(ProgressBar.VISIBLE);
}
public void onPageFinished(WebView view, String url) {
Reg_Status.this.pBar.setVisibility(ProgressBar.INVISIBLE);
}
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
view.loadUrl(Config.URL_INTERNET_ERROR);
Reg_Status.this.pBar.setVisibility(ProgressBar.VISIBLE);
}
}
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView((int) R.layout.activity_reg_status);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
this.pBar = (ProgressBar) findViewById(R.id.pBar);
WebView webView = (WebView) findViewById(R.id.wView_reg);
webView.getSettings().setSupportZoom(true);
webView.getSettings().setJavaScriptEnabled(true);
webView.setWebViewClient(new C01561());
webView.loadUrl(Config.URL_REG);
}
Okay. You have this method, onPageFinished(), implemented and do that snippet you are doing it inside onCreate() inside that method.
public void onPageFinished(WebView view, String url) {
//You code, which you had put inside onCreate() should go here.
}
EDIT
Intent intent = new Intent(MainActivity.this, TemporaryActivity.class);
startActivity(intent);
...
NEW EDIT
public class C01561 extends WebViewClient {
private Context context;
C01561(Context context) {
this.context = context;
}
public void onPageFinished(WebView view, String url) {
Reg_Status.this.pBar.setVisibility(ProgressBar.INVISIBLE);
Intent intent = new Intent(context, TemporaryActivity.class);
startActivity(intent);
}
}
And when you create an instance of WebViewClient make sure to pass the MainActivity context.
webView.setWebViewClient(new C01561(MainActivity.this));
Create one Handler to delay the start of the Second Activity.
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
Intent intent = new Intent();
intent.setClass(MainActivity.this, TemporaryActivity.class);
startActivity(intent);
}
}, TIME_OUT);
Now, call this handler in your if condition and set TIME_OUT accordingly.

Android metaio AREL launch url in app and NOT external browser

This is based on the Metaio sdk, but not sure the problem is dependant of it. I have created a basic AREL based Android app, using the Creator. On detection of marker I would like to load a url in a webview.
However when the marker is detected, I get the dialog of choosing what browser to open the url in.
How can I override that and make it open inside a webview in my app?
I tried using public boolean shouldOverrideUrlLoading(WebView view, String url) but it does not get called.
How can I make sure I get all the urls that are attempted to open by an Activity? so I can direct the calls to a webview..
In my activity I have this inside onCreate:
mWebView = (WebView) findViewById(R.id.webview);
mWebView.setWebViewClient(new WebViewHandler());
and this outside onCreate:
class WebViewHandler extends WebViewClient
{
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon)
{
Log.d("LEE","ping1!!!!!"+url);
mProgress.setVisibility(View.VISIBLE);
}
#Override
public void onPageFinished(WebView view, String url)
{
Log.d("LEE","ping2!!!!!"+url);
mProgress.setVisibility(View.GONE);
}
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
{
Log.d("LEE","Triggered url: !!!!!"+url);
}
}
You have a mistake in your override. You should be returning false at the end of shouldOverrideUrlLoading(). This will allow your WebView to handle the request instead of the system.
Have you tried to do it directly in AREL using arel.Media.openWebsite(url, false);
http://dev.junaio.com/arel/documentationArelJS/symbols/arel.Media.html#.openWebsite
You can edit arel code from creator directly
I solved it by overriding openWebsite() inside ARELInterpreterCallback like this...
//ARELViewActivity.java
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import com.metaio.cloud.plugin.view.WebViewActivity;
import com.metaio.sdk.ARELActivity;
import com.metaio.sdk.jni.IARELInterpreterCallback;
public class ARELViewActivity extends ARELActivity {
protected ARELInterpreterCallback myARELCallback;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myARELCallback = new ARELInterpreterCallback();
if (mARELInterpreter != null)
mARELInterpreter.registerCallback(myARELCallback);
}
#Override
protected int getGUILayout() {
return 0;
}
class ARELInterpreterCallback extends IARELInterpreterCallback
{
#Override
public void onSDKReady()
{
loadARELScene();
}
#Override
public boolean openWebsite(String url, boolean openInExternalApp){
//url is set with arel.Media.openWebsite("template://item#", false); inside logic.js
if (url.contains("template://")) {
if (url.contains("item1")) {
urlSub = url.substring(14, url.length());
runOnUiThread(new Runnable() {
#Override
public void run() {
Intent i = new Intent(ARELViewActivity.this, WebViewActivity.class);
i.putExtra(getPackageName() + ".URL", "http://www.google.com.mx");
startActivity(i);
}
});
return true;
} else {
urlSub = url.substring(14, url.length());
runOnUiThread(new Runnable() {
#Override
public void run() {
Intent i = new Intent(ARELViewActivity.this, WebViewActivity.class);
i.putExtra(getPackageName() + ".URL", "http://www.yahoo.com.mx");
startActivity(i);
}
});
return true;
}
} else {
return false;
//return super.openWebsite(url, openInExternalApp);
}
}
}
}

How to get return value from javascript in WebView of Android?

I want to get a return value from Javascript in Android. I can do it with the iPhone, but I can't with Android. I used loadUrl, but it returned void instead of an object. Can anybody help me?
Same as Keith but shorter answer
webView.addJavascriptInterface(this, "android");
webView.loadUrl("javascript:android.onData(functionThatReturnsSomething)");
And implement the function
#JavascriptInterface
public void onData(String value) {
//.. do something with the data
}
Don't forget to remove the onData from proguard list (if you have enabled proguard)
Here's a hack on how you can accomplish it:
Add this Client to your WebView:
final class MyWebChromeClient extends WebChromeClient {
#Override
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
Log.d("LogTag", message);
result.confirm();
return true;
}
}
Now in your javascript call do:
webView.loadUrl("javascript:alert(functionThatReturnsSomething)");
Now in the onJsAlert call "message" will contain the returned value.
Use addJavascriptInterface() to add a Java object to the Javascript environment. Have your Javascript call a method on that Java object to supply its "return value".
Here's what I came up with today. It's thread-safe, reasonably efficient, and allows for synchronous Javascript execution from Java for an Android WebView.
Works in Android 2.2 and up. (Requires commons-lang because I need my code snippets passed to eval() as a Javascript string. You could remove this dependency by wrapping the code not in quotation marks, but in function(){})
First, add this to your Javascript file:
function evalJsForAndroid(evalJs_index, jsString) {
var evalJs_result = "";
try {
evalJs_result = ""+eval(jsString);
} catch (e) {
console.log(e);
}
androidInterface.processReturnValue(evalJs_index, evalJs_result);
}
Then, add this to your Android activity:
private Handler handler = new Handler();
private final AtomicInteger evalJsIndex = new AtomicInteger(0);
private final Map<Integer, String> jsReturnValues = new HashMap<Integer, String>();
private final Object jsReturnValueLock = new Object();
private WebView webView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
webView = (WebView) findViewById(R.id.webView);
webView.addJavascriptInterface(new MyJavascriptInterface(this), "androidInterface");
}
public String evalJs(final String js) {
final int index = evalJsIndex.incrementAndGet();
handler.post(new Runnable() {
public void run() {
webView.loadUrl("javascript:evalJsForAndroid(" + index + ", " +
"\"" + StringEscapeUtils.escapeEcmaScript(js) + "\")");
}
});
return waitForJsReturnValue(index, 10000);
}
private String waitForJsReturnValue(int index, int waitMs) {
long start = System.currentTimeMillis();
while (true) {
long elapsed = System.currentTimeMillis() - start;
if (elapsed > waitMs)
break;
synchronized (jsReturnValueLock) {
String value = jsReturnValues.remove(index);
if (value != null)
return value;
long toWait = waitMs - (System.currentTimeMillis() - start);
if (toWait > 0)
try {
jsReturnValueLock.wait(toWait);
} catch (InterruptedException e) {
break;
}
else
break;
}
}
Log.e("MyActivity", "Giving up; waited " + (waitMs/1000) + "sec for return value " + index);
return "";
}
private void processJsReturnValue(int index, String value) {
synchronized (jsReturnValueLock) {
jsReturnValues.put(index, value);
jsReturnValueLock.notifyAll();
}
}
private static class MyJavascriptInterface {
private MyActivity activity;
public MyJavascriptInterface(MyActivity activity) {
this.activity = activity;
}
// this annotation is required in Jelly Bean and later:
#JavascriptInterface
public void processReturnValue(int index, String value) {
activity.processJsReturnValue(index, value);
}
}
On API 19+, the best way to do this is to call evaluateJavascript on your WebView:
webView.evaluateJavascript("foo.bar()", new ValueCallback<String>() {
#Override public void onReceiveValue(String value) {
// value is the result returned by the Javascript as JSON
}
});
Related answer with more detail: https://stackoverflow.com/a/20377857
The solution that #Felix Khazin suggested works, but there is one key point missing.
The javascript call should be made after the web page in the WebView is loaded. Add this WebViewClient to the WebView, along with the WebChromeClient.
Full Example:
#Override
public void onCreate(Bundle savedInstanceState) {
...
WebView webView = (WebView) findViewById(R.id.web_view);
webView.getSettings().setJavaScriptEnabled(true);
webView.setWebViewClient(new MyWebViewClient());
webView.setWebChromeClient(new MyWebChromeClient());
webView.loadUrl("http://example.com");
}
private class MyWebViewClient extends WebViewClient {
#Override
public void onPageFinished (WebView view, String url){
view.loadUrl("javascript:alert(functionThatReturnsSomething())");
}
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
return false;
}
}
private class MyWebChromeClient extends WebChromeClient {
#Override
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
Log.d("LogTag", message);
result.confirm();
return true;
}
}
As an alternative variant that uses a custom scheme to communicate Android native code <-> HTML/JS code. for example MRAID uses this technic[About]
MainActivity
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
WebView.setWebContentsDebuggingEnabled(true);
}
final WebView webview = new CustomWebView(this);
setContentView(webview);
webview.loadUrl("file:///android_asset/customPage.html");
webview.postDelayed(new Runnable() {
#Override
public void run() {
//Android -> JS
webview.loadUrl("javascript:showToast()");
}
}, 1000);
}
}
CustomWebView
public class CustomWebView extends WebView {
public CustomWebView(Context context) {
super(context);
setup();
}
#SuppressLint("SetJavaScriptEnabled")
private void setup() {
setWebViewClient(new AdWebViewClient());
getSettings().setJavaScriptEnabled(true);
}
private class AdWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.startsWith("customschema://")) {
//parse uri
Toast.makeText(CustomWebView.this.getContext(), "event was received", Toast.LENGTH_SHORT).show();
return true;
}
return false;
}
}
}
customPage.html (located in the assets folded)
<!DOCTYPE html>
<html>
<head>
<title>JavaScript View</title>
<script type="text/javascript">
<!--JS -> Android-->
function showToast() {
window.location = "customschema://goto/";
}
</script>
</head>
<body>
</body>
</html>
You can do it like this:
[Activity(Label = "#string/app_name", Theme = "#style/AppTheme", MainLauncher = true)]
public class MainActivity : AppCompatActivity
{
public WebView web_view;
public static TextView textView;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
Window.AddFlags(WindowManagerFlags.Fullscreen);
Window.ClearFlags(WindowManagerFlags.ForceNotFullscreen);
// Set our view from the "main" layout resource
SetContentView (Resource.Layout.main);
web_view = FindViewById<WebView>(Resource.Id.webView);
textView = FindViewById<TextView>(Resource.Id.textView);
web_view.Settings.JavaScriptEnabled = true;
web_view.SetWebViewClient(new SMOSWebViewClient());
web_view.LoadUrl("https://stns.egyptair.com");
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
{
Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
public class SMOSWebViewClient : WebViewClient
{
public override bool ShouldOverrideUrlLoading(WebView view, IWebResourceRequest request)
{
view.LoadUrl(request.Url.ToString());
return false;
}
public override void OnPageFinished(WebView view, string url)
{
view.EvaluateJavascript("document.getElementsByClassName('notf')[0].innerHTML;", new JavascriptResult());
}
}
public class JavascriptResult : Java.Lang.Object, IValueCallback
{
public string Result;
public void OnReceiveValue(Java.Lang.Object result)
{
string json = ((Java.Lang.String)result).ToString();
Result = json;
MainActivity.textView.Text = Result.Replace("\"", string.Empty);
}
}

Categories

Resources