Android學習筆記6-跨程式共享資料-ContentProvider
1,內容提供器簡介
1,內容提供器(ContentProvider) 主要用於在不同的應用程式之間實現資料共享額功能,它提供了一套完整的機制,允許一個程式訪問另一個程式的資料,同時保證被訪問的資料的安全性。
2,使用內提供器是Android實現跨程式共享資料的標準形式。
2,執行時許可權
Android開發團隊在6.0系統中加入了執行時許可權,使用者可以不用在安裝軟體時一次性授權應用的所有申請的許可權,而是在軟體的使用過程中再對某一許可權進行授權。
Android中的危險許可權有9組24個許可權
分別是日曆、拍照、聯絡人、位置、麥克風、電話、感測器、簡訊及儲存。
注意 :24個許可權每個都屬於一個許可權組,我們在進行執行時許可權的處理時 使用的是許可權名
但是使用者一旦同意授權了,那麼該許可權所在的許可權組的其他許可權也會被授權。
下面我們做一個打電話的Demo
首先在AndroidManifest.xml檔案中宣告許可權
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.chen.runtimepermissiontest" >
//CALL_PHONE是打電話時所需要的許可權
<uses-permission android:name="android.permission.CALL_PHONE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
MainActivity.java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button makeCall = (Button) 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 onRequestPermissionsResult (int requestCode,String [] permissions,int [] grantResults) {
switch (requestCode) {
case 1:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
call();
} else {
Toast.makeText(this, "你沒許可權", Toast.LENGTH_SHORT).show();
}
break;
default:
}
}
}
ContextCompat.checkSelfPermission(Context, 許可權名).
1,先呼叫checkSelfPermission方法判斷使用者是否已經授過權,此方法接受兩個引數,第一個是Context,第二個是具體的許可權名。
2,將checkSelfPermission方法的返回值與 PackageManager.PERMISSION_GRANTED 比對
若相等則說明使用者已經授權,不相等則表示使用者沒有授權.
3, 若使用者沒有授權,則呼叫ActivityCompat.requestPermissions(Activity例項,String陣列,請求碼)。
將申請的許可權名放入String陣列中,請求碼必須是唯一值。
4,呼叫了requestPermissions()方法後,系統會彈出一個許可權申請的對話方塊,可以選擇同意或者拒絕。
然後把申請許可權的結果回撥到onRequestPermissionsResult(nt requestCode(請求碼),String [] permissions,int [] grantResults))中,授權的結果被封裝到grantResults引數中。
3,訪問其他程式中的資料
內容提供器的用法有兩種
- 使用現有的內容提供器來操作相應程式中的資料
- 建立自己的內容提供器給我們的程式提供外部訪問介面
3-1 ContentResolver的基本用法
通過Context的getContentResolver()方法獲取該類的例項
- insert() 新增資料
- update() 更新資料
- delete() 刪除資料
- query() 查詢資料
Uri:
ContentResolver中的增刪改查的方法不接受資料庫表名的引數,而是使用Uri代替,稱為內容URI,內容URI給內容提供器中的資料建立了唯一的識別符號。
Uri = authority + path
- authurity是為了區分不同的應用程式,一般為應用程式的包名. 如: com/example.app.provider
- path是為了同一應用程式中的不同表 如:table1
則Uri = com/example.app.provider/table1
為了辨認某個字串是內容Uri,需要在字串的頭部加上協議宣告。
URI的標準寫法:
content://com/example.app.provider/table1
再把它解析成Uri物件
Uri uri = Uri.parse(“content://com/example.app.provider/table1”)
查詢資料
Cursor cursor = getContentResolver(uri, //指定查詢某個應用程式下的某一張表
projection, // 指定查詢的列名
selection, // 指定where的約束條件
selectionArgs, // 為where中的佔位符提供具體的值
sortOrder // 指定查詢結果的排序方式
);
插入資料
ContentValues values = new ContentValues();
values.put("column1","text");
values.put("column2",1);
getContentRresolver().insert(uri,values);
更改資料
ContentValues values = new ContentValues();
values.put("columns1", " ");
getContentResolver().update(uri,values ,"column1 = ? and column2 = ?" ,
new String[] {"text","1"});
刪除資料
getContentResolver().delete(uri,"column2 = ?" ,new String[] {"1"} );
讀取聯絡人的demo
public class MainActivity extends AppCompatActivity {
ArrayAdapter<String> adapter;
List<String> contactList = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView listView = (ListView) findViewById(R.id.contacts_id);
adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,
contactList);
listView.setAdapter(adapter);
//獲取聯絡人許可權
if(ContextCompat.checkSelfPermission(this,
Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,new String[]
{Manifest.permission.READ_CONTACTS} ,1 );
} else {
readContact();
}
}
@Override
public void onRequestPermissionsResult(int requestCode,String[] permissions,int[] grantResults) {
switch (requestCode) {
case 1 :
if (grantResults.length >0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
readContact();
} else {
Toast.makeText(this, "你沒有讀取聯絡人許可權", Toast.LENGTH_SHORT).show();
}
default:break;
}
}
private void readContact() {
Cursor cursor = null;
try {
//查詢聯絡人資料
cursor = getContentResolver().query(ContactsContract.CommonDataKinds
.Phone.CONTENT_URI,null ,null ,null );
if(cursor != null) {
while (cursor.moveToNext()) {
//獲取聯絡人姓名
String displayName = cursor.getString(cursor.getColumnIndex
(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
//獲取聯絡人號碼
String displayNumber = cursor.getString(cursor.getColumnIndex
(ContactsContract.CommonDataKinds.Phone.NUMBER));
contactList.add(displayName + "\n" + displayNumber);
}
adapter.notifyDataSetChanged();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if(cursor != null) {
cursor.close();
}
}
}
}