Android's PackageManager class has currentToCanonicalPackageNames() and canonicalToCurrentPackageNames() methods. What exactly is canonical package name? Where is it used (what's its purpose)? When does it differ from a current package name?
For example, on my Nexus S the current package name for browser app is "com.google.android.browser", and its canonical name is the same "com.google.android.browser". For some other applications I've checked I also get same current and canonical package names. Neither developer.android.com, nor source code gives me an explanation of what exactly is canonical package name. Hope this helps to better understand what I'm asking above.
Here is developer documentation:
http://developer.android.com/reference/android/content/pm/PackageManager.html
public abstract String[] currentToCanonicalPackageNames (String[] names)
Added in API level 8
Map from the current package names in use on the device to whatever the current canonical name of that package is.
Parameters
names Array of current names to be mapped.
Returns
Returns an array of the same size as the original, containing the canonical name for each package.
public abstract String[] canonicalToCurrentPackageNames (String[] names)
Added in API level 8
Map from a packages canonical name to the current name in use on the device.
Parameters
names Array of new names to be mapped.
Returns
Returns an array of the same size as the original, containing the current name for each package.
Check out this link of the source for a better understanding:
https://android.googlesource.com/platform/frameworks/base/+/483f3b06ea84440a082e21b68ec2c2e54046f5a6/core/java/android/app/ApplicationPackageManager.java
And please refer to this StackOverflow question: how do i get canonical names of packages of deafult apps in Android
Related
I would like to do something, I don't know how to do it. But before, let me explain the previous steps:
1st: I have defined a content manager that, when I introduce a specific "id" from a resource, it finds such reosurce and shows it to me. In addition, I have created a POJO for the resource and an interface in which I specifiy my request.
2nd: Now I want to be able to incorporate such resources into a local data base. So, I have defined my entity for such data base (and that entity has the same attributes that the resource (consulted) from the API). Then I have defined the contract for such entity and the repository for that entity (where I have defined my query as "WHERE field "name" = (...)" .
3rd: After that, I have defined a ContentProvider for my DB.
4th: Finally, there is my MainActivity, which acts as a Client to consult my DB through my content provider.
Now, my question is, how and where I have to define the next:
a) When I make a search -based on the attribute name of the resource-, if the content provider doesn't find it in my local DB, then a request is made to the API (and the name specified on my search should fit with the attribute "name"
of the resource in the API).
b)Once the response with the resource is given, my local DB should add that resource as a new entity.
Thanks.
I hope I have explained myself well.
For my testing I used:
private static final String SKU_PRO = "android.test.purchased";
Now I want to release my app and create the purchasable item in the developer console. Before releasing the apk I have to know how to name the SKU.
In a tutorial I read they used this:
"com.example.buttonclick"
But my packagename looks like this:
"com.myname.myapp"
My suggestion is:
"com.myname.myapp.purchasedpro"
Is this the correct way?
From developer docs:
Product ID
Product IDs are unique across an app's namespace. A product
ID must start with a lowercase letter or a number and must be composed
of only lowercase letters (a-z), numbers (0-9), underscores (_), and
periods (.). The product ID android.test is reserved, as are all
product IDs that start with android.test.
Note: Be sure to plan your
product ID namespace carefully. You cannot modify an item's product ID
after the item is created, and you cannot reuse a product ID within an
app.
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,'.
I would like to access the content provider using URI, which is of the following form.
sUriMatcher.addURI("org.abcd.providers.contentprovider", "bookmarks", 1)
So, can I access it using the URI, "content://org.abcd.providers.contentprovider/bookmarks" ? What does the value "1" mean? How do I query the provider of this type, Thanks in advance.
The "1" is used internally in the ContentProvider. Its used to associate an URI with an number. Handy for using in a switch statement.
Why not using String matching? Well, an URI might have variable parts. For example "content://my.provider/bank/customer/2". The 2 is the Id of the customer. Or "content://my.provider/location/42/name". The variable part here is the 42. String matching goes out of control here. The UriMatcher on the other hand is able to match example 1 with addURI("my.provider", "bank/customer/#", 1) and example 2 with addURI("my.provider", "location/#/name",2). When we ask a configured UriMatcher to match a URI it returns the number associated with the matching URI.
But we are going out of track here. The number is not relevant to you as a consumer. You can query the provider with the context method 'getContentResilver().query(content://org.abcd.providers.contentprovider/bookmarks, /*other args */)'. See the documentation for more infos.
But you can only talk to the provider if its exported (nothing you can do about it) or it requires permissions that your application has. This includes no permissions at all.
I need to know the canonical names of a few Default Android applications like Email, Contacts & others. I want to be able to start them using their canonical names.
Like
Intent i = new Intent("com.pacakge.canonicalname");
So any ideas where i could get a list of the canonical package names of default Android apps?
thanks
There's a method in the PackageManager class called currentToCanonicalPackageNames(String[] names), which I suspect could be used to do what you're asking. So something like:
String[] names = {"Email","Contacts"};
try{
String[] canonicalNames = context.getPackageManager().currentToCanonicalPackageNames(names);
//do whatever you want with canonicalNames, e.g. launch the email app,
Intent email = context.getPackageManager().getLaunchIntentForPackage(canonicalNames[0]);
context.startActivity(email);
}catch(NameNotFoundException e){
Log.d("MY ACTIVITY NAME", "Package name(s) not found.");
}
I'm looking into doing this sort of thing myself, but haven't tried this code, so use with caution.
EDIT:
So tried it this evening, the solution may not be what you're looking for. Assuming you're starting with only the display names of these apps (technically referred to as application labels), you may have to actually go through all of the apps installed on the device looking for that application label. I just posted my solution to my blog, so take a look.