Content provider
- It is mainly used to realize data sharing between different applications
- You can choose which part of the data to share only
- Use existing content providers to read and manipulate data in programs
- Or create your own content provider to provide external access to our program’s data
Runtime permissions
mechanism
- Common Rights The system automatically grants permissions
- Dangerous permissions (permissions group name | permissions)
- CALENDAR: READ_CALENDAR / WRITE_CALENDAR
- CAMERA: CAMERA
- CONTACTS: READ_CONTACTS / WRITE_CONTACTS / GET_CONTACTS
- LOCATION: ACCESS_FINE_LOCATION / ACCESS_COARSE_LOCATION
- MICROPHONE: RECORD_AUDIO
- PHONE: READ_PHONE_STATE / CALL_PHONE / READ_CALL_LOG / WRITE_CALL_LOG / ADD_VOICEMAIL / USE_SIP / PROCESS_OUTGOING_CALLS
- SENSORS: BODY_SENSORS
- SMS: SEND_SMS / RECEIVE_SMS / READ_SMS / RECEIVE_WAP_PUSH / REACEIVE_MMS
- STORAGE: READ_EXTERNAL_STORAGE / WRITE_EXTERNAL_STORAGE
- After a dangerous permission is granted, all other permissions in the corresponding permission group are also granted
Request permission at runtime
- Declare in the androidmanifest.xml file
<uses-permission android:name="android.permission.CALL_PHONE" />
-
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button makeCall = findViewById(R.id.make_call); makeCall.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (ContextCompat.checkSelfPermission((MainActivity.this, Manifest.permission.CALL_PHONE) ! = PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(MainActivity.this, new String[] { Manifest.permission.CALL_PHONE }, 1); } else { call(); }}}); } private void call() { try { Intent intent = new Intent(Intent.ACTION_CALL); intent.setData(Uri.parse("tel:10086")); startActivity(intent); } catch (SecurityException e) { e.printStackTrace(); } } @Override public void onRequestPermissionResult(int requestCode, String[] permissions, int[] grantResults) { switch (requestCode) { case 1: if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { call(); } else { Toast.makeText(this, "You denied the permission", Toast.LENGTH_SHORT).show(); } break; default: } }Copy the code
ContextCompat.checkSelfPermission
: Check whether the user is authorized
The first argument is Context
The second parameter is the specific permission name
With the return values andPackageManager.PERMISSION_GRANTED
Compare, equal is authorized, unequal is not authorized- If not authorized, it is called
ActivityCompat.requestPermissions()
Apply for authorization from a user
The first parameter requires an instance of Acitivity
The second argument is an array of strings containing the names of the permissions to apply for
The third parameter is the request code, as long as it is unique - Call out
ActivityCompat.requestPermissions()
A dialog box is displayed asking you to apply for permission
After the user chooses to agree or reject, callback toonRequestPermissionResult
In the method
The result of authorization is encapsulated ingrantResults
In the parameters - Make a phone call
- Build an implicit Intent action named intent.action_call, which is the built-in action for making a call. The data section specifies the protocol tel and the number 10086
- ACTION_DIAL Indicates that the dialing interface is opened. You do not need to declare the permission for the Intent
Access data in other programs
Basic usage of ContentResolver
- Through the Context
getContentResolver()
Method to get an instance of the class - A series of methods are provided for CRUD operations on data
insert()
update()
delete()
query()
- Content URI: Establishes a unique identifier for data in a content provider
authority
: Distinguish between different applications, generally adopted<package_name>.provider
Is named in a waypath
: Distinguishes different tables in the same application, usually added toauthority
behind- Prefixes the string with a protocol declaration
- E.g.
content://com.example.app.provider/table1
- Resolve to
Uri
object
Uri uri = Uri.parse(content://com.example.app.provider/table1);
- The query
query()
:Cursor cursor = getContentResolver().query( uri, projection, selection, selectionArgs, sortOrder); Copy the code
uri
: Specifies a table under an application to be queriedprojection
: Specifies the column name to be queriedselection
: Specifies where constraintsselectionArgs
: provides concrete values for placeholders in wheresortOrder
: Specifies the sorting method of the query results
if (cursor ! = null) { while (cursor.moveToNext()) { String column1 = cursor.getString(cursor.getColumnIndex("column1")); int column2 = cusor.getInt(cursor.getColumnIndex("column2")); } cursor.close() }Copy the code
- The move cursor traverses all rows and retrieves the data for the corresponding column in each row
- add
insert()
ContentValue values = new ContentValues(); values.put("column1", "text"); values.put("column2", 1); getContentResolver().insert(uri, values); Copy the code
- Modify the
update()
ContentValues values = new ContentValues(); values.put("column1", ""); getContentResolver().update(uri, values, "column1 = ? and column2 = ?" , new String[] {"text", "1"});Copy the code
- delete
delete()
getContentResolver().delete(uri, "column2 = ?", new String[] { "1" }); Copy the code
Create your own content provider
Create a step
- Create a new class inheritance
ContentProvider
Override six abstract methodsboolean onCreate()
- Called when the content provider is initialized, usually to complete operations such as creating and upgrading the database
- It is initialized only if a ContentResolver attempts to access data in the program
Cursor query(Uri uri, String[] projection, String selection, String[] SelectionArgs, String sortOrder)
- The results of the query are stored in the Cursor object and returned
Uri insert(Uri uri, ContentValues values)
- Returns a URI that represents the new record
int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)
- Returns the number of affected rows
int delete(Uri uri, String selection, String[] selectionArgs)
- Returns the number of deleted rows
String getType(Uri uri)
- Return the corresponding
MIME
type MIME
The string consists of three parts- Have to be
vnd
At the beginning - If the content URI ends in a path, it is followed
android.cursor.dir/
If the content URI ends in id, it is followedandroid.cursor.item/
- The last plug in
vnd.<authority>.<path>
- E.g.
vnd.android.cursor.dir/vnd.com.example.app.provide.table1
- Have to be
- Return the corresponding
The content URI
- Establishes a unique identifier for the data in the content provider
authority
: Distinguish between different applications, generally adopted<package_name>.provider
Is named in a waypath
: Distinguishes different tables in the same application, usually added toauthority
behind- Prefixes the string with a protocol declaration
- You can add an ID after the content URI
content://com.example.app.provider/table1/1
- Select * from table1 where com.example.app = com.example.app
- Wildcard matches can be used
*
Matches any character of any length#
Matches a number of any length- E.g.
content://com.example.app.provider/*
Matches the contents of any table
content://com.example.app.provider/table1/#
Matches any row in table1
UriMatcher
class- provide
addURI()
methods
Accepts 3 parameters, which can be passed in separatelyauthority
,path
And a child can take code - call
match()
You can pass in a Uri object and return some custom code that matches the Uri object
Use this code to determine which table data needs to be accessed
- provide
- All CRUD operations must match the URI format of the corresponding content to prevent privacy data leakage
public class MyProvider extends ContentProvider { public static final int TABLE1_DIR = 0; public static final int TABLE1_ITEM = 1; public static final int TABLE2_DIR = 2; public static final int TABLE2_ITEM = 3; private static UriMatcher uriMatcher; static { uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); uriMatcher.addURI("com.example.app.provider", "table1", TABLE1_DIR); uriMatcher.addURI("com.example.app.provider", "table1/#", TABLE1_ITEM); uriMatcher.addURI("com.example.app.provider", "table2", TABLE1_DIR); uriMatcher.addURI("com.example.app.provider", "table2/#", TABLE2_ITEM); }... public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {switch (urimatcher.match (uri)) {case TABLE1_DIR: // Query all data breaks in table1; Case TABLE1_ITEM: // Select break from table2; Case TABLE2_DIR: // query all data breaks in table2; Case TABLE2_ITEM: // Select break from table2; default: break; }... } @Override public String getType(Uri uri) { switch (uriMathcer.match(uri)) { case TABLE1_DIR: return "vnd.android.cursor.dir/vnd.com.example.app.provide.table1"; case TABLE1_ITEM: return "vnd.android.cursor.item/vnd.com.example.app.provide.table1"; case TABLE2_DIR: return "vnd.android.cursor.dir/vnd.com.example.app.provide.table2"; case TABLE2_ITEM: return "vnd.android.cursor.item/vnd.com.example.app.provide.table2"; default: break; } return null; }... }Copy the code