In my code I have a lot of instances like this:
if (!valid){
validate();
}
if (valid){
\\ execute some code
}
and I was wondering if there was a better way to do this? First off, it's annoying to have to write a bunch of these consecutive if statements, and secondly, part of my code in validate() requires that I load a webview with a login page, and then login. Once I've reached the logged in page, I retrieve a value using JavaScript which then changes the value of valid to true if it matches. There's no real convenient until function, and using while(!valid) doesn't quite give me what I want.
Here is my validate()
private void validate(){
class MyJavaScriptInterface {
#JavascriptInterface
public void showHTML(String content) {
// grants access based on authorization level
loggedIn = true;
if(content.contains("OK")){
valid = true;
Toast.makeText(getApplicationContext(), "Log In Successful",
Toast.LENGTH_SHORT).show();
}else {
valid = false;
Toast.makeText(getApplicationContext(), "No Access Granted", Toast.LENGTH_SHORT)
.show();
}
updateMenuTitles();
}
}
// open up the login page
final WebView wv = (WebView)findViewById(R.id.login_webview);
wv.getSettings().setJavaScriptEnabled(true);
wv.addJavascriptInterface(new MyJavaScriptInterface(), "HTMLOUT");
wv.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
//once page is finished loading, check id="role" pass that value to showHTML
if(url.contains(getString(R.string.loginURL))) {
wv.loadUrl("javascript:(function() { " +
"window.HTMLOUT.showHTML(document.getElementById('course-eval-status')" +
".innerHTML);})()");
wv.setVisibility(View.GONE);
closeWebview.setVisibility(View.GONE);
}
}
#Override
public void onReceivedError(WebView view, int errorCode, String description,
String failingUrl) {
Log.w("LoginActivity: ", description);
}
});
wv.loadUrl(getString(R.string.loginURL));
if(!loggedIn) {
wv.setVisibility(View.VISIBLE);
closeWebview.setVisibility(View.VISIBLE);
}else{
closeWebview.setVisibility(View.GONE);
wv.setVisibility(View.GONE);
}
}
Your question is not clear but could this be what you are looking for?
boolean valid = false;
private boolean validate() {
System.out.println("Validating");
return true;
}
public void test() {
if (valid || (valid = validate())) {
System.out.println("Try 1");
}
if (valid || (valid = validate())) {
System.out.println("Try 2");
}
}
This will only call validate once. However - a better mechanism would be something like:
private boolean valid() {
return valid || (valid = validate());
}
public void test2() {
if (valid()) {
System.out.println("Try 1");
}
if (valid()) {
System.out.println("Try 2");
}
}
If validate() changes the value of valid, then I don't really see a way around this. It seems to me that the issue isn't so much syntactical as it is business logic. You mention that your code "doesn't wait around" -- couldn't you change it to make it wait? If not, then perhaps you need some unit tests to better be able to validate your code. Regardless, the issue doesn't seem like it's with the valid flag.
Related
I'm using this library to validate URL within my app but I wanna run the same method for 4 or more URLs instead of one but can't seem to figure out how to.
My code:
validateUrl(this, "https://www.dummy.dummy/");
SharedPreferences sharedPreferences = getSharedPreferences("url", MODE_PRIVATE);
if (sharedPreferences.getBoolean("validated", true)) {
Log.e("WEB", "RUNNING");
doSomething():
} else {
Log.e("WEB", "DOWN");
}
private void validateUrl (Context context, String URL) {
new FarlaGetRequest(context)
.setURL(URL)
.setListener(new FarlaGetRequest.onGetRequestListener() {
#Override
public void onSuccess(String response) {
Log.e("WEB", "Done");
SharedPreferences.Editor editor = getSharedPreferences("url", MODE_PRIVATE).edit();
editor.putBoolean("validated",true);
editor.apply();
}
#Override
public void onFailure(int error) {
Log.e("WEB", "Failed");
}
}).execute();
}
The goal is, if the url is able to connect (server sent response 200) then do something, else don't.
So what I'm stuck at is, how do I do this for multiple URLs?
Example:
Check 1st (log if it's running or down)
Check 2nd (log if its running or down)
Same for the 3rd and 4th as well.
At the end, it should say which are active and which ones aren't so can someone help me please? ease?
you can use a List of url's and execute that validator function for the number of times that the size of list is and if the url connects (got response 200) then just move to the next url otherwise remove that url from list. So , in this way you will end up with all the working URL's.
Solution Code:
List<String> urlList = new ArrayList<>();
// add all url's in the list; for example : urlList.add("https://www.dummy.dummy/");
Now we will use a loop to execute the checker function for all the url's
for(int i =0; i<urlList.size();i++)
{
validateUrl (context, urlList.get(i))();
}
and in the YOUR_URL_CHECKER_FUNCTION just put a condition that if the server sents response as 200 then do nothing otherwise urlList .remove("https://www.dummy.dummy/")
Sample code:
private void validateUrl (Context context, String URL) {
new FarlaGetRequest(context)
.setURL(URL)
.setListener(new FarlaGetRequest.onGetRequestListener() {
#Override
public void onSuccess(String response) {
// HERE YOU CAN CHECK THAT WHAT'S THE RESPONSE**
if(!response.equals("200"))
{
`urlList .remove("https://www.dummy.dummy/")`// link to remove
}
}
#Override
public void onFailure(int error) {
Log.e("WEB", "Failed");
}
}).execute();
}
Hope you get that. Feel free to ask if something is unclear. And kindly mark it as the correct answer if it helps you so that this answer can help any other needy.😀
Thanks for reading this
I am having difficulty a utility method meant to read all 20 edittexts and check if they are empty and return custom toast messages for instances of each editText being empty
The utility method is called inside my onclicklistener as seen below. Its called checkEmpty
btnRequest.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (checkEmpty(etPickupLocation, getActivity())) return;
}
});
see checkempty below
public static boolean checkEmpty(EditText myEditText, Context context) {
String editTextIdInt= String.valueOf(myEditText.getId());
Log.d(TAG, "checkEmpty: editTextIdInt>> "+ myEditText.getId());
String editTextIdStr = context.getString(Integer.parseInt(editTextIdInt));
Log.d(TAG, "checkEmpty: editTextIdStr >>"+ editTextIdStr);
if (myEditText.getText().toString().trim().length() == 0) {
Toast.makeText(context, editTextIdStr+" is missing.", Toast.LENGTH_SHORT).show();
return true;
}
return false;
}
The issue is : I want to return the id of the editTextResource (etPickupLocation) as the second log output but instead i keep getting false
log output
2020-09-20 10:33:21.556 11445-11445/com.packagename.clasname D/UTILITYLOG: checkEmpty: editTextIdInt>> 2131230927
2020-09-20 10:33:21.556 11445-11445/com.packagename.clasname D/UTILITYLOG: checkEmpty: editTextIdStr >>false
All I want is to get the id of the editext bein passed into the method so i can return the right toast method
or is there a better approach to doing this?
Help me out guys
Thanks so much to Mike Ms clarification
I decided to use this approach instead since I cannot use an EditText's ID to retrieve a string resource.
public static boolean checkEmpty(EditText myEditText, Context context) {
Log.d(TAG, "checkEmpty: Obj" + myEditText.toString());
String myObj = myEditText.toString();
String OutputText="";
if (myObj.contains("etPickupLocation")) {
OutputText = "Sender Address";
}else if (myObj.contains("etWhereTo")) {
OutputText = "Recipient Address";
} else {
Log.d(TAG, "checkEmpty: >> DOING NOTHING");
OutputText = "Something";
}
if (myEditText.getText().toString().trim().length() == 0) {
Toast.makeText(context, "Enter "+OutputText+"." , Toast.LENGTH_SHORT).show();
return true;
}
return false;
}
I am trying to check to see if a view is displayed with Espresso. Here is some pseudo code to show what I am trying:
if (!Espresso.onView(withId(R.id.someID)).check(doesNotExist()){
// then do something
} else {
// do nothing, or what have you
}
But my problem is .check(doesNotExist()) does not return boolean. It is just an assertion. With UiAutomator I was able to just do something like so:
if (UiAutomator.getbyId(SomeId).exists()){
.....
}
Conditional logic in tests is undesirable. With that in mind, Espresso's API was designed to guide the test author away from it (by being explicit with test actions and assertions).
Having said that, you can still achieve the above by implementing your own ViewAction and capturing the isDisplayed check (inside the perform method) into an AtomicBoolean.
Another less elegant option - catch the exception that gets thrown by failed check:
try {
onView(withText("my button")).check(matches(isDisplayed()));
//view is displayed logic
} catch (NoMatchingViewException e) {
//view not displayed logic
}
Kotlin version with an extension function:
fun ViewInteraction.isDisplayed(): Boolean {
try {
check(matches(ViewMatchers.isDisplayed()))
return true
} catch (e: NoMatchingViewException) {
return false
}
}
if(onView(withText("my button")).isDisplayed()) {
//view is displayed logic
} else {
//view not displayed logic
}
I think to mimic UIAutomator you can do this:
(Though, I suggest rethinking your approach to have no conditions.)
ViewInteraction view = onView(withBlah(...)); // supports .inRoot(...) as well
if (exists(view)) {
view.perform(...);
}
#CheckResult
public static boolean exists(ViewInteraction interaction) {
try {
interaction.perform(new ViewAction() {
#Override public Matcher<View> getConstraints() {
return any(View.class);
}
#Override public String getDescription() {
return "check for existence";
}
#Override public void perform(UiController uiController, View view) {
// no op, if this is run, then the execution will continue after .perform(...)
}
});
return true;
} catch (AmbiguousViewMatcherException ex) {
// if there's any interaction later with the same matcher, that'll fail anyway
return true; // we found more than one
} catch (NoMatchingViewException ex) {
return false;
} catch (NoMatchingRootException ex) {
// optional depending on what you think "exists" means
return false;
}
}
Also exists without branching can be implemented really simple:
onView(withBlah()).check(exists()); // the opposite of doesNotExist()
public static ViewAssertion exists() {
return matches(anything());
}
Though most of the time it's worth checking for matches(isDisplayed()) anyway.
We need that functionality and I ended up implementing it below:
https://github.com/marcosdiez/espresso_clone
if(onView(withText("click OK to Continue")).exists()){
doSomething();
} else {
doSomethingElse();
}
I hope it is useful for you.
You check with the below code also. If view is displayed it will click else it will pass on.
onView(withText("OK")).withFailureHandler(new FailureHandler() {
#Override
public void handle(Throwable error, Matcher<View> viewMatcher){
}
}).check(matches(isDisplayed())).perform(customClick());
Why no one mentioned:
onView(withId(R.id.some_view_id)).check(matches(not(doesNotExist())))
just add not before doesNotExist. But if you use this logic a lot it's better to use a custom matcher.
Based on the answer by Dhiren Mudgil, I ended up writing the following method:
public static boolean viewIsDisplayed(int viewId)
{
final boolean[] isDisplayed = {true};
onView(withId(viewId)).withFailureHandler(new FailureHandler()
{
#Override
public void handle(Throwable error, Matcher<View> viewMatcher)
{
isDisplayed[0] = false;
}
}).check(matches(isDisplayed()));
return isDisplayed[0];
}
I'm using this to help determine which View in a ViewFlipper is currently displayed.
I think that what Espresso wants you to do is to change your logic to use doesNotExist()
I have for example
onView(snackBarMatcher).check(doesNotExist())
onView(withId(R.id.button)).perform(click())
onView(snackBarMatcher).check(matches(isDisplayed()))
It's been some time since this issue was stated, but as it is one of the top hit on Google when searching for ways to make sure a view is present, before doing any actions on it in Espresso, I would like to share my very basic way of handling this.
1: Start out by writing an extension to ViewInteraction:
fun ViewInteraction.exists(): Boolean {
val viewExists = AtomicReference<Boolean>()
this.perform(object : ViewAction {
override fun perform(uiController: UiController?, view: View?) {
viewExists.set(view != null)
}
override fun getConstraints(): Matcher<View>? {
return Matchers.allOf(ViewMatchers.withEffectiveVisibility(
ViewMatchers.Visibility.VISIBLE),
ViewMatchers.isAssignableFrom(View::class.java))
}
override fun getDescription(): String {
return "check if view exists"
}
})
return viewExists.get()
}
2: Create a simple help method in your base class (to be used in all test classes):
fun viewExists(id: Int): Boolean {
return try {
onView(withId(id)).exists()
} catch (e: RuntimeException) {
false
}
}
With this you either get true or false from onView(withId(id)).exists(), or safely catch the RuntimeException and return false.
Normally a simple check to .exists() would be sufficient, but in some cases, like when you are deleting ListView items until non is left -> when the last item is deleted, the ListView might no longer be present, then an Exception is thrown when trying to check if it exists.
3: With the above implementation, it is safe to check if any view exists, since the RuntimeException is handled nicely behind the scene:
if(viewExists(R.id.something)) {
//do something
}
//do something else
I have created an application which needs sign in from Facebook/Twitter/Google to get started. In a layout I have created three switches each for Facebook, Twitter and Google which has options ON and OFF. I want to make the switch of the particular account as 'ON' if the user is logged in from that corresponding account. Example if the user is logged in from Facebook, only the switch beside Facebook should be ON. How can I do that?
Any suggestions would be appreciated, and also if somebody know then please refer me to any tutorial related to this.
Below is my code for the login page. I have shown the login for Facebook part:
Thanx :)
private OnClickListener loginButtonListener = new OnClickListener() {
#SuppressWarnings("deprecation")
public void onClick( View v ) {
String[] permissions = { "offline_access", "publish_stream", "user_photos", "publish_checkins","photo_upload" };
if(v.getId() == R.id.button1 )
{
facebookSwitch = true;
twitterSwitch = false;
googleSwitch = false;
if( !mFacebook.isSessionValid() ) {
Toast.makeText(Login.this, "Authorizing", Toast.LENGTH_SHORT).show();
mFacebook.authorize(Login.this, permissions, new LoginDialogListener());
}
else {
Toast.makeText( Login.this, "Has valid session", Toast.LENGTH_SHORT).show();
try {
JSONObject json = Util.parseJson(mFacebook.request("me"));
//Log.d("Login", "11111111111111111");
String facebookID = json.getString("id");
//Log.d("Login", "22222222222222");
String firstName = json.getString("first_name");
//Log.d("Login", "3333333333333333333");
String lastName = json.getString("last_name");
//Log.d("Login", "4444444444444444444444");
Toast.makeText(Login.this, "You already have a valid session, " + firstName + " " + lastName + ". No need to re-authorize.", Toast.LENGTH_LONG).show();
Intent intent = new Intent(Login.this,MainActivity.class);
startActivity(intent);
}
catch( Exception error ) {
Toast.makeText( Login.this, error.toString(), Toast.LENGTH_SHORT).show();
}
catch( FacebookError error ) {
Toast.makeText( Login.this, error.toString(), Toast.LENGTH_SHORT).show();
}
}
}
Try it this way....
- First create a Singleton Class with 3 booleanvariables for 3 logins info, and thereGetter-Setter`. Singleton is needed over here so that only One object of that class is formed no matter from where that class is called in the whole application. So now you have a single point of info.
- Always check Singleton Class's variables in the beginning of another Activity or when needed by you, to know that whether the user is logged into one or two or all the social networking sites.
////////////////////////////////Edited Part/////////////////////////////
A simple way of creating a Singleton is below, thought there are few more:
public class Test{
public static Test uniqueInstance = new Test();
private Test(){}
public static Test getInstance(){
return uniqueInstance;
// No matter what but always u will get the same instance.
}
}
Now To call this object in another class do as below...
public class Main{
Test t = Test.getInstance(); // Now use t to call the fields and methods of class T.
}
I'm making an app in which I open a BrowserField and the user can navigate further to links present in the web page. The problem is that when I press the physical back button, the previous screen is presented while I want to present the previous page in the BrowserField itself. How to do that? Is that even possible?
Thanks.
You need to use BrowserFieldHistory to go back to previous pages using the canGoBack() and goBack() methods. Just over-ride the keyChar method to control the ESCAPE key input and put your own logic like so:
public boolean keyChar(char key, int status, int time) {
if ( key == Characters.ESCAPE) {
if(yourBrowserField.getHistory().canGoBack()){
yourBrowserField.getHistory().goBack();
}else{
UiApplication.getUiApplication().popScreen(this);
return true;
}
}
}
Yes It is Possible.
Try this code:
public class NewsBrowserScreen extends MainScreen
{
int current_index,popup;
String url;
VerticalFieldManager vertical;
BrowserField browserField;
BrowserFieldConfig browserFieldConfig;
BrowserFieldHistory browserFieldHistory;
public NewsBrowserScreen(int current_index,int popup,String url)
{
this.current_index=current_index;
this.popup=popup;
this.url=url;
createGUI();
}
private void createGUI()
{
vertical=new VerticalFieldManager(VERTICAL_SCROLL|VERTICAL_SCROLLBAR|HORIZONTAL_SCROLL|HORIZONTAL_SCROLLBAR);
browserFieldConfig=new BrowserFieldConfig();
browserFieldConfig.setProperty(BrowserFieldConfig.NAVIGATION_MODE, BrowserFieldConfig.NAVIGATION_MODE_POINTER);
browserField=new BrowserField(browserFieldConfig);
browserFieldHistory=browserField.getHistory();
vertical.add(browserField);
add(vertical);
browserField.requestContent(url);
}
public boolean onClose()
{
if(browserFieldHistory.canGoBack())
{
browserFieldHistory.goBack();
return true;
}
else
{
browserFieldHistory.clearHistory();
return super.onClose();
}
}
}
Enough;