I was planning to use generated resource IDs for all my startActivityForResult() codes, so that I can use onActivityResult() in base classes and not have to worry if the derived class used the same code.
Unfortunately it seems that the codes are restricted to 16 bits, and resource IDs are 32 bits. Is there a way to generate unique 16 bit IDs instead?
Actually there is. Moreover you can use standard id as Android resource. Simply just mask your id with 0x0000FFFF and use it wherever you want as ID for startActivityForResult() or requestPermissions() , you may use this simple utility:
public static int normalizeId(int id){
return id & 0x0000FFFF;
}
Why?
Firstly, Lets point to the reason behind that limitation to 16 bit vlaue. It's Fragment/Activity. OS enforces developers to use 16 bit while ID is 32 bit(as integer number) because system always masks id with 0xffff then shifts it with 16 (<<16) when call comes from Fragment. so it's a unique id marked as fragment target Id.On the other side, the id sent via activity stays as it's, so its activity target Id. Then when results come out, OS knows where to send whether to Fragment or Activity. Lets say we have this id Id=0x0001
Id in startActivityForResult() in Activity becomes(no-change):
Id=0x0001
Id in startActivityForResult() in Fragment becomes:
Id=0xFFFF0001
Now how comes we can just ignore the first 16 bit ? lets take a look on anatomy of id of any resource in Android. it composes of three parts as HEX value construction:
PPTTVVVV
PP: represents package id. There are two of them:
0x01 (system package ID)
0x7f (app package ID)
TT: represents type Id. i.e.:
0x0b : array
0x01 : attr
0x0c : dimen
0x10 : color
0x0e : bool
0x02 : drawable
.. etc
VVVV: represents real unique identification of specific type of resource under specific package id.
As you can see now that ignoring first 16bit which represents PPTT will not have impact on your app or leading to conflict with ids. So safely use only VVVV part which is 16 bit value in startActivityForResult() or requestPermissions()
I hope that may help you,'.
Related
(Moved from https://softwareengineering.stackexchange.com/questions/406813/how-to-implement-fnv-1a-in-sqlite)
I'm trying to modify a SQLite query (in Android) to return its results in pseudorandom order. As in this question, the order needs to be stable over repeated queries (e.g. due to paging, screen rotation, etc.), so I can't just use ORDER BY RANDOM(). Instead I want to use a hash function that depends on a couple of input values that provide stability and sufficient uniqueness. (One of these values is a unique ID column of the table, which is a set of integers fairly close together; the other value is more like an session ID, also an integer, that remains invariant within this query.)
According to this well-researched answer, FNV-1 and FNV-1a are simple hash functions with few collisions and good distribution. But as simple as they are, FNV-1 and FNV-1a both involve XOR operations, as well as looping over the bytes of input.
Looping within each row of a query is pretty awkward. One could fake it by unrolling the loop, especially if only a few bytes are involved. I could make do with two bytes, combining LSBs from the two input values (val1 & 255 and val2 & 255).
XOR isn't supported directly in SQLite. I understand A ^ B can be implemented as (A | B) - (A & B). But the repetition of values, combined with the unrolling of the loop, starts to get unwieldy. Could I just use + (ignoring overflow) instead of XOR? I don't need very high quality randomness. The order just needs to look random to a casual observer over small-integer scales.
So I'm wondering if anyone has already implemented such a thing. Given how widely used this hash function is, it seems like there would likely already be an implementation for this situation.
Here's my attempt at implementing FNV-1a:
SELECT ..... ORDER BY (((fnvbasis + val1 & 255) * fnvprime) + val2 & 255) * fnvprime % range;
I'm ignoring the fact that in FNV, the XOR operation (which I've replaced with +) is only supposed to affect the lowest 8 bits of the hash value. I'm also ignoring any overflow (which I hope just means the upper bits, which I don't care about, are lost).
For fnvbasis I'll use 16777619, and for fnvprime I'll use 2166136261. These are the specified values for 32 bit input, since I don't see a specified value for 16 bit input. For range I'll use a prime number that's greater than the expected number of rows returned by this query.
So is this a reasonable way to approximate FNV-1a in a SQLite query? Is there a better, existing implementation? I.e. will it actually produce an ordering that looks pretty random to a casual user, despite my mutilating the operations of the real FNV-1a?
Inspired by comments from rwong and GrandmasterB on the previous attempt at this question before I moved it, I decided I could precompute the first iteration of FNV-1a's loop, i.e. the hash based on the unique ID column of the table. The precomputed column, fnv1a_step1, is set to
(fnvbasis ^ (ID & 0xFF)) * fnvprime
Because this value is precomputed on each row of the table separately, it can be supplied by the app and doesn't need to be expressed in SQLite; hence the use of ^ (XOR) above. Also, if ID is a string, we can compute an 8-bit hash value from it in Java or Kotlin as well. But we could even use
(fnvbasis + (RANDOM() & 0xFF)) * fnvprime
(back to using + if doing this in SQLite) because the value is only computed once, and therefore is stable even when computed from RANDOM().
The second iteration of the FNV-1a loop can be computed pretty simply in the ORDER BY clause of the query, using the current session ID, so it produces a different-but-stable ordering for each session:
ORDER BY (fnv1a_step1 + sessionId & 0xFF) * fnvprime % range;
I've implemented this in my app, and it seems to work, to my requirements. The order is stable within a session, but is different in each session.
I know there are many alternatives to reach what I wish, but I wont this solution because it is the most comfortable to me. I wish to use enum that starts with number, like so.
public enum Quality {
1080p,
720p,
BlueRay //this one OK
}
And then use it like so when converting to string:
Quality.1080p.name();
Why it is not possible?
Because the Java language doesn't allow variable names to start with a number- just a letter or underscore. Any character after the first may be a number. The main reason for this is to make parsing easier, and prevent situations where the parser can't tell if a symbol is a number or a variable name.
For example, if numbers were valid at the start of a variable I could do the following:
String 1 = "string";
System.out.println(1);
Does this print 1 or "string"? They avoid the problem by not allowing it. Many (most?) languages have that restriction.
This question's answer explains the situation with Java well. I would like to know what the situation is with Android. Specifically:
Question 1: For a given string, will the hash code always be the same? (Even more specifically, I need a hashcode of a given string to be the same on a user's phone each time the app is opened).
I googled for the source of android's String and found this, but I'm playing with fire because I don't know the first thing about Android source, if/when it's modified by manufacturers etc.
Question 2: If the answer to 1 is no, then would it be sensible for me to use the hashCode() code in the source quoted above in my own hashCode() function?
The same String should has the same hashCode() (based on hashCode definition)
If you take a look at Android hashCode() of String class. You will see hashCode is calculated based on char array (the same), char count ( the same) and offset field ( this value seems always Zero (0) - is set in String constructor - I don't know why Google adds this offset field. Oracle String.hashCode() is calculated based on char array, char count only.
You can build your own hashCode() function like Oracle String hashCode(): This implementation is based on char array and char count so the same String always has the same hashCode().
As the hash-code algorithm is actually specified in the interface contract, and the Java-doc is also used as part of the Android SDK headers, I suppose you can count on it as being "stable".
But you might be better of to use a cryptographically strong hash function like SHA1 or SHA256 depending on your use-case, as they will also be a lot less likely to produce collisions (The Java hashCode() has only a 32-bit value range!).
I ask this because I have exceptions from reports (from users from the market), mentioning that I have duplicated views with id 0x2 (or 0x3).
Since all my generated ids are really big, I think that the views with duplicated ids are views with no specifically defined ids.
My question is what are the ids of the views, that the developer hasn't explicitly assigned ids to them.
Thanks in advance,
Danail
The AAPT constantly updates your R file to generate unique hexadecimal values for each of your own IDs. In terms of IDs YOU create, they only need to be unique within the parent viewgroup. As always please post your stacktrace.
According to the source code, a View for which you haven't set an ID, has an ID of -1.
public static final int NO_ID = -1;
I would say no id is created if you do not specify an id to a view. Try creating a very simple application and create components with no id's , you'll notice that no id's are created in the R.java file.
I have very basic understanding problem of Content types.
I went through lot of examples and text explaining the above term, but still have some basic understanding problem. Can some clarify me please.
In the android notepad example, and many others, it is mentioned vnd.android.cursor.dir/ resolves to a list of items in a directory and vnd.android.cursor.item/ refers to specific item in a directory.
Is this vnd.android.cursor.dir some standard constant defined by android. Where did this come from?, or can i change it like
vn.com.android.myexample.dir/
How is this even resolved and what is its purpose, why not use the full CONTENT_URI?
Sorry, i'm totally lost, and don't understand this.
Documentation: https://developer.android.com/guide/topics/providers/content-provider-basics#MIMETypeReference
The MIME types returned by ContentProvider.getType have two distinct parts:
type/subType
The type portion indicates the well known type that is returned for a given URI by the ContentProvider, as the query methods can only return Cursors the type should always be:
vnd.android.cursor.dir for when you expect the Cursor to contain
0 through infinity items
or
vnd.android.cursor.item for when you expect the Cursor to contain
1 item
The subType portion can be either a well known subtype or something unique to your application.
So when using a ContentProvider you can customize the second subType portion of the MIME type, but not the first portion. e.g a valid MIME type for your apps ContentProvider could be:
vnd.android.cursor.dir/vnd.myexample.whatever
The MIME type returned from a ContentProvider can be used by an Intent to determine which activity to launch to handle the data retrieved from a given URI.
Where did this come from?, or can I change it like vn.com.android.myexample.dir/
No, because "vnd" stands for vendor in MIME Registration trees, android in this case.