I want to navigate Angular single page application without reloading the webpage. On button click I'm calling following code to navigate.
String fullUrl = "https://example.com/page1";
String hashUrl = "/page1";
public void goBackInWebView(String fullUrl, String hashUrl) {
WebBackForwardList history = webview.copyBackForwardList();
int index;
int currentIndex = history.getCurrentIndex();
for (int i = 0; i < history.getSize(); i++) {
index = i - currentIndex;
if ((webview.canGoBackOrForward(1 + i)) || (webview.canGoBackOrForward(1 - i))) {
if (history.getItemAtIndex(i).getUrl().endsWith(hashUrl)) {
webview.goBackOrForward(index);
break;
} else if (i == history.getSize()) {
webview.loadUrl(fullUrl);
break;
}
} else {
//OUTER ELSE
webview.loadUrl(fullUrl);
break;
}
}
}
If the webpage is not saved in the history it will call webview.loadUrl(fullUrl); else it will load the page using webview.goBackOrForward(index);.
but is above code everytime OUTER ELSE is callling.
First of all canGoBackOrForward is used for Getting whether the page can go back or forward the given number of steps. as you mentioned in question your web page is single page so you don't need call this method. I think bellow code can solve your problem.
public void goBackInWebView(String fullUrl, String hashUrl) {
WebBackForwardList history = webview.copyBackForwardList();
if (history.getSize() == 0) {
webview.loadUrl(fullUrl);
}else {
for (int i = 0; i < history.getSize(); i++) {
if (history.getItemAtIndex(i).getUrl().endsWith(hashUrl)) {
webview.goBackOrForward(i);
break;
} else {
webview.loadUrl(fullUrl);
}
}
}
}
I find it difficult to see much relation to Android and WebView, because the problem is SPA.
Better use hashtag # navigation for SPA, because this won't request anything server-side.
The point simply is, that the back button does not matter the least, while never navigating.
One just needs to bind JavaScript, which runs whenever window.location.hash changes.
Related
I want to make a button that allows to go to a random page, but I am having trouble with the logic of it, as I can see loopholes but I dont know how to solve them. Or should i use a different approach? Code as below.
qn3_nextBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
for (int i=1; i<4; i++) {
int rng = new Random().nextInt(2) + 1;
if (rng == i && !qns.contains(1)) {
qns.add(1);
Intent qn1 = new Intent(question3.this, question1.class);
qn1.putExtra("name", name);
qn1.putIntegerArrayListExtra("questions", qns);
startActivity(qn1);
} else if (rng == i && !qns.contains(2)) {
qns.add(2);
Intent qn2 = new Intent(question3.this, question2.class);
qn2.putExtra("name", name);
qn2.putIntegerArrayListExtra("questions", qns);
startActivity(qn2);
} else if (rng == i && !qns.contains(3)) {
qns.add(3);
Intent qn3 = new Intent(question3.this, question3.class);
qn3.putExtra("name", name);
qn3.putIntegerArrayListExtra("questions", qns);
startActivity(qn3);
}
}
}
});
loopshole that is... the user will need to press the button multiple times if the function does not meet the conditions
First Add your Intents into an ArrayList<Intent>:
ArrayList<Intent> pages = new ArrayList();
pages.add(qn1);
pages.add(qn2);
pages.add(qn3);
After that generate a random int between 0 and the list.size() inside the onClick and get that page from the list:
int index = new Random().nextInt(pages.size());
Intent page = pages.get(index);
startActivity(page);
Finally remove that page from the list by calling:
pages.remove(index);
Just don't forget to check if the ArrayList is empty or not in the first line of the onClick:
if(pages.size == 0) return;
I hope it works!
I'm working in Accessibility Service. i need to get the app name using Accessibility Service. i have studied the documentation of the Accessibility Service in developer's of Android website. but there is no mention about getting the app name using Accessibility.
I also want to extract text from "TextViews" of the other apps(Activities) running in background. How i can do this..
I'm assuming you know how to implement an AccessibilityService.
Retrieving window content:
First register for TYPE_WINDOW_CONTENT_CHANGED events.
#Override
public void onAccessibilityEvent(AccessibilityEvent accessibilityEvent){
int eventType = accessibilityEvent.getEventType();
switch (eventType) {
case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED:
AccessibilityNodeInfo rootNode = getRootInActiveWindow();
ArrayList<AccessibilityNodeInfo> textViewNodes = new ArrayList<AccessibilityNodeInfo>();
findChildViews(rootNode);
for(AccessibilityNodeInfo mNode : textViewNodes){
if(mNode.getText()==null){
return;
}
String tv1Text = mNode.getText().toString();
//do whatever you want with the text content...
}
break;
}
}
Method findChildViews() :
private void findChildViews(AccessibilityNodeInfo parentView) {
if (parentView == null || parentView.getClassName() == null || ) {
return;
}
if (childCount == 0 && (parentView.getClassName().toString().contentEquals("android.widget.TextView"))) {
textViewNodes.add(parentView);
} else {
for (int i = 0; i < childCount; i++) {
findChildViews(parentView.getChild(i));
}
}
}
}
As far as i know, there's no assured way to get the app name, but you can try fetching the text content from the event object you get from TYPE_WINDOW_STATE_CHANGED events.
Try dumping accessibilityEvent.toString() & you'll know what i'm talking about.
Also, accessibilityEvent.getPackageName() is a simple way to get package name of that app; in case you find it useful!
previous answer is missing definition of childCount
int childCount = parentView.getChildCount();
So I'm trying to do the following in android xamarin.
When you press on a map element an infowindow is shown.When you press that window and an event is linked to the element the app goes to another fragment that is described by the action object. The problem is the moment I press the infowindow the whole app freezes and nothing happens. In the logs I can't see anything and the app stops at the following line:
pager.Adapter = pagerAdapter;
Added a breakpoint there and after saying "step over" the ide doesn't break anymore and the app freezes (no user interaction possible).
So let me start by giving all the relative code and a little explanation.
So first I'll show you what happens on the infowindow click. This happens on a SupportMapFragment that has it's own listener.
void GoogleMap.IOnInfoWindowClickListener.OnInfoWindowClick (Marker p0)
{
InfoPopup ip = CustomJsonConverter.Convert<InfoPopup> (p0.Title);
if (ip == null || ip.Goto == null || !(this.Activity is MainView))
return;
MainView main = (this.Activity as MainView);
p0.HideInfoWindow ();
switch (ip.Goto.type) {
case "InfoFragment":
Info info = InfoController.Items.Find (x => x.Index == ip.Goto.id);
if (info != null) {
main.RunOnUiThread (() => {
main.ShowInfosFragment ();
main.ShowInfoFragment (info);
});
}
break;
case "FaqFragment":
FaQ faq = FaQController.Items.Find (x => x.Index == ip.Goto.id);
if (faq != null) {
main.RunOnUiThread (() => {
main.ShowFaqsFragment ();
main.ShowFaqFragment (faq);
});
}
break;
}
}
I tested it with an action of InfoFragment which gives back an item so that's good. Then it goes to the main.ShowInfosFragment() which is where it freezes. So that method is really simple. This function is in the Activity holding the fragments (thanks Cheesebaron).
public void ShowInfosFragment(){
ShowFragment(1, new InfosFragment (){ InfoSelectedAction = ShowInfoFragment });
}
So the problem giving function is the following. This function is in the Activity holding the fragments (thanks Cheesebaron).
protected void ShowFragment(int index, Android.Support.V4.App.Fragment fragment, bool ignoreType = false){
RemoveSubMenu();
if (pagerAdapter.Count <= index || ignoreType || !(pagerAdapter.GetItem (index).GetType().Equals(fragment.GetType()))) {
pagerAdapter.AddFragment (index, fragment);
SetSubMenu (fragment);
pager.Adapter = pagerAdapter;
}
pager.SetCurrentItem (index, true);
DrawerButtonLayout ();
}
I've used this function a lot and it has always worked to move to the other fragments from the menu or at startup to set the mapfragment.
Anyone sees what's the problem with my code? Tried tons of things but can't seem to figure this one out with my friend google.
Thanks already for reading.
Kind regards,
Karl
Is it possible to erase a specific url from the android's webview history? I Google a lot but was not able to find any sol, even i checked the api's documentation and i think there is no direct way to do the same.
have a look at below code:
// getting the whole list of web view's history....
WebBackForwardList list = wv.copyBackForwardList();
// getting previuous item/link
String lastUrl = list.getItemAtIndex(list.getCurrentIndex()-1).getUrl();
From 2nd line of code it is clear that it is possible to play around with history, so i think there must be some way or trick to delete a particular link from web view history.
Does it makes any sense to you guys?
Any code snippet or any link will highly be appreciated.
thanks,
Well, not sure if you actually can play around with the back forward list. I would assume it's a copy - at least that's what the name suggest.
However, you can manipulate the back stepping to some degree. In my case I exit the application already when user tries to step back from second page towards first page.
#Override
public boolean dispatchKeyEvent(KeyEvent event) {
int action = event.getAction();
int keyCode = event.getKeyCode();
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
if ((action == KeyEvent.ACTION_DOWN) && myWebView.canGoBack() ) {
WebBackForwardList list = myWebView.copyBackForwardList();
String lastUrl = list.getItemAtIndex(list.getCurrentIndex()-1).getUrl().toString();
// Exit if index == 1, i.e. currently on 2nd page
if (list.getCurrentIndex() == 1) {
finish();
} else ...
You could step over also other other pages by combining stuff from above and overloading url loading:
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url){
view.loadUrl(url);
return true;
}
The question and answer both helped us to find the following solution for our problem.
We wanted to jump back to particular url (partialUrl), which could be anywhere in WebBackForwardList. So we are using following code to goBackOrForward, based on the partial Url passed in method by theValueString parameter. ( We wanted to call the method from any other thread so using runOnUiThread )
if (!theValueString.isEmpty()) {
final String partialUrl = theValueString;
runOnUiThread(new Runnable() {
#Override
public void run() {
// getting the whole list of web view's history....
WebBackForwardList list = myWebview.copyBackForwardList();
int index = list.getCurrentIndex();
for (int i = list.getSize() - 1; i >= 0; i--) {
String historyurl = list.getItemAtIndex(i).getUrl();
if (historyurl.contains(partialUrl)) {
myWebview.goBackOrForward(i - index);
break;
}
}
}
});
}
I have a view to create an account. If the save button is clicked and any of the fields are left open, it displays a toast. If all fields are filled in, the account is saved. I tried to accomplish this with an onClickListener that has an iteration through all the fields. It works perfectly if a field is not filled in and it works perfectly if alle fields are filled, but when a field isn't filled, I type something in there, try to save again and the button doesn't do anything.
I think it has something to do with the return, but I don't know what to do else. If the return wouldn't be there, I would get a toast for each field that isn't filled in.
Here's the relevant code:
private void registerButtonListeners() {
mCRUDAccountButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
for (int i = 0; i < mEditTexts.length; i++) {
if(mEditTexts[i].getText().length() == 0){
CommonCode.showToast(mNoTextTitles[i], mContext, mViewGroup);
mEmptyField = 1;
return;
}
};
if (mEmptyField == 0){
saveState();
}
}
});
}
thanks guys!
You're never resetting your flag back to 0!
so...
#Override
public void onClick(View v) {
mEmptyField = 0;//RIGHT HERE (give them the benefit of the doubt)
for (int i = 0; i < mEditTexts.length; i++) {
if(mEditTexts[i].getText().length() == 0){
CommonCode.showToast(mNoTextTitles[i], mContext, mViewGroup);
mEmptyField = 1; //You were too optimistic, they failed.
return;
}
};
if (mEmptyField == 0){
saveState();
}
}
});
Now, you're doing this test for the first time, every time. Otherwise, you go through and set that flag to 1, and next time, even though your loop never finds a match, when you get to the if mPentyField == 0 test, it fails cause you set that to 1 in the previous go around.