Class ReportFileProvider
Provides the report's file to another app through the share sheet, as a content address the receiving app is granted to read.
[ContentProvider(new string[] { "${applicationId}.reportprovider" }, Exported = false, GrantUriPermissions = true)]
public sealed class ReportFileProvider : ContentProvider, IComponentCallbacks2, IComponentCallbacks, IJavaObject, IJavaPeerable, IDisposable
- Inheritance
-
ReportFileProvider
- Implements
- Inherited Members
Remarks
The report is copied into the app's cache; the authority is <applicationId>.reportprovider, so several
VpnHood apps can live on one device. It takes no change: inserting, updating and deleting do nothing.
Methods
Delete(Uri, string?, string[]?)
Implement this to handle requests to delete one or more rows.
public override int Delete(Uri uri, string? selection, string[]? selectionArgs)
Parameters
uriUriThe full URI to query, including a row ID (if a specific record is requested).
selectionstringAn optional restriction to apply to rows when deleting.
selectionArgsstring[]This value may be null .
Returns
- int
The number of rows affected.
Remarks
Implement this to handle requests to delete one or more rows. The
implementation should apply the selection clause when performing
deletion, allowing the operation to affect multiple rows in a directory.
As a courtesy, call
ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver)
notifyChange() after deleting. This method can be called from multiple
threads, as described in Processes
and Threads.
The implementation is responsible for parsing out a row ID at the end of
the URI, if a specific row is being deleted. That is, the client would
pass in content://contacts/people/22 and the implementation
is responsible for parsing the record number (22) when creating a SQL
statement.
Exceptions
GetType(Uri)
Implement this to handle requests for the MIME type of the data at the given URI.
public override string GetType(Uri uri)
Parameters
uriUrithe URI to query.
Returns
- string
a MIME type string, or
nullif there is no type.
Remarks
Implement this to handle requests for the MIME type of the data at the
given URI. The returned MIME type should start with
vnd.android.cursor.item for a single record,
or vnd.android.cursor.dir/ for multiple items.
This method can be called from multiple threads, as described in
Processes
and Threads.
Note that by default there are no permissions needed for an application to access this information; if your content provider requires read and/or write permissions, or is not exported, all applications can still call this method regardless of their access permissions.
If your mime type reveals details that should be protected,
then you should protect this method by implementing #getTypeAnonymous.
Implementing #getTypeAnonymous ensures your #getType can be
only accessed by caller's having associated readPermission for the URI.
Insert(Uri, ContentValues?)
Implement this to handle requests to insert a new row.
public override Uri? Insert(Uri uri, ContentValues? values)
Parameters
uriUriThe content:// URI of the insertion request.
valuesContentValuesA set of column_name/value pairs to add to the database.
Returns
- Uri
The URI for the newly inserted item.
Remarks
Implement this to handle requests to insert a new row. As a courtesy,
call
ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver)
notifyChange() after inserting. This method can be called from multiple
threads, as described in Processes
and Threads.
OnCreate()
Implement this to initialize your content provider on startup.
public override bool OnCreate()
Returns
- bool
true if the provider was successfully loaded, false otherwise
Remarks
Implement this to initialize your content provider on startup. This method is called for all registered content providers on the application main thread at application launch time. It must not perform lengthy operations, or application startup will be delayed.
You should defer nontrivial initialization (such as opening,
upgrading, and scanning databases) until the content provider is used
(via #query, #insert, etc). Deferred initialization
keeps application startup fast, avoids unnecessary work if the provider
turns out not to be needed, and stops database errors (such as a full
disk) from halting application launch.
If you use SQLite, android.database.sqlite.SQLiteOpenHelper
is a helpful utility class that makes it easy to manage databases,
and will automatically defer opening until first use. If you do use
SQLiteOpenHelper, make sure to avoid calling
android.database.sqlite.SQLiteOpenHelper#getReadableDatabase or
android.database.sqlite.SQLiteOpenHelper#getWritableDatabase
from this method. (Instead, override
android.database.sqlite.SQLiteOpenHelper#onOpen to initialize the
database when it is first opened.)
OpenFile(Uri, string)
Override this to handle requests to open a file blob.
public override ParcelFileDescriptor? OpenFile(Uri uri, string mode)
Parameters
uriUriThe URI whose file is to be opened.
modestringThe string representation of the file mode. Can be "r", "w", "wt", "wa", "rw" or "rwt". Please note the exact implementation of these may differ for each Provider implementation - for example, "w" may or may not truncate.
Returns
- ParcelFileDescriptor
Returns a new ParcelFileDescriptor which you can use to access the file.
Remarks
Override this to handle requests to open a file blob.
The default implementation always throws FileNotFoundException.
This method can be called from multiple threads, as described in
Processes
and Threads.
This method returns a ParcelFileDescriptor, which is returned directly to the caller. This way large data (such as images and documents) can be returned without copying the content.
The returned ParcelFileDescriptor is owned by the caller, so it is their responsibility to close it when done. That is, the implementation of this method should create a new ParcelFileDescriptor for each call.
If opened with the exclusive "r" or "w" modes, the returned ParcelFileDescriptor can be a pipe or socket pair to enable streaming of data. Opening with the "rw" or "rwt" modes implies a file on disk that supports seeking.
If you need to detect when the returned ParcelFileDescriptor has been
closed, or if the remote process has crashed or encountered some other
error, you can use ParcelFileDescriptor#open(File, int,
android.os.Handler, android.os.ParcelFileDescriptor.OnCloseListener),
ParcelFileDescriptor#createReliablePipe(), or
ParcelFileDescriptor#createReliableSocketPair().
If you need to return a large file that isn't backed by a real file on
disk, such as a file on a network share or cloud storage service,
consider using
StorageManager#openProxyFileDescriptor(int, android.os.ProxyFileDescriptorCallback, android.os.Handler)
which will let you to stream the content on-demand.
For use in Intents, you will want to implement #getType
to return the appropriate MIME type for the data returned here with
the same URI. This will allow intent resolution to automatically determine the data MIME
type and select the appropriate matching targets as part of its operation.
For better interoperability with other applications, it is recommended
that for any URIs that can be opened, you also support queries on them
containing at least the columns specified by android.provider.OpenableColumns.
You may also want to support other common columns if you have additional meta-data
to supply, such as android.provider.MediaStore.MediaColumns#DATE_ADDED
in android.provider.MediaStore.MediaColumns.
Exceptions
- FileNotFoundException
Throws FileNotFoundException if there is no file associated with the given URI or the mode is invalid.
- SecurityException
Throws SecurityException if the caller does not have permission to access the file.
- FileNotFoundException
The address names no report in the cache, or one outside it.
Query(Uri, string[]?, string?, string[]?, string?)
Implement this to handle query requests from clients.
public override ICursor? Query(Uri uri, string[]? projection, string? selection, string[]? selectionArgs, string? sortOrder)
Parameters
uriUriThe URI to query. This will be the full URI sent by the client; if the client is requesting a specific record, the URI will end in a record number that the implementation should parse and add to a WHERE or HAVING clause, specifying that _id value.
projectionstring[]The list of columns to put into the cursor. If
nullall columns are included.selectionstringA selection criteria to apply when filtering rows. If
nullthen all rows are included.selectionArgsstring[]You may include ?s in selection, which will be replaced by the values from selectionArgs, in order that they appear in the selection. The values will be bound as Strings.
sortOrderstringHow the rows in the cursor should be sorted. If
nullthen the provider is free to define the sort order.
Returns
- ICursor
a Cursor or
null.
Remarks
Implement this to handle query requests from clients.
Apps targeting android.os.Build.VERSION_CODES#O or higher should override
#query(Uri, String[], Bundle, CancellationSignal) and provide a stub
implementation of this method.
This method can be called from multiple threads, as described in Processes and Threads.
Example client call:
<pre><code class="lang-csharp">// Request a specific record.
Cursor managedCursor = managedQuery(
ContentUris.withAppendedId(Contacts.People.CONTENT_URI, 2),
projection, // Which columns to return.
null, // WHERE clause.
null, // WHERE clause value substitution
People.NAME + " ASC"); // Sort order.</code></pre>
<p>Example implementation:</p>
<p></p>
<pre><code class="lang-csharp">// SQLiteQueryBuilder is a helper class that creates the
// proper SQL syntax for us.
SQLiteQueryBuilder qBuilder = new SQLiteQueryBuilder();
// Guard against SQL injection attacks
qBuilder.setStrict(true);
qBuilder.setProjectionMap(MAP_OF_QUERYABLE_COLUMNS);
qBuilder.setStrictColumns(true);
qBuilder.setStrictGrammar(true);
// Set the table we're querying.
qBuilder.setTables(DATABASE_TABLE_NAME);
// If the query ends in a specific record number, we're
// being asked for a specific record, so set the
// WHERE clause in our query.
if((URI_MATCHER.match(uri)) == SPECIFIC_MESSAGE){
qBuilder.appendWhere("_id=" + uri.getPathLeafId());
}
// Make the query.
Cursor c = qBuilder.query(mDb,
projection,
selection,
selectionArgs,
groupBy,
having,
sortOrder);
c.setNotificationUri(getContext().getContentResolver(), uri);
return c;</code></pre>
<p>
<format type="text/html">
<a href="https://developer.android.com/reference/android/content/ContentProvider#query(android.net.Uri,%20java.lang.String[],%20java.lang.String,%20java.lang.String[],%20java.lang.String)" title="Reference documentation">Java documentation for
<pre><code class="lang-csharp">android.content.ContentProvider.query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String)</code></pre>
.</a>
</format>
</p>
<p>
Portions of this page are modifications based on work created and shared by the
<format type="text/html"><a href="https://developers.google.com/terms/site-policies" title="Android Open Source Project">Android Open Source Project</a></format>
and used according to terms described in the
<format type="text/html"><a href="https://creativecommons.org/licenses/by/2.5/" title="Creative Commons 2.5 Attribution License">Creative Commons 2.5 Attribution License.</a></format></p>
SaveAndGetUri(Context, string, byte[])
Copies a report into the app's cache, and gives the content address the share sheet can grant.
public static Uri SaveAndGetUri(Context context, string fileName, byte[] content)
Parameters
contextContextThe app's context.
fileNamestringThe report's file name.
contentbyte[]The report.
Returns
- Uri
The content address.
Exceptions
- Exception
Android built no content address.
Update(Uri, ContentValues?, string?, string[]?)
Implement this to handle requests to update one or more rows.
public override int Update(Uri uri, ContentValues? values, string? selection, string[]? selectionArgs)
Parameters
uriUriThe URI to query. This can potentially have a record ID if this is an update request for a specific record.
valuesContentValuesA set of column_name/value pairs to update in the database.
selectionstringAn optional filter to match rows to update.
selectionArgsstring[]This value may be null .
Returns
- int
the number of rows affected.
Remarks
Implement this to handle requests to update one or more rows. The
implementation should update all rows matching the selection to set the
columns according to the provided values map. As a courtesy, call
ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver)
notifyChange() after updating. This method can be called from multiple
threads, as described in Processes
and Threads.