Beta Playground ContentProvider (simple database for all your apps (call it a devicekvs))

DonManfred

Expert
Licensed User
Longtime User
i played around with creating a ContentProvider ....

I came out with a small and simple Library which provides a simple ContenProvider.

The small library b4aContentProvider is basically only returning some Constants which you need to use when using contentResolver to get Data from the DatacontentProvider.
It also contains the ContentProvider itself for sure (more or less hidden).
The Database schema behind the ContentProvider is based on the b4xcloudkvs Database. I´m just playing around and i thougth it may be a good idea. :D

This all may be something for you if you have multiple apps on one Device for which you want to store Data accessible by all your apps.
The plus: No additional permissions are needed. No need to share a file or something, no need for Runtimepermissions.

One App, i name it the ContentProvider Host, must implement the ContentProvider. All your other apps only need to use the contentResolver Library.

To make your app the Host add this to your Manifest
B4X:
AddApplicationText(
<provider
    android:name="de.donmanfred.dataprovider"
    android:authorities="de.donmanfred.dataprovider"
    android:enabled="true"
    android:exported="true" />)

You´ll find two Example Apps attached.


Code to write a Dataset to the Provider:

B4X:
Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.
    Private prov As DataProvider
    Private cr As ContentResolver
End Sub

B4X:
    Dim m As Map = CreateMap("January": 1, "February": 2)
 
    Dim jgen As JSONGenerator
    jgen.Initialize(m)
    Dim val As ContentValues
    val.Initialize
    val.PutString(prov.KEY,GUID)
    val.PutString(prov.USER,Application.PackageName)
    val.PutLong(prov.TIME,DateTime.Now)
    val.PutInteger(prov.ID,815)
    val.PutBytes(prov.VALUE,serializator.ConvertObjectToBytes(m)) ' I am usind b4xserializator so the content is limited to the understood content...
    Dim resUri As Uri = cr.Insert(prov.CONTENT_URI,val)
    Dim contentID As Int = resUri.ParseId
    Log($"contentID of created content: ${contentID}"$)


Code to read the last Data from the Provider:
Here i am limiting the results to 1 Item. Sorted by time value DESCending. And the id must be 815 and the USER field must be "b4a.example"

B4X:
    Dim projection() As String = Array As String(prov.ID,prov.KEY,prov.VALUE,prov.TIME,prov.USER)
    cr.QueryAsync(prov.CONTENT_URI,projection, $"${prov.ID}=815 AND ${prov.USER}="b4a.example" "$,Null,prov.TIME&" DESC LIMIT 1")
    wait for CR_QueryCompleted(Success As Boolean, Crsr As Cursor)
    Log($"QueryCompleted(${Success})"$)
    If Crsr.IsInitialized Then
        If Crsr.RowCount > 0 Then
            Log($"CR --------------------------------------"$)
            Dim Cursor As Cursor
            Cursor = Crsr
            For i = 0 To Cursor.RowCount - 1
                Cursor.Position = i
                'calcon.ACCOUNT_TYPE,calcon.OWNER_ACCOUNT)
                Log($"$time{Cursor.GetLong(prov.TIME)}: ${Cursor.GetInt(prov.ID)}: ${Cursor.GetString(prov.KEY)}:${Cursor.GetString(prov.USER)}: ${serializator.ConvertBytesToObject(Cursor.GetBlob(prov.VALUE))} "$ ) ' You can use the constants you used for the projection. But remember: only the ones you defined in the projection are available in the Result.
            Next
            Cursor.Close
            Log($"CR --------------------------------------"$)
        Else
            ' No rows
        End If
    End If

Hope to give some inspiration for you to use it.

As the VALUE is saved using b4xserializator your are Limited to the follwing types:

The following types are supported as values:
Lists, Maps, Strings, primitives (numbers), user defined types and arrays (only arrays of bytes and arrays of objects are supported).
Custom types should be declared in the main module.
Including combinations of these types (a list that holds maps for example).

Though i did not tried to use the same Customtype in two apps and try to write/access them later... Not sure it it works because the two Types are defined in two different Apps... I´ll investigate ;-)
 

Attachments

  • b4aContentProviderV1.0.zip
    5.1 KB · Views: 360
  • ClientEx.zip
    8.7 KB · Views: 372
  • ContentProviderEx.zip
    9 KB · Views: 368
Last edited:

Peter Simpson

Expert
Licensed User
Longtime User
Hiya Manfred,
This looks great. I have to create an example of an issue that I'm having for @klaus, once I have done that I will be testing your Playground ContentProvider.

Your dedication for this forum really is excellent, plus now and again @DonManfred you put a smile on my face.

Anyway yo yo yo keep rapping, oops wrong type of wrapping ;)

Thank you Don
 
Upvote 0

rboeck

Well-Known Member
Licensed User
Longtime User
Hi,

i tried to test your contentprovider and was not able to find a solution for this problem:

When i open the sample file DataContentProviderEx in line 45/main:
prov.USER <- here i get: Unknown Member: user

I dont find any definition of user as member of provider; i am using B4A 9.0. Something on my side seems out of order?
 
Upvote 0

rboeck

Well-Known Member
Licensed User
Longtime User
I am sure, that the problem is on my computer, but at which position are the members of contentprovider defined? Some part of my software is outdated, but which one?
prov.png
 
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
To give an explanation. The members like ID, USER, TIME, VALUE are just placeholders for the Strings
"ID", "USER", "TIME" and "VALUE"

You can for sure define your own fields with your own names. The above are only to demonstrate the principle and to give some help.
I could have used constants in B4A too instead.
 
Upvote 0
Top