Is it possible to examine the R file and update its contents via reflection in an Android application. I was looking to change the value various constants defined in the R file ? Is it possible ? Would it make sense ?
It is not possible and, in my opinion, it wouldn't make sense.
The values in the R class change when you build your application and you can never guarantee that they will be the same. The integer values are not meant to be used directly, only they static constants should be used in your code.
It's not possible and it would not make sense.
R is a set of static fields. There is nothing you can do to change that.
Everything is baked into it on compile time.
Related
I want to make a small change to the Android standard TimePicker class. Specifically, I'm trying to change it so it works in 15 minute increments, rather than 1 minute increments.
This post helped me constrain the range of minute values to {0, 15, 30, 45}, as required in my app. But as I pointed out in a follow up comment, the minute spinner still shows previous minute as current value - 1, and the next minute as current value + 1, which creates a sloppy-feeling user interface.
I looked into the relevant Android source code, and it appears that the changes I would need to make are pretty simple. But when I tried copying the source code into my project I got about a zillion errors relating to the package declaration, where to find Widget, how to resolve R.id variables, etc.
So my question is:
What's the best way to make a small change to a given class from Android source code, and incorporate it into your own project?
In my case, I just need to make a few small changes to TimePicker and NumberPicker, but I'm not sure how to properly set this up in my project.
Thanks for any suggestions.
But when I tried copying the source code into my project I got about a zillion errors relating to the package declaration
Your source file's directory needs to match the package name. And since you cannot overwrite android.widget.TimePicker, you will either need to move that class to a new package or give it a new name.
where to find Widget
That implies that you copied TimePicker into one of your packages. That is fine, but then you need to add in the appropriate import statements for classes that TimePicker referred to from its original package. Or, you need to keep your (renamed) TimePicker in android.widget, adding this package to your project. This is rudimentary Java.
how to resolve R.id variables
If TimePicker relies upon resources that are not part of the Android SDK, you will need to copy those resources from the AOSP into your project as well.
What's the best way to make a small change to a given class from Android source code, and incorporate it into your own project?
IMHO, that cannot be answered readily in the abstract. Generally speaking, you do the sorts of things that I listed above.
You are best off subclassing the relevant classes and overriding the methods you would like to change.
In Java, you can do the following in a subclass:
The inherited fields can be used directly, just like any other
fields.
You can declare a field in the subclass with the same name as
the one in the superclass, thus hiding it (not recommended).
You can
declare new fields in the subclass that are not in the superclass.
The inherited methods can be used directly as they are.
You can write a new instance method in the subclass that has the same signature as the one in the superclass, thus overriding it.
You can write a new static method in the subclass that has the same signature as the one in the superclass, thus hiding it.
You can declare new methods in the subclass that are not in the superclass.
You can write a subclass constructor that invokes the constructor of the superclass, either implicitly or by using the keyword super.
More info on subclassing in Java
In android we have files by name String. Developers define the string values that they used for naming objects in this file. This is a very useful way. Because avoid of hard coding string values(you can change them from a single file, less time to change), also useful to creating multi language application and etc. (for more info just google this).
But the question is this: whether iPhone(Monotouch) have a mechanism like this to define strings on them or developers have to define themselves mechanism for this?
In XCode, you'll find File/New File, then on the left, pick "Resource", and you'll find "Strings File".
From code, you'll be referencing the keys in your strings file with NSLocalizedString:
NSLog("%#", NSLocalizedString(#"YOUR-STRING-KEY-OR-DEFAULT-VALUE", #"Comment about what this is"));
For details on what that second param is for, What is the second parameter of NSLocalizedString()?
Put your strings in a single file. Make them global constants. Access them throughout the app. When you change these, the change will be reflected everywhere.
It's not a big deal to have persistent string references throughout your app. It can be done in any decent programming language and platform I suppose.
Can I somehow alias a generated R file from a library and a generated R file from an application?
IE: I have two projects, one being a library. I reference the library in the application.
The library creates one R file, the application creates two: com.example.mapplication.R and the R from the referenced library, com.example.mlibrary.R. However, since I want to use both frequently in the application, I want to alias both the R classes. For example, call the library R something like libR and the app R something like appR.
I tried a couple of things which are of such stupidity, I won't even fully mention them, but I did some things like private com.example.mapplication.R appR = com.example.mapplication.R (immediately realising this wasn't gonna work), and private Class<com.example.mapplication.R> appRclass = com.example.mapplication.R.class;, but that didn't give me the desired effect. I do, however, use the latter method and some reflection to make it possible to be able to get the field and inner classes like this:
Class<com.example.mapplication.R> appRclass = com.example.mapplication.R.class;
int activity_main_layoutid = Toolkit.getFromClass(appR).
getMeTheInnerClass("layout").getMeAField("activity_main");
I haven't fully implemented the Toolkit method, but as we all know refletion can do this kind of stuff, but at the end of the day it's just as much work as just typing com.example.mapplication.R or com.example.mlibrary.R everywhere.
So to wrap thing up: Is it possible to alias multiple R's so that I can use appR and libR to distinguish the two?
I wish we could, but according to what I know, it isn't possible, at least not yet.
I also wish we could put resources in sub folders, but even this is impossible.
What you can do is setting a unique prefix (rename each resource file) for each library, as it's done by some third party libraries (like actionBarSherlock, which uses "abs" as the prefix).
Alternatively, you can have a special trick and put the files in the src folder and reach them from there, but that's more of a workaround, since the R won't have a reference to any of the resources there.
For example, you can put an image called image.png into the src/com/company/app_name, and then create a bitmap from it using:
final InputStream fis = getClass().getResourceAsStream("/com/company/app_name/image.png");
final Bitmap bitmap = BitmapFactory.decodeStream(fis);
By the way, if you've thought of using the assets folder, you can't do it for library projects, since it requires you to have the files in the project that uses the library project. It will work, but it misses the encapsulation idea...
I am looking for the preset android files that come with the Android os. Can someone direct me to the source?
(Android install path)\android-sdk-windows\platforms\android-version\data\res
Hope this is what you mean.
Call the following as an example:
android.R.*
You can access built-in animations, layouts, text fields, whatever you need.
So if you wanted to find the default android black color, call the following:
View.setBackGroundColor(android.R.color.black);
This returns the INTEGER containing the pointer to the appropriate resource files.
All R files are generated as integer pointers, so this is the proper way to access these resources.
Hope this helped!
Try codesearch from google:
http://google.com/codesearch (choose android on the left side) or directly:
http://google.com/codesearch#cZwlSNS7aEw/frameworks/base/core/res/&exact_package=android
go to gen-> android.support.v7.appcompat ->R.java
Android generated a special called the
‘R’ file. This is a file of constants that allow you to
get Java references to the TextView you defined
in main.xml In fact, you can get references to all
kinds of in app resources you define! But remember
the String resources you defined in XML? You can
get references to those too.
You mean R.java? It will be in %project root%/res/android/%your project name%/
In normal, we should use #+id/ to define an id and use #id to reference an id. Today I found #+android:id/title in apps/settings/res/layout/preferenc_progress.xml.
How to understand it and how to use it?
It is used for resources that are shipped with the SDK.
You can take a look at them by browsing to
[PATH TO ANDROID SDK]/platforms/android-[VERSION]/data/res
By using the android in android.R.whatever you just specify the R file to look up. For more information you should read Accessing Platform Resources.
That belongs to the app preferences activity screen definition.
title and summary are standard Android fields of a TextView preference item.
I think it does the same thing. It's just a more formal way of saying it by specifying where the namespace is.
I've never met this way of giving id, but in theory this means adding new id title to android package. So you'll be able to use it in your code like android.R.id.title. But I'm not sure resource compiler will really create any id in android package. I think it can be used only with predefined ids. But I'll give you more precise answer later, when I'll be able to check it.
EDIT: I've checked it and found some differences. Firstly, if you define Android's id using #+android:id/some_id, which is already present in SDK, this id will not be defined in your R.java file. If it's not present in SDK, it will be defined in R.java, but with different kind of value. Secondly, if you'll try to convert id from its string representation to int value, Resources.getIdentifier() method will return 0 in case of #+android:id format.
This means it will create an id in your resource file.