In Android, there is a recommendation that developers should not use enum. Instead of enum, Android supports some annotations, like #IntDef.
I tried this annotation is a simple project. My code looks like this:
#IntDef({APPLE, BANANA})
public #interface Fruit {
}
public static final int APPLE = 1;
public static final int BANANA = 2;
private #Fruit int mFruit;
If I try to set variable mFruit to 6 for example, I see the message that it must be one of APPLE or BANANA. This is fine, it works great.
When I paste this code to my second application and I try to set variable to different value than APPLE or BANANA, it works and there is no warning message and I am able to build application.
So, my question is: is there any way how can I disable or enable support of this annotation? What can cause this different behavior, that some project supports it and some project don't? I am using the same version of Android Studio for both projects.
You probably need to explicitly set retention policy. Look at the official Android IntDef example, where retention policy is set to #Retention(SOURCE)
Related
As I continue to work on and debug my hobby app to learn/practise Xamarin Android devt, I discovered I produced a version that could be installed on my phone, but it could not be run. (After successful installation, only the Done button could be pressed, the Open button was grayed out)
s'shot of Open button that is grayed out when the public static class is added in the code
There were a few changes since the last version that could be run, and having narrowed it down, the problem is the definition of a public static class in order to define some global variables.
public static class GlobalVariables1
{
public static string TdyAlertTime1 = "11";
public static string TdyAlertTime2 = "15";
public static string TdyAlertTime3 = "21";
}
This was adopted having followed How to declare global variable. I have tried making adjustments to that but still not resolving.
I also tried other methods found on the Net to no avail:
Store data and global variables using the Application object
public class HelloApplication : Application
{
public static int GlobalVariable = 1;
}
I also saw SharedPreferences and Application Properties Dictionary but the latter seemed applicable for certain functions eg. OnStart; and the former, I had poor experience before when trying to develop a Preferences screen.
But back to my original intention. I want to define simple global variables or constants (actually for debugging purposes currently, but learning it would be useful for other purposes too) to be utilised in two different classes in my project.
What could be wrong with the method I adopted (to cause the inability to run)? Or what method could I really use in a simple manner?
Thanx & Rgds
this is an extension of Android: Why do we need to use R2 instead of R with butterknife? and Reference in R.java not final
I understand that fields of R.java in the library project do not have final modifier to protect value collisions between library projects. However ButterKnife recovers final modifier in R2 and uses it.
I think this goes to the collision problem and values can collide, but there is no problem. How does it work?
===
I add examples.
There are one main project and one library project. The main project has com.main.R and the library project has com.library.R.
When there is a collision:
com.main.R: public static final int example = 0x1234
com.library.R: public static int example = 0x1234
if build tools does not recompile the library project, how can we avoid the collision between those values?
When ButterKnife creates R2
com.main.R: public static final int example = 0x1234
com.library.R: public static int example = 0x1234
com.library.R2: public static final int example = 0x1234
com.library.R2 has a collision and even it has a final modifier. Doesn't it produce a problem? why?
Thanks
Although final keyword has been removed from the R.java generated class since it caused a negative impact on the build performance, Butterknife uses only final for itself which is why only the Butterknife code needs to be recompiled everytime a new id is to be added. The good point is Butterknife uses annotations in order to make sure that type that we return is always correct.
From the doc:
In other words, the constants are not final in a library project. The reason for this is simple: When multiple library projects are combined, the actual values of the fields (which must be unique) could collide. Before ADT 14, all fields were final, so as a result, all libraries had to have all their resources and associated Java code recompiled along with the main project whenever they were used.
This was bad for performance, since it made builds very slow. It also prevented distributing library projects that didn't include the source code, limiting the usage scope of library projects.
The reason the fields are no longer final is that it means that the library jars can be compiled once and reused directly in other projects. As well as allowing distributing binary version of library projects (coming in r15), this makes for much faster builds.
Imagine If R.java was still supposed to contain the final keyword, for every library module that you've included in your android project, recompilation needed to be done since then R.java would be used by both the Android source code and libraries. Hence final keyword has been removed now. However, Butterknife still uses the final as it doesn't care about the clashes but BindView annotations internally use those type-annotations like #IdRes, #StringRes, #DrawableRes, etc inside that ensures the type safety of variables declared to be consistent.
I investigated further. In summary,
Resource values in library projects are reassigned when main project is built
"Final" needs to be removed to use reassigned values
Values in R2 is not reassigned so it might conflict, but it is only marker for Annotation. The actual value used when finding views comes from R
Details are here:
https://battleshippark.wordpress.com/2018/02/12/butterknife-library-project-r2-final/
I was happy using arc4random_uniform since iOS, and also for iOS targets of cocos2d-x.
Turns out it doesn't work for Android. The error:
error: 'arc4random_uniform' was not declared in this scope
How can I get around this?
Worst case, at compile time I'd check if arc4random_uniform() exists, and if not, use some other method (like the old arc4random()...).
I really would like to avoid using different code bases for different targets here.
Any other suggestions?
Note: As cocos2d-x is a "one code"→"many platforms", delegating this issue to Java code for Android would work against that.
Some of the C++ libs you can use in ios are not available in Android.
Unfortunately arc4ramndom is just one of them.
So the only way is to use an alternative of the stdlib like std::rand() or the default random engine if you want something more.
This is an example about how to use std::default_random_engine to get a random value in a given interval.
int randomValue(int from, int to) {
std::random_device rd;
std::default_random_engine e1(rd());
std::uniform_int_distribution<int> uniform_dist(from, to);
int mean = uniform_dist(e1);
return mean;
}
You can use Cocos2d native methods for generating random numbers. CCRANDOM_0_1() for example generates a random CGFloat between 0 and 1.
I am writing my first android app. It is a Unit Convertor. I planned to give four types of conversions in v1.0. While two of those are working fine, two more are not.
I want to release it with the two which are working first. But don't want to delete the code written for the buggy conversions.
While I can use my VCS for such purposes, I wanted to know if there is a way to control the availability of a feature using some configuration or something. I could not find any such reference online. But don't think I am the first person who has come up with such a need.
Is there some standard way of doing this? If so, can someone point me to it?
You don't say how you're displaying these 'features' If it's a button you could just change its visibility to Gone in the xml:
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
/>
The standard way that I have seen in some organizations is to maintain a separate Feature file where they have public methods that return whether or not this is supported in the particular version. Say for example,
inches to cm is available in version 1
pounds to kilogram is not.
In the Feature file, you can specifically mention these.
private static int InchesToCm = 1;
private static int PoundsToKg = 2;
public static boolean shouldShowInchesToCm() {
return InchesToCm <= getResources().getDimension(R.dimen.current_version);
}
I hope you get the point. You can set current_version separately. And then call these functions to check if or not you should show the View. Obviously just removing them by setting their visibility to INVISIBLE will work as well, but this is a standard method.
I'm trying to compile an app for a custom rom where addFlags(Intent.FLAG_FLOATING_WINDOW); can be used. But compiling it in android seems to cause errors and stop me from doing it. Is there a way i can disable error check on a specific .java file?
There is no (public) Intent.FLAG_FLOATING_WINDOW constant, according to the sdk documentation, hence the compile error. Presumably, it's specific to the custom rom your attempting to build for?
You cannot just bypass a compile error like this. However, since we're talking about a constant, you may be able to substitute the reference with the actual value. All the flag constants defined by the Intent class are simply ints, but you'd have to know the value in order to be able to replace it. You should be able to find that somewhere in the custom rom's source that you're referring to.
For example, suppose the contant would have the following definition:
public static final int FLAG_FLOATING_WINDOW = 1234;
Then a valid addFlags() call using this value would look like this:
addFlags(1234);
That will build, irrespective of the constant definitions in Intent.
Edit:
The question was related to Paranoid Android, for which the FLAG_FLOATING_WINDOW declaration is as follows.
/**
* If set, this intent will always match start up as a floating window
* in mutil window scenarios.
*/
public static final int FLAG_FLOATING_WINDOW = 0x00002000;
Source: Intent.java (#ParanoidAndroid)