I have an activity in an Android application that includes both native UI elements and a WebView. The WebView is normally hidden (Visibility.GONE), and it performs occasional work "in the background" on its JavaScript loop. On a particular button click, the WebView is made visible and the user can see the web page. On a subsequent button click, the WebView is hidden again. The user can repeat this process.
I added a call to WebView.postVisualStateCallback when the user presses the button to make the WebView visible. I only make the WebView visible during the VisualStateCallback.onComplete. This works great the first time the user clicks the button and I make the WebView visible. However, after the user dismisses the WebView and I make it hidden again, I cannot repeat this process. Any subsequent call to WebView.postVisualStateCallback never results in another call to VisualStateCallback.onComplete.
mWebView.postVisualStateCallback(++mWebViewVisualStateCallback, new WebView.VisualStateCallback() {
#Override
public void onComplete(long requestId) {
if (requestId == mWebViewVisualStateCallback) {
mWebView.setVisibility(View.VISIBLE);
}
}
});
I am not navigating to new web pages in the WebView. The web page is essentially a long-lived single-page app. The DOM may be changing in the WebView while it is in the background, which is why I'm trying to subsequently call WebView.postVisualStateCallback. I am testing on an emulator and Pixel 2 with Oreo 8.1/API 27.
Is it possible to use WebView.postVisualStateCallback multiple times on the same main frame? Why would WebView.postVisualStateCallback only work once?
Quoted from android website, I think you might need to consider these situations when using postVisualStateCallback()
To guarantee that the WebView will successfully render the first frame
after the VisualStateCallback#onComplete method has been called a set
of conditions must be met:
If the WebView's visibility is set to VISIBLE then the WebView must be attached to the view hierarchy.
If the WebView's visibility is set to INVISIBLE then the WebView must be attached to the view hierarchy and must be made VISIBLE from
the VisualStateCallback#onComplete method.
If the WebView's visibility is set to GONE then the WebView must be attached to the view hierarchy and its LayoutParams's width and height
need to be set to fixed values and must be made VISIBLE from the
VisualStateCallback#onComplete method.
Hope this is helpful~
Related
I am new to Espresso. That is why this could be more of a "should this even work or am I just doing it wrong" type of question.
But basically I have issues testing my WebView with Espresso. When I arrive to the Activity (actually Fragment) with the WebView, Espresso cannot determine that the view is idle and I get the dreaded AppNotIdleException exception. And I don't know if I am doing something wrong or should this case even work.
Here's my test basically:
#Test
public void testIncludingWebView() {
// Go to the activity we want to test. Note, tests start actually earlier.
onView(allOf(withId(R.id.action_open_activity1), isCompletelyDisplayed()))
.perform(click());
// We arrived at the right Activity.
assertEquals(Activity1.class, Utils.getCurrentActivity().getClass());
// Select an item from a GridView in the Activity that will launch the WebView.
onData(MyMatcher.withName(is("Dummy")))
.perform(click());
// We should arrive to an Activity with a Fragment. The Fragment will
// display a full screen DialogFragment that contains the WebView.
assertEquals(WebViewActivity.class, Utils.getCurrentActivity().getClass()); // <== We never assert this
// Some tests on the WebView. But these are never run.
onWebView().forceJavascriptEnabled();
onWebView().withElement(findElement(Locator.NAME, "name"))
.perform(DriverAtoms.webKeys("some text"))
.withElement(findElement(Locator.XPATH, "//button[contains(text(), 'Submit')]"))
.perform(webClick());
}
To recap: I have some Activities that I navigate to and finally I arrive to an Activity with a Fragment and this Fragment will display a full screen DialogFragment that has the WebView. When I arrive here, Espresso cannot determine the idle state.
Also very important to mention is that when I enable Developer Options -> Show screen updates I can see the screen constantly flickering on the view where I get the timeout exception meaning that the screen is updated constantly. AFAIK one of the things Espresso does for determining if the app is idle or not is to wait for the screen rendering to end. So this could be the issue.
But why would the screen update all the time? And I guess here's the beef of it; is it Chrome / WebView updating the screen all the time because of how I open the WebView or do I have some unknown animation going on that I just need to find? I tried to look for animations in the view that I can stop, but since it's just a WebView I am displaying, I haven't found anything.
So have others been able to test this kind of scenario with Espresso or not?
I've got an xamarin forms/prism app, and my hardware back button does nothing on the initial page.
If I navigate to another page, it closes the app as expected. If I navigate to the initial page again, it also closes the app - but not if the app just started.
Is there something I'm missing?
My class App mainly has an OnInitialized that navigates to the initial page:
protected override void OnInitialized()
{
NavigationService.NavigateAsync( "MyMasterDetail/MyNavigationPage/StartPage", animated: false );
}
On MyMasterDetail, there are buttons that navigate to MyNavigationPage/SettingsPage and other pages like that.
It doesn't matter if I use Android 5 in Emulator or Android 6 on a real device, the behaviour is the same.
When using a MasterDetail as your root, you are not actually navigating anywhere else. You are simply changing the Detail property of the MasterDetail to another Page. This is not a navigation action. So you are not really navigating. If you want to fake it, you need to add the INavigationPageOptions to your MyNavigationPage and set the ClearNavigationStackOnNavigation property to false. This will continuously push new pages onto the MasterDetailPage.Detail MyNavigationPage without clearing the stack (PopToRoot). Then this will allow your bac button to behave like you are wanting.
I have an activity that loads content from the internet when it initially loads, however the order it takes is:
1) User hits button to go to new activity
2) App stays on old activity
3) App loads content from internet (usually takes about a second or two)
4) App brings user to new activity with content already loaded
Now this is fine, however it can be confusing for a user because while they are still on the original activity, there is no indication that their input did anything. If the user were to click the button again, it wouldn't register that as another click on the original activity, it would register that as a click on the new activity which is still loading, which may cause a user to end up somewhere they did not wish to be.
I'd like to be able to fix this by having the order of the process be:
1) User hits button to go to new activity
2) Old activity disappears, brings user to "blank" new activity without content loaded
3) Display a loading wheel
4) App loads content from internet
5) Content is displayed and loading wheel disappears.
However I can't figure out how to accomplish this, I placed all my code in the onResume() method because I thought that would work, but the content loaded the same way as it always has, does anyone have any suggestions on how to accomplish what I want? Here is the code in my onResume() method:
protected void onResume() {
super.onResume();
setContentView(R.layout.coupon);
//method call to access the URL needed to display the content
accessURL(Global.contentURL);
}
Any help would be greatly appreciated.
You can use an AsyncTask that creates a ProgressDialog while it fetches the data in the background. There are many questions about this on SO (e.g. How to use AsyncTask to show a ProgressDialog while doing background work in Android?) as well as on the Internet.
I use activity with ImageView, and by click on button it switches to activity with VideoWiew and plays movie, the movies first frame is the image on previous activity. I disabled animation between activity by using
Intent intent = new Intent(ImageClass.this, MovieClass.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
startActivity(intent);
but it still flashes black screen between them, how can i disable this?
One of the simplest way is to move all the expensive (time-consuming) processing from your activity's onCreate and onStart method to onResume mthod. By this, your newly launched activity will be visible right after its launched but then will take a little extra to make it available for user to interact. Further, I would suggest you to move all the heavy lifting in AsyncTask for smoother UI experience.
I recently had a problem with smooth transition. Even though I am loading the lengthy tasks in AsyncTask, it still takes time to load, and the screen has to wait.
If you have a WebView, for example, that takes a while to load, and under the WebView, you have some TextViews and other things, supposedly a layout.
The layout will load first, and the WebView later, making the screen loading ackward.
A solution for this would be to set the Visibility to GONE on all the objects before it loads, and then set to VISIBLE after the WebView loads.
webView.setWebViewClient(new WebViewClient() {
public void onPageFinished(WebView view, String url) {
webView.setVisibility(View.VISIBLE);
LinearLayout ll_load_after_web_view_bottom = findViewById(R.id.ll_load_after_web_view_bottom);
LinearLayout ll_load_after_web_view_top = findViewById(R.id.ll_load_after_web_view_top);
ll_load_after_web_view_bottom.setVisibility(View.VISIBLE);
ll_load_after_web_view_top.setVisibility(View.VISIBLE);
}
});
Hi i am having a activity with a button, on click of the button it has to load a custom browser in a new activity not the default browser of android. and i need a way to exclude the history of the browser such that on back press it comes back to the previous activity without navigating to previous website. I am new to android and any ways to do this
You are probably just talking about the WebView
Link to the official tutorial
Note :
This onKeyDown(int, KeyEvent) callback method will be called anytime a
button is pressed while in the Activity. The condition inside uses the
KeyEvent to check whether the key pressed is the BACK button and
whether the WebView is actually capable of navigating back (if it has
a history). If both are true, then the goBack() method is called,
which will navigate back one step in the WebView history.Returning
true indicates that the event has been handled. If this condition is
not met, then the event is sent back to the system.
You can start by putting a WebView in an activity.
If you want to have a view which can browse the web in your app then make use of the WebView view.
Else if you want to create your own custom browser, then you have to make use Web engine WebKit present in the library layer of the android.