1. The background

Recently, the company has a new business function, which needs to obtain the playback history of all other apps in the main APP of our system. Upon receiving this requirement, there are many ways to obtain the data of third-party apps across processes, including IPC, broadcast, and ContentPrivider(based on AIDL). But getting the data is all the playback records, so the first choice is ContentPrivider.

We generally use ContentPrivider to read the database information of a third party and return a Cursor. Because the data format of each business line is different, it is necessary for each business line to return the same data field for unified processing. At first, we considered packaging an SDK to other businesses. Storing playback records in our unified encapsulated database table has two drawbacks:

  1. The downside is that third party businesses need to keep a copy of their own database information, and also store data separately in our SDK
  2. Historical data existing before application is imported into the new database when it is first used
  3. Data can only be read from the database. The application may need to read data in the background

2. Implementation scheme

Finally, you have to decide how to use ContentPrivider. See the article ContentPrivider for more information on ContentPrivide

In order to solve the above two drawbacks, I came across the **MatrixCursor ** class, through this class can construct a virtual Cursor, even without a database can share data to third party applications through ContentPrivider. Define a ContentPrivider as follows:

Public class MyProvider extends ContentProvider {public class MyProvider extends ContentProvider {public class MyProvider extends ContentProvider {public class MyProvider extends ContentProvider public boolean onCreate() { return true; } @override public Uri insert(Uri Uri, ContentValues values) {// Match URI_CODE with Uri, To match the corresponding table name in the ContentProvider // return URI at the bottom; Public Cursor query(Uri Uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { String[] tableCursor = new String[]{"name", "job", "salary"}; MatrixCursor matrixCursor = new MatrixCursor(tableCursor); Matrixcursor.addrow (new Object[]{" matrixcursor.addrow ", "11111"}); Matrixcursor.addrow (new Object[]{" matrixcursor.addrow ", "2222"}); Matrixcursor.addrow (new Object[]{" matrixcursor.addrow ", "3333"}); return matrixCursor; } /** * Override public int update(Uri Uri, ContentValues values, String selection, String[] selectionArgs) {return 0; } @override public int delete(Uri Uri, String selection, String[] selectionArgs) {return 0; } @override public String getType(Uri Uri) {return null; }}Copy the code

Let’s focus on the query method:

/** * public Cursor query(Uri Uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { String[] tableCursor = new String[]{"name", "job", "salary"}; MatrixCursor matrixCursor = new MatrixCursor(tableCursor); Matrixcursor.addrow (new Object[]{" matrixcursor.addrow ", "11111"}); Matrixcursor.addrow (new Object[]{" matrixcursor.addrow ", "2222"}); Matrixcursor.addrow (new Object[]{" matrixcursor.addrow ", "3333"}); return matrixCursor; }Copy the code

First, we instantiate a MatrixCursor, pass in the table fields, and then return the data once added by the addRow method. Then define MyPrivider in the androidmanifest.xml file

  <provider
            android:name="com.data.dataprovider.MyProvider"
            android:authorities="${applicationId}.myprovider"
            android:exported="true" />
Copy the code

When each business APK integrates the MyProvider, our main APP can directly fetch the data and call the ContentPrivider data in the main APP as normal:

/ / set the URI URI uri_user = URI. Parse (" content: / / com. Data. The dataprovider. Myprovider "); ContentResolver resolver = getContentResolver(); // You can pass in arguments, Cursor = resolver.query(uri_user, new String[]{"page", "size","data"}, "data", new String[]{"1","10 0","123"}, null); while (cursor.moveToNext()) { Log.d("MatrixCursor", "query:" +" name:"+ cursor.getString(0) + " job:" + cursor.getString(1) + " salary:" + cursor.getString(2)); } cursor.close(); // Print result D/MatrixCursor: query: name: MatrixCursor job: old driver salary:11111 D/MatrixCursor: query: Name: Li Si Job: Maintenance person Salary :2222 D/MatrixCursor: Query: name: Wang Wu job: developer Salary :3333Copy the code

In the future, no matter the data of each business is obtained from the local database or from the background, it can be returned through unified fields, and the data of the local database of the current application can be obtained. The main APP does not need to consider the data problem.

Downside: We know that getting data from ContentPrivider must start the application process, which can cause performance problems