Android容許一個程序訪問另外一個程序的數據,而且保證被訪問數據的安全性。主要是經過Content Provider來實現的。java
Android6.0以前,權限在app安裝的時候賦予,若是不一樣意就沒有辦法安裝,致使了不少店大欺客的行爲。6.0之後,Android的權限變成了須要的時候進行申請,也就是運行時申請。可是並非全部的權限都須要申請,只有一些涉及到用戶安全和隱私的權限纔去申請,這一類權限叫作危險權限。其餘的不須要運行時申請的權限叫作普通權限。android
權限組名安全 |
權限名app |
CALENDARide |
READ_CALENDARthis |
WRITE_CALENDARgoogle |
|
CAMERAurl |
CAMERAspa |
CONTACTScode |
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 |
|
RECEIVE_MMS |
|
STORAGE |
READ_EXTERNAL_STORAGE |
WRITE_EXTERNAL_STORAGE |
以上權限是以組的方式進行受權,就是說你受權了任意一個權限,那麼app將會得到一組權限。
具體的代碼以下:
public void call(View view){ if(ContextCompat.checkSelfPermission(RuntimePermissionActivity.this, Manifest.permission.CALL_PHONE)!= PackageManager.PERMISSION_GRANTED){//沒有受權 ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.CALL_PHONE},1); }else{//有受權 callPhone(); } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { switch (requestCode){ case 1:{ if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){ callPhone(); }else { Toast.makeText(this,"您拒絕了權限申請",Toast.LENGTH_SHORT).show(); } break; } } } private void callPhone(){ try { Intent intent = new Intent(Intent.ACTION_CALL); intent.setData(Uri.parse("tel:10086")); startActivity(intent); }catch (SecurityException e){ Log.e(TAG, "callPhone: "+e.getMessage()); } }
代碼的講解以下:
代碼中直接打電話,會涉及到用戶話費等隱私問題,因此須要獲得用戶的受權。會調用checkSelfPermission檢驗是否已經包含此權限,若是沒有會調用系統的權限確認窗口進行確認。以後在onRequestPermissionsResult方法中回調。
android中完整的權限表:https://developer.android.google.cn/reference/android/Manifest.permission
注意:普通的權限在使用的時候,是須要在AndroidManifest.xml文件中進行申明的。
咱們能夠調用Android系統的一些數據,例如用戶的聯繫人,通話記錄,等等內容。
URI用來表示須要得到哪一部分的數據,URI的格式爲:<協議>://<authority>/<path>,其中authority通常爲程序的包名。
一個標準的URI的表示方式爲:content://com.example.app/table1
固然在查詢數據的時候,主要用到的是URI的對象,因此以上String類型的參數,還須要經過
Uri uri = Uri.parse("content://com.example.app/table1")得到
使用getContentResolver()方法,得到ContentResolver對象
query( Uri uri,String[] projection, String selection,String[] selectionArgs, String sortOrder):Cursor
query()方法參數 |
對應Sql部分 |
uri |
from table_name |
projection |
select column1,column2 |
selection |
where column = ? |
selectionArgs |
where條件中佔位符對應的數據 |
sortOrder |
order by column1,column2 |
insert(Uri url,ContentValues values):Uri//返回值爲新建數據的uri
update( Uri uri,ContentValues values, String where,String[] selectionArgs):int //返回值爲被更新的行數
delete( Uri url, String where,String[] selectionArgs):int//返回值被刪除的行數
實現本身的ContentProvider直接extends ContentProvider,實現其中的onCreate(),query(),insert(),update(),delete(),getType()這幾個方法。其中onCreate()返回值表示Provider是否已經建立成功。最後在AndroidManifest.xml文件中配置一下。其中getType()方法返回值是一個MIME類型。
URI的格式爲:<協議>://<authority>/<path>
URL能夠分爲兩種:一種是表示全部的的數據,還有一種是表示一條數據。例如:content://base.example.com/table1 表示得到全部數據,而後content://base.example.com/table1/1表示得到一條數據。
*表示匹配任意長度的字符。#表示匹配任意長度的數字。
因此一個可以匹配任意表的URI能夠寫成:content://base.example.com/ *
可以匹配table1表中的一條數據的URI能夠寫成:content://base.example.com/table1/#
.必須以vnd開頭
.若是內容URI以路徑結尾,則後接android.cursor.dir/,若是內容URI以id結尾,則後接android.cursor.item/
.最後接上vnd.<authority>.<path>
content://com.example.com/table1 所對應的MIME爲:vnd.android.cursor.dir/vnd.com.example.com.table1
content://com.example.com/table1/1 所對應的MIME爲:vnd.android.cursor.item/vnd.com.example.com.table1