Table of Contents

Class ReportFileProvider

Namespace
VpnHood.AppLib.App.Android
Assembly
VpnHood.AppLib.App.Android.dll

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

uri Uri

The full URI to query, including a row ID (if a specific record is requested).

selection string

An optional restriction to apply to rows when deleting.

selectionArgs string[]

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.

Java documentation for

        <pre><code class="lang-csharp">android.content.ContentProvider.delete(android.net.Uri, 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>

Exceptions

SQLException

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

uri Uri

the URI to query.

Returns

string

a MIME type string, or null if 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.

Java documentation for

        <pre><code class="lang-csharp">android.content.ContentProvider.getType(android.net.Uri)</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>

Insert(Uri, ContentValues?)

Implement this to handle requests to insert a new row.

public override Uri? Insert(Uri uri, ContentValues? values)

Parameters

uri Uri

The content:// URI of the insertion request.

values ContentValues

A set of column_name/value pairs to add to the database.

Returns

Uri

The URI for the newly inserted item.

Remarks

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.)

Java documentation for

        <pre><code class="lang-csharp">android.content.ContentProvider.onCreate()</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>

OpenFile(Uri, string)

Override this to handle requests to open a file blob.

public override ParcelFileDescriptor? OpenFile(Uri uri, string mode)

Parameters

uri Uri

The URI whose file is to be opened.

mode string

The 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.

Java documentation for

        <pre><code class="lang-csharp">android.content.ContentProvider.openFile(android.net.Uri, 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>

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

uri Uri

The 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.

projection string[]

The list of columns to put into the cursor. If null all columns are included.

selection string

A selection criteria to apply when filtering rows. If null then all rows are included.

selectionArgs string[]

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.

sortOrder string

How the rows in the cursor should be sorted. If null then 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

context Context

The app's context.

fileName string

The report's file name.

content byte[]

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

uri Uri

The URI to query. This can potentially have a record ID if this is an update request for a specific record.

values ContentValues

A set of column_name/value pairs to update in the database.

selection string

An optional filter to match rows to update.

selectionArgs string[]

This value may be null .

Returns

int

the number of rows affected.

Remarks