i wrote a View class based on ViewSwitcher and now I want to write helper classes for the view like known form the ListView: ListAdapter, ListActivity and so on..
Regarding the activity class I ran into a problem. The ListActivity forces you to add a ListView to your activity with a fixed id: #id/android:list. In my base activity class i want to archive the same, forcing a special id so that my helper classes can access the view object.
As I'm writing a general lib that could be used in various projects I can't use R.id.foobar to get the view as there's no R class. The specific project will an own R.java.
So I peeked at the source code of ListActivity and found:
View emptyView = findViewById(com.android.internal.R.id.empty);
mList = (ListView)findViewById(com.android.internal.R.id.list);
if (mList == null) {
throw new RuntimeException(
"Your content must have a ListView whose id attribute is " +
"'android.R.id.list'");
}
Ok, I could write my on R class, put it directly into my package and try to access it in the same way but I've no clue what value the id should have or need?
Also I couldn't find any R class at android_frameworks_base/core/java/com/android/internal
And even if this problem is solved: How can the user of my lib access "my id" from his layout XML?
Thanks for your help! :)
I do not think this is safe, as Android has not supplied reusable widget authors with an ID range to use for your desired purpose.
Instead, do one of the following:
Have the reuser of your widget pass in the appropriate ID.
Use Resources#getIdentifier() to look up an ID in the R.* "namespace" given the string form of the name. If you go this route, be sure to cache this result, as it is a bit expensive to look up, apparently.
If you're creating a library APK that other applications can use, then consumers of this library cannot refer to its resource IDs in XML layouts.
When an Android application is started, it loads in and caches resource information from the application APK (resources.arsc), plus the system resources (i.e. those in android.R).
Your application, running in a separate process and as a different user ID, cannot directly read the resources from other APKs.
However, if you're just using the library for your own purposes, you should be able to get a greater level of access between your APKs by signing them with the same key, or specifying the same process ID in your manifest.
you can refer to raw resources supplied by a ContentProvider over a URI, I read Jpeg's out of Zips supplied by a ContentProvider that the user downloads in a seperate apk.
the uri is something like
android.resource://name.of.component/r_file_id
Then the ContentProvider can return the appropriate resource file identification to the calling app and it can then access the file over the URI.
edit: Same keys might be necessary for this to work
Related
Whenever we want to inflate a view or get a resource we have to cast it in run-time. views, for example, are used like so:
In the past, we would have needed to cast it locally
(RelativeLayout) findViewById(R.id.my_relative_layout_view)
Now, we use generics
findViewById<RelativeLayout>(R.id.my_relative_layout_view)
my question is why doesn't the compiler(or whoever generates the R class) doesn't also keep some kind of a reference to the type of the element(doesn't matter if it's a string or an int or any other type) that way casting problems should not occur
We cannot really speculate on that, that would be a design choice.
It might be that they wanted to avoid bloating the APK. Every ID would need a full package name to the class. So would each ID in android.R too. Since R is packaged in every APK.
Solutions
However, if you are using Kotlin, you can even do away with the generics check. Kotlin will determine it automatically.
val view = findViewById(R.id.my_relative_layout_view)
view.method()
Or event simpler, if you use synthetics:
my_relative_layout_view.method()
Also, if you are using data bindings, you can just access it like this:
binding.my_relative_layout_view.method()
I realized that when calling "createFile", it creates a new file even if its title is an already existing title.
What am doing now is to search for the file first and if i can't find it, i create it. Two methods for a simple problem.
There is a better way to create a file overriding it if already it exists?
Google Drive is actually a 'flat' model, where every object is identified by it's unique ID.
So, when an object (file/folder) is created, it gets a unique ID. The object may/not have content. Everything else is 'metadata'. The tree structure of popular OSs is actually 'faked' by metadata links (parent links). That means in Google Drive you may have multiple children with the same metadata (title/name) in a parent object. And you may also have multiple parents for any child object (single object appears in multiple parents' folders).
All this rant means one thing for your situation:
Once you create a file/folder and get hold of it's ID, 'creation of a new file with the same name' can be accomplished by modifying it's content and/or metadata (you can see a typical example here).
If you take the path of delete/create (which is also possible, but had not been until recently), you are actually:
1/ modifying the original file/folder's 'trashed/deleted' metadata
2/ creating a brand new object with a different ID
Think twice before you select the method you use. UPDATE method is a 'one-step', approach preferable in async environment (create MUST wait for successful delete). On the other hand, if you use DELETE/CREATE approach you may be able to take advantage of the fact that 'trashed' object will be around for a while.
Good Luck
I think files are uniquely identified by their ID in the Drive API. Therefore you have no way to control for the title using the drive API itself. So doing it yourself is probably the way to go.
EDIT: The ID is what is important with all that synchronisation happening. A title could change easily therefore using it as a unique identifier would be a bad idea. Hence the unique ID.
What you could do if the file already exists is either remove it and replace it by the new one (bad idea I would say) or simply add an extra number at the end of the new file that will be added to the folder.
I have been working on a simple android tutorial and while browsing through the project folders I found this R.java file in gen folder...
When I opened it seemed to me as a mess...
first R itself is a class.
it had multiple Inner classes defined within eg drawable,id,layout,etc.
and that inner classes had lots of variables declared as below which were assigned with hex values
public static final int addr=0x7f080003;
...
...
and much more
R is auto generated and acts as some pointer for other files
Questions for R.java
what it is basically for
how it works
why
values are in hex
what role did it performs while the actual application is running
"Acts as some pointer to other files" is actually absolutely correct, now the question is which files it points to how it is done.
What does it contain?
R file contains IDs for all the resources in the res folder of your project and also some additional IDs that you define on your own (in the layouts, for example). The IDs are needed for the Android resource management system to retrieve the files from the APK. Each ID is basically a number which corresponds to some resource in the resource management system.
The file itself is needed so you can access or reference the resource from code by giving the ID of the resource to the resource manager. Say, if you want to set the view in the activity, you call
setContentView(R.layout.main);
main in the R file contains the number which is understood by the Android resource management system as the layout file which is called main.
Why is it better than just plain file names?
It's harder to make a mistake with the generated fields. If you write the field name incorrectly, your program won't compile and you will know that there's an error immediately. If you write an incorrect string, however, the application won't fail until it is launched.
If you want to read more on this topic, you should check the Android documentation, especially the Accessing Resources part.
This holds your resource ids. So when you do something like
TextView tv = (TextView) findViewById(R.id.mytextview);
it looks up your id here for that View, layout, etc... This way the app has an easy way to look up your ids while you can use easy to remember names. Anytime you create a resource it automatically creates an id for it and stores it here. That's why you never want to try and edit this file yourself.
One way to think about how valuable R.java is, imagine a world without it. Its amazing how android brings the xml and java world together to help avoid coding the UI manually completely. With legacy java building UI using the java language was a pain. Invaluable.
With Android you can not only build your UI using only xml, but also see it while you build it. Invaluable.
Every element in the xml can be referenced in the java code WITHOUT writing a single line of code to parse the xml :). Just R.id.nameOfElement. Invaluable.
Rapid development is beautifully done in android. Imagine if iPhone would have 5000 screens to fit that one piece of code, they would crumble on their XCode. Google has done a wonderful job with just R.java. Invaluable.
I am doing some debugging in my application, mainly loading custom styles from styles.xml when my custom view is given a style="#styles/CustomStyle", and attributes such as custom:attribute="custom value"
I looked into the TextView source to see how Android loads styles/attributes and I am mimicking that. However I am not being passed any of my R.styleables through some of the calls to my constructors and so I am trying to peek in there to see which resources are coming in.
I am using obtainStyledAttributes() to load these key/value pairs into a TypedArray, however I am wondering if there is an easy way to convert the R.styleable.CustomWidget_customAttribute from the int that R reads, to its referenced name.
In essence, I want LogCat to say, "We've been given R.styleable.xxx" and not "We've been given 1487214712442"
Look at this method: http://developer.android.com/reference/android/content/res/Resources.html#getResourceName(int)
Return the full name for a given resource identifier. This name is a single string of the form "package:type/entry".
You most likely are not able to do this explicitly, as all resources are stored in a generated java class with no accessible reference to the original strings.
However, your best bet is override the toString() method for the R class.
See if something like that works.
Hope this helped!
I am building an Android app, and I have a problem to get resource from string.xml.
I need to have a URL in String.xml that will be used several times through the app.
I tried Resources.getText("my_url"), but this does not work. Eclipse complains when I use this.
Do you think this is the best way to do ?
What you probably want is:
String myUrl = getString(R.string.my_url);
The getString() method is in Context which means that it's available directly in your Activity class since Activity is a subclass of Context. (The getString() method is also in Resources but it's easier to call on it directly on your Activity.)
What happens with your XML resources is that each is given a unique integer ID and this is added to the automatically generated R class as a public static final int. You then use these IDs to reference the resources. Have a look in the gen folder in your Eclipse project and you'll find the R class in there.
Do you ever refer this page: https://developer.android.com/guide/topics/resources/available-resources.html ?
If you want to retrieve the String represented by a resource ID, you can call the Context.getString() method.
Or, you have to post Eclipse's complains.