I am newbie to Android development and I am confused between the difference of URI and Uri?
Please mention the main differences.
java.net.URI is mutable
android.net.Uri is immutable
Immutable URI reference. A URI reference includes a URI and a fragment, the component of the URI following a '#'. Builds and parses URI references which conform to RFC 2396.
In the interest of performance, this class performs little to no validation. Behavior is undefined for invalid input. This class is very forgiving--in the face of invalid input, it will return garbage rather than throw an exception unless otherwise specified.
More infos here
Related
I'm struggling with storing a realm db on the sd card. The point is that I have to use DocumentFile instead of simple File object to have write access. Another words:
Uri uri = getUriInstanceToSaveDB(); // my inner method
new File(uri.getPath()).canWrite() == false
DocumentFile.fromTreeUri(getActivity(), uri).canWrite() == true
Therefore I can't just store data using RealmConfiguration.Builder() (cause it uses File object as storing mechanism). Of course, I've also tried to use simple String there instead of File object - no result.
Real doesn't support DocumentFile at this point in time, so I'm afraid you are currently out of luck unless you can find a way to map a DocumentFile to a local File reference.
Also one of the problems with DocumentFile is that it might reference a file that doesn't exist locally, which would prevent Realm from using it. So it is unclear if Realm could ever support this.
Android API has DocumentFile class. This class has canWrite() method.
Suppose I called this method and it returned true. Also suppose this object was representing "raw" file.
Now how can I do what it said I can?
Namely, how to write "Hello world" text into that file?
Thanks.
Namely, how to write "Hello world" text into that file?
It is not necessarily a file.
To write to the document identified by that DocumentFile, call getUri() on that DocumentFile to get the Uri to the document. Pass that to openOutputStream() on a ContentResolver. Then, write to the stream, flush() the stream, and close() the stream. Basically, once you get the OutputStream, from there ordinary Java I/O takes over.
I am creating a content provider for an android application, but I am having a problem correctly matching the uri using UriMatacher.
For example, I add the uri's to match (snipped from the link)
sURIMatcher.addURI("content://com.example", "people", PEOPLE);
sURIMatcher.addURI("content://com.example", "people/#", PEOPLE_ID);
sURIMatcher.addURI("content://com.example", "people/#/phones", PEOPLE_PHONES);
And then attempt to access contacts/people/1/phones. The successful match ends up being with PEOPLE_ID instead of PEOPLE_PHONES.
The query is initially generated by this code.
Uri uri = Uri.parse("content://com.example/people/#/phones");
ContentUris.appendId(uri.buildUpon(), 1).build();
With some logging statements thrown in, I see that the following:
The uri passed to the query gives this:
content://com.example/people/1#/phones
but uri.getPath() gives this:
/people/1
The third path part of the uri is clearly dropped, which explains why it was matching the wrong uri.
The example from the Android developer website seems to indicate that there shouldn't be a problem with this. Am I creating the uri incorrectly? Is it just a bug? Is this intended functionality (and therefore the example from android developers is a bad one)?
Uri.parse() is ignorant of the UriMatcher's wildcards; here, the # is the fragment identifier of a URI, so when you parse content://com.example/people/#/phones, it becomes content://com.example/people + fragment /phones. The id is correctly appended to the end of the URI, and then the fragment is carried over. In this case, you can't rely on ContentUris, but rather need to build the Uri the long way:
path = new Uri.Builder()
.scheme( ContentResolver.SCHEME_CONTENT )
.authority( DataProvider.AUTHORITY )
.appendPath( "people" )
.appendPath( "1" )
.appendPath( "phones" ) ).build();
How can I construct a URI to table MediaStore.Files.FileColumns ?
I try like this:
Uri uri=Uri.parse(MediaStore.Files.FileColumns);
But in Eclipse "MediaStore.Files.FileColumns" is underlined. I guess, I do this wrong. How to correctly construct a URI?
FileColumns is interface. You cannot reference interface. If you need explicit column, use
Uri uri=Uri.parse(MediaStore.Files.FileColumns.<COLUMN>);
for example:
Uri uri=Uri.parse(MediaStore.Files.FileColumns.MEDIA_TYPE);
MediaStore.Files.FileColumns is an Interface, the method Uri.parse() receives a string.
When I call an Android ContentProvider I get the following exception:
java.lang.RuntimeException: Unable to
start activity
ComponentInfo{de.harm.android.couchone/de.harm.android.couchone.CouchContactClient}:
java.lang.IllegalArgumentException:
Unknown URL
content://de.harm.android.couchone.provider/test2
These are the projects:
https://github.com/der-harm/CouchOneProvider
.../CouchOneContacts
Android uses the so-called ContentResolver to communicate with ContentProvider which in turn handles the persistence functionality - accessing the database.
The ContentProvider registers itself with a unique Uri. The ContentResolver calls the ContentProvider with this Uri and passes additional data, like a SQL query string and/or data to be saved.
In the CouchOneProvider/AndroidManifest.xml I have the following:
<provider android:authorities="de.harm.android.couchone.provider"
android:name=".Provider" />
The Provider uses
static {
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI(PROVIDER_NAME, DB_Name, URI_COLLECTION);
uriMatcher.addURI(PROVIDER_NAME, DB_Name + "/#", URI_ENTITY);
}
and
public static boolean isCollectionUri(Uri uri) {
return uriMatcher.match(uri) == URI_COLLECTION;
}
to process the CONTENT_URI used by the ContentResolver to call the ContentProvider:
Am I missing permissions in any of both AndroidManifest.xml?
Am I defining the authority in AndroidManifest.xml wrongly?
Is the CONTENT_URI wrong?
Update:
I have additional information:
Logcat says:
Failed to find provider info for
de.harm.android.couchone.provider
This should be the starting point. But so far I couldn't find any solution.
The fully qualified classname of the ContentProvider implementation is:
de.harm.android.couchone.Provider
In AndroidManifext.xml exactly this is specified as authority, except for the name being to lower case, but this should be fine.
The package name is defined previously in the xml file, so ".Provider" should be ok, too.
As to be seen in the exception, the client calls:
content://de.harm.android.couchone.provider/test2
Logcats answer is:
Failed to find provider info for de.harm.android.couchone.provider
I don't see what's missing, perhaps it's Eclipse or emulator problem?
I install the provider as "run project as Android application".
I have resolved this problem:
Both projects had the same package structure. I changed de.harm.android.couchone to de.harm.android.couchone.provider and de.harm.android.couchone.client.
I think this link is related to question topic. How to implement a custom content-provider.