If I create a cursor like this:
using (var musicCursor = Context.ContentResolver.Query(MediaStore.Audio.Media.ExternalContentUri, null, null, null, null))
// Do something
Then repeat it a couple if times, I get errors like this on logcat:
02-02 23:05:39.770: E/CursorLeakDetecter(28387): android.database.sqlite.DatabaseObjectNotClosedException: Application did not close the cursor or database object that was opened here
02-02 23:05:39.770: E/CursorLeakDetecter(28387): at android.content.ContentResolver.query(ContentResolver.java:399)
02-02 23:05:39.770: E/CursorLeakDetecter(28387): at android.content.ContentResolver.query(ContentResolver.java:316)
02-02 23:05:39.770: E/CursorLeakDetecter(28387): at dalvik.system.NativeStart.run(Native Method)
Adding musicCursor.Close(); to the end of the using makes these errors go away.
The cursor should be automatically closed on Dispose. Please fix it.
Xamarin 3.9.274.0 (74260cb)
Visual Studio extension to enable development for Xamarin.iOS and Xamarin.Android.
Xamarin.Android 188.8.131.52 (49a04b966feb40dfdba49d57ba16249b66d606a6)
Visual Studio plugin to enable development for Xamarin.Android.
jonp: did we claim that .NET IDisposable() automatically calls Java close() on public document? I don't think it's automatically possible to detect such ones when generating binding code.
I certainly don't claiming that IDisposable.Dispose() automatically calls close().
It could be done -- check to see if the type implements java.lang.AutoCloseable, and if it does have Dispose(bool) call Close() -- but it hasn't been done yet.
What does dispose do if it doesn't call close?
Dispose() disposes internal Java object handle.
Even if the corresponding Java API implemented AutoCloseable, we shouldn't change the semantics of Dispose() in prior to any API breaking version. It will cause existing user code calling Java close() method twice.
I believe the documentation needs some updating/clarification.
Is the correct way to properly utilize a cursor this way?
var cursor = some cursor;
Beacuse the documentation on Cursor says that you have to Dispose() it: https://developer.xamarin.com/api/member/System.Windows.Forms.Cursor.Dispose()/.
And here is some documentation that says you have to Close() it: https://developer.xamarin.com/guides/android/platform_features/intro_to_content_providers/part_2_-_using_the_contacts_contentprovier/.
If possible, can we please get a reproduction project that demonstrates this behavior? This will help us confirm this issue and ultimately issue a fix if we determine this to be an issue with the ICursor implementation.
Seeing that ICursor is the following:
public interface ICursor : ICloseable, IJavaObject, IDisposable
It seems that one would have to call the respective .Close() prior to .Dispose().
Thus marking NEEDINFO as I tried to reproduce this in a quick sample app, and it seems to be working. However I believe a proper reproduction might be able to shed more light to this issue.
Because we have not received a reply to our request for more information we are closing this issue. If you are still encountering this issue, please reopen the ticket with the requested information. Thanks!