OOTB, Robolectric does not support Locales that well. Therefore, if your app is dependent on locales (which a lot of apps are if they are i18n'nd properly) this can be a royal pain. Long story short, I created my own ShadowFooGeocoder and ShadowFooAddress that allow me to simulate the locale I want. They're basically re-implementations of the existing shadows.
However, when I bind my class as such: bindShadowClass(ShadowFooGeocoder.class), this works great. At runtime, the correct shadow is returned. The problem is that I want to set up the simulations on this object and I'm not sure how. shadowOf(instance) where instance is an injected GeoCoder returns ShadowGeoCoder. I've tried working directly with the ShadowWrangler, but that also returns a ShadowGeocoder.
How can I get at my shadowed class that I've bound through the bindShadowClass(...) call so I can set my expectations (simulations)?
Note: This is a repost of the same question on the Robolectric group here. I posted here because my success rate of getting anyone to answer questions on the group is fairly low. I'm hoping for a better result here.
What I've basically done here is extend ShadowGeocoder like this:
#SuppressWarnings({"UnusedDeclaration"})
#Implements(Geocoder.class)
public class ShadowFooBarGeocoder extends ShadowGeocoder {
// implementation stuff
}
Then I would bind it using the bindShadowClasss(...) and when I retreive the shadow via the static shadowOf(...) call I get back a "ShadowGeocoder" which is an instance of ShadowFooBarGeocoder. I then cast it to that type and perform whatever work I need to.
Related
I'm using UIAutomator test framework for long tests (concerning to my acceptance test). And I need to wait until some activity is started.
I decided to use By.clazz (android.support.test.uiautomator package) methods to find activity object. I expected that something like
uiDevice.wait(Until.findObject(By.clazz(SomeActivity.class)), 30000);
will work. But it doesn't. I suppose that object of my activity cannot be found. I tried to use other By.clazz methods with different params but without success.
So, my code is pretty simple:
UiDevice uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
/*.... do something...
like click on buttons which will open some activities...
*/
//does not work, time value just for sample
uiDevice.wait(Until.findObject(By.clazz(SomeActivity.class)), 30000);
I found workaround solution with using By.res, like
uiDevice.wait(Until.findObject(By.res(BASIC_PACKAGE, "someMainIdInSomeFragment")), 30000);
But I have very complicated structure of the app with base activities and so on. I often have the same layout for different activities with load different fragments. So I need to know that we started exactly SomeActivity ,regardless of loaded fragments.
So, the questions are:
Is it possible to use By.clazz for Activity to find its object?
Is there some another way to find activity object with UIAutomator?
Did I do everything right? Or maybe there are some mistakes? Is it possіble to do with UiAutomator?
Thanks!
Using class with UiObject2
Find the EditText, make sure to click on it (legacySetText would do it implicitly), and set your text.
val input = By.clazz(EditText::class.java.canonicalName)
device.wait(Until.findObject(input), TIMEOUT).apply {
click()
text = "your_text"
}
Yes, could be done through the id.
// android:id="#+id/widget_id"
By.res(applicationId, "widget_id")
Your syntax seems good to me. Just make sure no spinner (or any other widget) is blocking your view during the click attempt.
I have a method that darkens a given hex color and percent. Currently, the only place I use this method is within one of my Activity classes (I may or may not end up using it in other classes later on).
public static int darkenColor(int color, int percent) { ... }
However, where should I put this method? Should I create a new class called Helpers that contains all of these methods that I may use only once throughout the entire app?
This is just a matter of choice. You can have Set of utility classes and have these helper methods to be in those classes. But, This method is for not used in one of your activity, and If you do not see that it will get reused in the near future in some other point, Put it as a private method inside your Activity. I say this because you do not want to over complicate the code and also By this way another developer can easily follow the flow of execution.
But after sometimes if you feel, that this code is getting reused, put that into a logically meaningful Utility class. When the code base is huge, you do not have any choice to follow a solid standardization of there to put your code, That is why there are things like Layered architectures etc.
We here (two small teams) are writing an Android library (OpenGL ES 3.1 based graphics effects library, but that's irrelevant to the question). One team writes the Core part (this code ends up in the (*.library.core package) , while another writes the individual effects (each effect is a single .java file in *.library.effects package + some shader code).
Currently the development works like this: each time a new effect gets written (lets say the class that implements it is called EffectBlahBlah), the Core team has to go over their code and, in one place, add a call to a static method EffectBlahBlah.init(), in another place - a call to another static method EffectBlahBlah.getUniforms(), etc etc. There are AFAIK 7 different places where we have to add 7 different calls to certain (static and non-static) methods from the new effect.
Now - having to add 7 lines of code is not the end of the world; however (especially in light of the fact that we are hoping to open the development of the effect part to outside programmers) we are hoping to automatize this in the following way:
have the Core scan the *.library.effect package and come up with a
list of all Effect classes that are there (we know how to do this)
in each of those 7 places in our code, automatically call the
appropriate method for each discovered class.
Now, if not for the static methods (which have to be there) I'd know how to do this: have all Effects extend an abstract class (lets say 'BaseEffect') which declares the 7 methods abstract, in each of the 7 places instantiate each effect in a loop using Class.forName(), cast it to a BaseEffect and call the appropriate method.
However Java does not allow abstract methods to be static. What do you recommend then?
You can use reflection for this. A possible sequence of calls is roughly:
Use Class.forName(name) to get the Class instance describing your class.
Call getMethods() on the Class instance to get the list of methods (or getMethod() to directly get a method, if you can figure out how to use it).
For the entries in the returned list of Method instances, use getModifiers() to check if it's static, and getName() to identify a specific method.
Once you found the desired Method instance, call the invoke() method on it to call the method. For static methods, you can use null for the receiver (first argument).
I have been creating Spinner controls (Combo boxes/Drop downs) in one of my apps, and was surprised to find out how difficult it was to achieve all of the following features:
User facing Strings are externalized, taking advantage of strings.xml internationalisation (I18N) feature of Android.
Spinner selections operate using a System view, which facilitates not having to work with or map Strings to meaningful values (yuck).
User view to System view mapping should be easy, automated and minimal (i.e not hand rolled for every component).
Others have attempted solutions to this, but universally as far as I could see they suffer from one or many of the following problems:
UI code is creeping into their enum class which doesn’t belong there (messy), nearly all existing solutions suffered from this.
Hardcoded User facing Strings in their enum classes. Because these are not externalized you cannot do I18N using the stock Android features.
Authors typically make the Fragment or Activity an OnItemSelectedListener which perpetuates a common problem of inheritance for convenience, where composition is more appropriate.
I have developed my own solution which does this: http://www.androidanalyse.com/android-spinner-externalize-user-strings-mapped-to-system-enum/
My question is, have I missed something? This seems like something that should not have been this hard (which makes me feel like I'm possibly reinventing the wheel).
Below is some example code showing my solution in-use (which is available Apache 2 license from the link above).
String none = getString(R.string.none);
String light = getString(R.string.light);
String medium = getString(R.string.medium);
String strong = getString(R.string.strong);
SpinnerUtil.createNewSpinner(view, R.id.wind, Arrays.asList(none, light, medium, strong), WindLevel.values(),
new SpinnerItemSelectedListener<WindLevel>() {
public void onItemSelected(Spinner item, WindLevel value) {
// Take whatever action you wish to here.
}});
I would just use ArrayAdapter<WindLevel>. Yes, you created a custom typed listener, but the regular event listener gets the position and can call getItem() on the ArrayAdapter<WindLevel> to get a WindLevel properly typed.
IMHO, the vast majority of Spinner widgets will be populated with material read in from a database, the Internet, or some other dynamic data source, rather than populated by some sort of enum with display values coming from static strings that can be internationalized ahead of time.
This is not to say that your code is useless: if you find it useful, then it was worth writing. And I am sure that there are apps out there that contain your targeted pattern (i.e., a Spinner backed by an enum or equivalent where the display values are known in advance and can be internationalized) who might find your solution useful as well. Every developer who writes enough code cooks up these sorts of helper classes and the like that help map an OS or framework model into something that better fits the developer's own mental model. So long as you are not perceiving any performance issues, it's all good.
Also, note that OnItemSelectedListener is an interface; implementing that interface on an existing class is not inheritance.
I believe the reason nobody answered you is :
What problem are you trying to solve ? Spinners existed prior to your well designed attempt.
Why reinvent them in exactly the same way they exist in Android ?
http://developer.android.com/guide/topics/ui/controls/spinner.html
It is a beautiful wheel indeed you designed, but still, it is just a wheel :)
UPDATE :
I think I begin to understand what you did. This is interesting. I'm not sure why you did not go to the pattern implemented by the ListPreference with its entries and entryvalues.
In fact, I'm not sure I understand why the Android team did not go that route either.
In any case, it is worth proposing your idea to the Android framework. It is after all open source.
I have a view that displays all the levels of my game. These levels are read by the activity and then passed into the view. I could read them from the view, but it's not really its responsibility, and I'm a fan of separation of concerns.
Right now, I'm calling a setter for this:
((GameView) findViewById(R.id.game)).setLevels(loadLevels());
However, I don't like the fact that the view will be dysfunctional if I forget to call the setter. Is there a better way to pass the levels in?
It is also a bit a matter of preference. Theoretically it's perfectly fine to pass the levels as you're doing. Alternatively, if you need more than just set the levels, but provide further functionalities (i.e. also saving of levels) I normally use a separate class responsible for handling such things (i.e. a Repository, some "Manager" class etc...). This class is then passed into the View on the constructor preferably s.t. one is forced to provide it. Of course, in order to separate things, I use interfaces rather than specific implementations s.t. it may then look as follows:
public class MyView {
public MyView(ILevelLoader levelLoader){
this.levelLoader = levelLoader;
}
...
}
Often, this may not work, because the view is something instantiated by the framework directly rather than by the application. In such a situation you're forced to do it through an appropriate setter. It is some sort of MVC/MVP pattern.
Just for your interest, you might also want to take a look at IoC containers and dependency injection. Guice provided by Google is a nice framework I've already used on Android.
I hope I didn't miss the point, but here goes:
Generally you have either a function setting something (like the text for a textview), or an attribute you set in the xml.
Take a look over at this answer I got on a question: How to layout a 'grid' of images in the center of the screen
There are some things the custom view needs, but lets take an example: 'numColumns'.
you can set it using setNumColumns (that would be the equivalent of your loadLevels() ? )
you can ignore it, it'll revert to default.
you can set it as an attribute lik so: app:numColumns="3"
You can try to use the attribute or the default in the class to accomplish this.
Make your view an abstract class with an abstract method getLevels()? This way, when you instantiate the class if you forget to pass the levels in your code won't compile.
Whether or not this is better is a matter of taste I guess :)