I have defined this #IntDef
public static final int LINE = 0;
public static final int CORNER = 1;
#IntDef({LINE, CORNER})
#Retention(RetentionPolicy.SOURCE)
public #interface ShapeTypes {}
and assigned it to one of my class members like this
public #ShapeTypes int shapeType;
and if I remember correctly, it used to work, but now, in Android Studio 3.1.2 I'm able to do something like this
myClassObj.shapeType = 99;
Shouldn't it cause compilation and/or runtime errors? Is there a way I can define range of allowed values for the variables now?
Update
It seems, that all annotations are not working anymore.
#IntRange(from = 4, to = 18)
public int size;
does not affect the statement size = 20;
Am I missing something? Some setting to turn on the annotations?
I'm having same problem in Android Studio 3.1.2. But one of my colleagues tested it in 3.1.0 and it seems it is working in that version.
IntDef treat like enum so you can't initialize later. You have declare manually.
#IntDef({ShapeTypes.SHAPETYPE})
#Retention(RetentionPolicy.SOURCE)
#interface ShapeTypes {
int SHAPETYPE= 0;
}
For more details have look this
Related
I am not clear how to use #Intdef when making it a flag like this:
#IntDef(
flag = true
value = {NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS})
this example is straight from the docs. What does this actually mean ? does it mean all of them are initially set to true ? if i do a "or" on the following:
NAVIGATION_MODE_STANDARD | NAVIGATION_MODE_LIST
what does it mean ...im a little confused whats happening here.
Using the IntDef#flag() attribute set to true, multiple constants can be combined.
Users can combine the allowed constants with a flag (such as |, &, ^ ).
For example:
public static final int DISPLAY_OP_1 = 1;
public static final int DISPLAY_OP_2 = 1<<1;
public static final int DISPLAY_OP_3 = 1<<2;
#IntDef (
flag=true,
value={
DISPLAY_OP_1,
DISPLAY_OP_2,
DISPLAY_OP_3
}
)
#Retention(RetentionPolicy.SOURCE)
public #interface DisplayOptions{}
public void setIntDefFlag(#DisplayOptions int ops) {
...
}
and Use setIntDefFalg() with '|'
setIntDefFlag(DisplayOptions.DISPLAY_OP1|DisplayOptions.DISPLAY_OP2);
The title sums it up very well.
I am using the #Intdef annotation in order to define which constants I can use as params or return values in some methods, like so :
#Retention(RetentionPolicy.SOURCE)
#IntDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS})
public #interface NavigationMode {}
public static final int NAVIGATION_MODE_STANDARD = 0;
public static final int NAVIGATION_MODE_LIST = 1;
public static final int NAVIGATION_MODE_TABS = 2;
#NavigationMode
public int getNavigationMode() {
return NAVIGATION_MODE_LIST;
}
public void setNavigationMode(#NavigationMode int mode) {
mNavigationMode = mode;
}
As a test, I have added this call :
setNavigationMode(5);
Android Studio shows it as an error, which is great, but I would also like to make the Gradle build check this lint rule for release builds (I don't want to lengthen debug builds with lint checks though).
So, I have added this to my build.gradle :
lintOptions {
abortOnError true
checkReleaseBuilds true
fatal 'NewApi', 'InlineApi', 'ResourceType'
}
However, Gradle compiles this project without detecting this error.
Am I missing anything ?
With the version 1.3.0-beta1 of the android gradle plugin, we now have a Lint check for IntDef annotations.
In a comment on this Google+ post Tor Norbye explains that ResourceType checks are built on top of IntelliJ, and do not work with lint currently. It may in the future.
Firstly, I have to say that I am just a beginner with the Android programming, and I may not understood things correctly. ^^
Secondly, my problem is that the R file (the one which create the different IDs of the objects) just stopped to create new ones.
I noticed that when I created a new image_button at the main_layout and when I tried to look for it on the MainActivity it wrote that it didn't exist.
Moreover, only after I modify the R file (which I should not touch according to the system warning), I have control over the new IDs.
And after breaking my head for two days - I decided to ask you,
The R file:
public final class R {
public static final class attr {
}
public static final class dimen {
/* Default screen margins, per the Android Design guidelines.
Customize dimensions originally defined in res/values/dimens.xml (such as
screen margins) for sw720dp devices (e.g. 10" tablets) in landscape here.
*/
public static final int activity_horizontal_margin = 0x7F040000;
public static final int activity_vertical_margin = 0x7F040001;
}
public static final class drawable {
public static final int ic_launcher = 0x7F020000;
public static final int loading_i = 0x7F020001;
}
public static final class id {
public static final int action_settings = 0x7F080004;
public static final int button1 = 0x7F080001;
public static final int imbt = 0x7F080003;
public static final int textView1 = 0x7F080000;
public static final int tv1 = 0x7F080002;
}
public static final class layout {
public static final int activity_main = 0x7F030000;
public static final int firstpage = 0x7F030001;
public static final int loading_screen = 0x7F030002;
}
public static final class menu {
public static final int main = 0x7F070000;
}
public static final class string {
public static final int action_settings = 0x7F050001;
public static final int app_name = 0x7F050000;
public static final int hello_world = 0x7F050002;
}
The creation of the new object:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ImageButton
android:id="#+id/imgBtn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
Yep, you shouldn't edit the R file directly. The problem you meet is normal. It should be causes by a file out of sync.
Hopefully, you could fix it by:
Option #1: Try to refresh whole project and 'Project -> build project'.
Option #2: If #1 doesn't work, hit 'Project - clean...', and then rebuild the project.
Option #3: Sometimes, #1 and #2 don't work. The last ultimate way,
which always works for me, is to delete the `gen` folder and rebuild the project.
Make sure that
Project --> Build Automatically
If it's already checkedm, run clean:
Project --> clean
If that doesn't work, then most likely there is an error in one of the files, most likely one of the layout XML files. Check the Problems view:
Window --> Show View --> Problems.
Fix all the problems (you can ignore the warnings).
Your last resort is to delete the R file (backup first) and then re-built (or clean).
It's one of the most common problems beginners face; even I faced this too. :)
The most obvious solution is to try cleaning and building your project. Sometimes it works, and most of the times it doesn't.
When cleaning and building doesn't work, then most likely you have some error in your code and that too in XML files. Android tools sometimes don't show which XML file has the error, so you manually need to open each file and check for errors. Once you have fixed the errors, your R.java will build automatically.
I hope this helps.. :)
Update:
This used to happen for Eclipse and ADT plugin. Android Studio is the savior. Start using it if you aren't already.
Clean your project and run it:
Project---> Clean then run
See Stack Overflow question Developing for Android in Eclipse: R.java not generating. It gives the perfect solution for you...
Change the build target version and clean the project. After completing that, change that build version to previous. It works for me.
am very much a newbie when it comes to android development so bear with me. Im currently using Windows 8 / Eclipse.
My issue is, the findViewById function seems to have gone mad, although I could very well be using it wrongly.
The app was working fine, then I 'dropped' a few new TextViews on the page which seems to totally confuse it.
The findViewById function now either finds the wrong control completely, or doesnt find anything at all (and will return null). I've checked my activity_main.xml file and the id's are still correct.
Can anyone help?
This is a typical example of my usage:
public void toggleButtonNetwork_Click(View v) {
ToggleButton tb = (ToggleButton) this.findViewById(R.id.toggleButtonNetwork);//did work, now does not work!
}
The only insight I may add is that my R.java file looked like this when it was working:
...
public static final class id {
public static final int menu_settings=0x7f070004;
public static final int textViewGPS=0x7f070003;
public static final int textViewNetwork=0x7f070001;
public static final int toggleButtonGPS=0x7f070002;
public static final int toggleButtonNetwork=0x7f070000;
}
...
and now looks like this (broken):
public static final class id {
public static final int menu_settings=0x7f070006;
public static final int textView1=0x7f070004;
public static final int textView2=0x7f070005;
public static final int textViewGPS=0x7f070002;
public static final int textViewNetwork=0x7f070003;
public static final int toggleButtonGPS=0x7f070000;
public static final int toggleButtonNetwork=0x7f070001;
}
This is a quite common problem. Try and invoke the Project/Clean... on your project. It sometimes happens that the automatic generating of the R classes goes wrong and this will force them to be rebuilt.
Everthing is fine.
Always Just go to project -> clean
And than run .
Thats it.
This doesn't answer your question. I suspect that A--Cs comment is correct.
But, there is nothing to be confused about. findViewById is really simple.
When you compile your app, the compiler generates R.java and adds a line for each view in your layout XMLs (and strings, drawables, colours etc - anything that is a "resource") and gives it a unique ID.
public static final int toggleButtonNetwork=0x7f070001;
The ID will change as you change your resources, but it doesn't matter. When you use findViewById, you give it the "friendly name", in this case R.id.toggleButtonNetwork, which is compiled into 0x7f070001 since public static final int toggleButtonNetwork is a static constant.
When you inflate your view from XML, typically with setContentView, the view hierarchy of objects is built. The id of each object is the id found in R.java.
findViewById returns a reference to the object, of type View, which you then cast to whatever type of View it is which is why you use
= (Button)findViewById(R.id.toggleButtonNetwork);
I am creating a library project for a number of android apps.
The apps all have some common functionality that I wish to include in the library project but the library project functions require use of application specific constants
So I am looking for a way to provide the library functions with the names of the constants and allow each app to define them
An example of a specific app constant and how it is used within the library project
public class AppConstants {
public static final long APP_ID = 6;//Needs to be set for each app
}
public static long getCurrentAppId(Context context) {
return getLongPreference(context, CURRENT_APP_ID_KEY, AppConstants.APP_ID);
}
This is just one example of approximately 60 constants that need to be defined for each app for a large number of library functions
Obviously I would normally just import/include the project specific app_constants.java file but this is not possible in the library project files as it hasn't got a clue about the specific applications (rightly so)
So what is the best way to have each specific app override the constants?
Update
I took a long time deciding on which of the superb answers I have been provided with best suited my needs (Thanks everyone) In the end I chose the xml solution. I don't particularly like it because it clutters up my apps resources and I did seriously consider using the interface solution but the xml solution does work nicely
Option #1
Extend your AppConstants class in each project
Better Option#2
Use XML resources to define the constants
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item type="integer" name="app_id" format="integer">6</item>
</resources>
then you can retrieve them by
Context.getResources().getInteger(R.integer.app_id);
add the xml file to your resources in each project with only the values you need different
I don't know of a great schema to do that but it would certainly work this way:
define some base class in your library
// class, enum or whatever you want it to be.
class BaseConstants {
// use some real singleton instead
public static final BaseConstants instance = new BaseConstants();
// define those values - sadly static inheritance does not work
private static final int APP_ID = 0;
private static final int CURRENT_APP_ID_KEY = 24;
// so we have to do that via methods
protected int getAppId() {
return APP_ID;
}
protected int getAppIdKey() {
return CURRENT_APP_ID_KEY;
}
}
let each Activity that wants something custom implement that
class App1Constants extends BaseConstants {
public static final App1Constants instance = new App1Constants();
private final static int APP_ID = 1;
// want a different APP_ID here.
protected int getAppId() {
return APP_ID;
}
// getAppIdKey not implemented here, uses default
}
Use that class as context to the constants for your library
class Library {
public static long getCurrentAppId(Context context, BaseConstants settings) {
return getLongPreference(context, settings.getAppIdKey(), settings.getAppId());
}
}
Activities would be like so
class myActivity extends Activity {
// each Activity can implement it's own constants class and overwrite only some values
private static final BaseConstants CONSTANTS = App1Constants.instance;
private void whatever() {
long appId = Library.getCurrentAppId(this, CONSTANTS);
}
}
class myActivity2 extends Activity {
// or could just use the default ones
private static final BaseConstants CONSTANTS = BaseConstants.instance;
private void whatever() {
long appId = Library.getCurrentAppId(this, CONSTANTS);
}
}
That schema is kind of ugly but it would work at least
Define them as enum's in your library project, like
public enum Planet { MERCURY, VENUS, MARS }
Android proper takes another approach, the dreaded constant interface, like,
interface Planets {
static final int MERCURY = 1;
static final int VENUS = 2;
...
}
However, this is a well-known Java anti-pattern (constant interface, and is covered in detail in Effective Java, I quote,
The constant interface pattern is a poor use of interfaces. That a
class uses some constants internally is an implementation detail.
Implementing a constant interface causes this implementation detail to
leak into the class’s exported API. It is of no consequence to the
users of a class that the class implements a constant interface. In
fact, it may even confuse them. Worse, it represents a commitment: if
in a future release the class is modified so that it no longer needs
to use the constants, it still must implement the interface to ensure
binary compatibility. If a nonfinal class implements a constant
interface, all of its subclasses will have their namespaces polluted
by the constants in the interface.
If you need the constants to have int values for some reason, and calling toString() on the enum isn't sufficient, you can give the enum's a extra information like,
public enum ZipCode {
LYNNWOOD(98036), SAN_JOSE(95112), ...;
private int zipCode;
private ZipCode(int zipCode) { this.zipCode = zipCode; }
public int getZipCode() { return zipCode; }
}
Note that enum's are slightly less performing than integer constants, but from a code organization and clarity perspective they are far superior.