<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.CALL_PHONE" />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="打电话"
android:onClick="call"
/>
LinearLayout>
package com.shu;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
/**
* 打电话
* @param view
*/
public void call(View view){
//检查用户是否授权
if(ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CALL_PHONE)!= PackageManager.PERMISSION_GRANTED){
//没有授权则提示用户进行授权
ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.CALL_PHONE},1);
}else {
//内置动作,需要申明权限
Intent intent = new Intent(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel:10086"));
startActivity(intent);
}
}
/**
* 权限请求结果
* @param requestCode
* @param permissions
* @param grantResults
*/
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode){
case 1:
if(grantResults.length>0&&grantResults[0]==PackageManager.PERMISSION_GRANTED){
Intent intent = new Intent(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel:10086"));
startActivity(intent);
}
else {
Toast.makeText(this,"权限未通过",Toast.LENGTH_LONG).show();
}
break;
default:
}
}
}
content://com.android.contacts/data/phones
手机联系人url
查询方法
cursor=getContentResolver().query();
public final Cursor query( Uri uri,
String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
return query(uri, projection, selection, selectionArgs, sortOrder, null);
}
![epub_26211889_207.jpg](https://img-blog.csdnimg.cn/img_convert/7b3423a379f8bfcdeb42b782fbdab64e.png#clientId=ubda6a572-d1fe-4&crop=0&crop=0&crop=1&crop=1&from=drop&id=u8be2f858&margin=[object Object]&name=epub_26211889_207.jpg&originHeight=272&originWidth=1280&originalType=binary&ratio=1&rotation=0&showTitle=false&size=41739&status=done&style=none&taskId=u7e351c8b-f4d1-42af-ba49-a43c2732732&title=)
//读取电话通讯录
private void read(){
Cursor cursor = null;
try {
System.out.println("xxx读取url:"+ContactsContract.CommonDataKinds.Phone.CONTENT_URI);
cursor=getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null,null,null,null);
if(cursor!=null){
while (cursor.moveToNext()){
String name = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String phone = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
listViews.add(name+"\n"+phone);
}
adapter.notifyDataSetChanged();
}
}catch (Exception e){
e.printStackTrace();
}finally {
if(cursor!=null){
cursor.close();
}
}
}
插入数据
将待添加的数据组装到ContentValues中,然后调用ContentResolver的insert()方法,将Uri和ContentValues作为参数传入即可。
/**
* 插入一条数据
*/
public void add(){
System.out.println("xxx读取url:"+ContactsContract.CommonDataKinds.Phone.CONTENT_URI);
ContentValues contentValues=new ContentValues();
contentValues.put("admin",10086);
getContentResolver().insert(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,contentValues)
}
修改数据
/**
* 修改数据
*/
public void update(){
System.out.println("xxx读取url:"+ContactsContract.CommonDataKinds.Phone.CONTENT_URI);
ContentValues contentValues=new ContentValues();
contentValues.put("admin","");
getContentResolver().update(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,contentValues,"admin=?",new String[]{"10001"});
}
删除数据
/**
* 删除数据
*/
public void delete(){
System.out.println("xxx读取url:"+ContactsContract.CommonDataKinds.Phone.CONTENT_URI);
ContentValues contentValues=new ContentValues();
contentValues.put("admin","");
getContentResolver().delete(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,"admin=?",new String[]{"10001"});
}
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".FirstActivity">
<ListView
android:id="@+id/listview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
LinearLayout>
package com.shu;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.content.ContentValues;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
public class FirstActivity extends AppCompatActivity {
ArrayAdapter<String> adapter;
List<String> listViews=new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_first);
ListView listView = (ListView) findViewById(R.id.listview);
adapter=new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, listViews);
listView.setAdapter(adapter);
//没有权限
if(ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS)!= PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(FirstActivity.this,new String[]{Manifest.permission.READ_CONTACTS},1);
}else{
read();
}
}
//读取电话通讯录
private void read(){
Cursor cursor = null;
try {
System.out.println("xxx读取url:"+ContactsContract.CommonDataKinds.Phone.CONTENT_URI);
cursor=getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null,null,null,null);
if(cursor!=null){
while (cursor.moveToNext()){
String name = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String phone = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
listViews.add(name+"\n"+phone);
}
adapter.notifyDataSetChanged();
}
}catch (Exception e){
e.printStackTrace();
}finally {
if(cursor!=null){
cursor.close();
}
}
}
/**
* 插入一条数据
*/
public void add(){
System.out.println("xxx读取url:"+ContactsContract.CommonDataKinds.Phone.CONTENT_URI);
ContentValues contentValues=new ContentValues();
contentValues.put("admin",10086);
getContentResolver().insert(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,contentValues);
}
/**
* 修改数据
*/
public void update(){
System.out.println("xxx读取url:"+ContactsContract.CommonDataKinds.Phone.CONTENT_URI);
ContentValues contentValues=new ContentValues();
contentValues.put("admin","");
getContentResolver().update(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,contentValues,"admin=?",new String[]{"10001"});
}
/**
* 删除数据
*/
public void delete(){
System.out.println("xxx读取url:"+ContactsContract.CommonDataKinds.Phone.CONTENT_URI);
ContentValues contentValues=new ContentValues();
contentValues.put("admin","");
getContentResolver().delete(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,"admin=?",new String[]{"10001"});
}
//权限不足时申明权限
@Override
public void onRequestPermissionsResult(int requestCode,String[] permissions, int[] grantResults) {
switch (requestCode){
case 1:
if(grantResults.length>0&&grantResults[0]==PackageManager.PERMISSION_GRANTED){
read();
}
else {
Toast.makeText(this,"权限未通过",Toast.LENGTH_LONG).show();
}
break;
default:
}
}
}
方推荐的方式就是使用内容提供器,可以通过新建一个类去继承ContentProvider的方式来创建一个自己的内容提供器。ContentProvider类中有6个抽象方法,我们在使用子类继承它的时候,需要将这6个方法全部重写。
package com.shu;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
/**
* @author shu
* @date 2021/7/22
* @description 自定义内容处理器
*/
public class MyProvider extends ContentProvider {
@Override
public boolean onCreate() {
return false;
}
@Nullable
@Override
public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
return null;
}
@Nullable
@Override
public String getType(@NonNull Uri uri) {
return null;
}
@Nullable
@Override
public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
return null;
}
@Override
public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
return 0;
}
@Override
public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
return 0;
}
}
onCreate()初始化内容提供器的时候调用。通常会在这里完成对数据库的创建和升级等操作,返回true表示内容提供器初始化成功,返回false则表示失败。
query()从内容提供器中查询数据。使用uri参数来确定查询哪张表,projection参数用于确定查询哪些列,selection和selectionArgs参数用于约束查询哪些行,sortOrder参数用于对结果进行排序,查询的结果存放在Cursor对象中返回。
insert()向内容提供器中添加一条数据。使用uri参数来确定要添加到的表,待添加的数据保存在values参数中。添加完成后,返回一个用于表示这条新记录的URI。
update()更新内容提供器中已有的数据。使用uri参数来确定更新哪一张表中的数据,新数据保存在values参数中,selection和selectionArgs参数用于约束更新哪些行,受影响的行数将作为返回值返回。
delete()从内容提供器中删除数据。使用uri参数来确定删除哪一张表中的数据,selection和selectionArgs参数用于约束删除哪些行,被删除的行数将作为返回值返回。
getType()根据传入的内容URI来返回相应的MIME类型,是所有的内容提供器都必须提供的一个方法,用于获取Uri对象所对应的MIME类型。一个内容URI所对应的MIME字符串主要由3部分组成,Android对这3个部分做了如下格式规定。必须以vnd开头。如果内容URI以路径结尾,则后接android.cursor.dir/,如果内容URI以id结尾,则后接android.cursor.item/。 最后接上vnd.. 。
content://com.shu.provider/table1
vnd.android.cursor.dir/vnd.com.shu. provider.table1
先定义一个内容提供器完成对数据的操作
package com.shu;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
/**
* @author shu
* @date 2022/3/29
* @description 跨程序共享处理器
*/
public class DatabaseProvider extends ContentProvider {
public static final int BOOK_DIR = 0;
public static final int BOOK_ITEM = 1;
public static final int CATEGORY_DIR = 2;
public static final int CATEGORY_ITEM = 3;
public static final String AUTHORITY = "com.shu.databasesave.provider";
private static final UriMatcher uriMatcher;
private MyDatabaseHelper helper;
static {
//在静态代码块中对UriMatcher进行初始化操作,并将期望匹配的几种URI格式添加进去
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI(AUTHORITY, "book", BOOK_DIR);
uriMatcher.addURI(AUTHORITY, "book/#", BOOK_ITEM);
uriMatcher.addURI(AUTHORITY, "category", CATEGORY_DIR);
uriMatcher.addURI(AUTHORITY, "category/#", CATEGORY_ITEM);
}
@Override
public boolean onCreate() {
//完成创建、升级 BookStore数据库
helper = new MyDatabaseHelper(getContext(), "BookStore.db", null, 2);
return true;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
//查询数据
SQLiteDatabase db = helper.getWritableDatabase();
Cursor cursor = null;
switch (uriMatcher.match(uri)) {
case BOOK_DIR:
cursor = db.query("Book", projection, selection, selectionArgs, null, null, sortOrder);
break;
case BOOK_ITEM:
String bookId = uri.getPathSegments().get(1);
cursor = db.query("Book", projection, "id = ?", new String[]{bookId}, null, null, sortOrder);
break;
case CATEGORY_DIR:
cursor = db.query("Category", projection, selection, selectionArgs, null, null, sortOrder);
break;
case CATEGORY_ITEM:
String categoryId = uri.getPathSegments().get(1);
cursor = db.query("Category", projection, "id = ?", new String[]{categoryId}, null, null, sortOrder);
break;
default:
break;
}
return cursor;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
//添加数据
SQLiteDatabase db = helper.getWritableDatabase();
Uri uriReturn = null;
switch (uriMatcher.match(uri)) {
case BOOK_DIR:
case BOOK_ITEM:
long newBookId = db.insert("Book", null, values);
uriReturn = Uri.parse("content://" + AUTHORITY + "/book/" + newBookId);
break;
case CATEGORY_DIR:
case CATEGORY_ITEM:
long newCategoryId = db.insert("Category", null, values);
uriReturn = Uri.parse("content://" + AUTHORITY + "/category/" + newCategoryId);
break;
default:
break;
}
return uriReturn;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
//更新数据
SQLiteDatabase db = helper.getWritableDatabase();
int updateRows = 0;
switch (uriMatcher.match(uri)) {
case BOOK_DIR:
updateRows = db.update("Book", values, selection, selectionArgs);
break;
case BOOK_ITEM:
String bookId = uri.getPathSegments().get(1);
updateRows = db.update("Book", values, "id = ?", new String[]{bookId});
break;
case CATEGORY_DIR:
updateRows = db.update("Category", values, selection, selectionArgs);
break;
case CATEGORY_ITEM:
String categoryId = uri.getPathSegments().get(1);
updateRows = db.update("Category", values, "id = ?", new String[]{categoryId});
break;
default:
break;
}
return updateRows;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
//删除数据
SQLiteDatabase db = helper.getWritableDatabase();
int deleteRows = 0;
switch (uriMatcher.match(uri)) {
case BOOK_DIR:
deleteRows = db.delete("Book", selection, selectionArgs);
break;
case BOOK_ITEM:
String bookId = uri.getPathSegments().get(1);
deleteRows = db.delete("Book", "id = ?", new String[]{bookId});
break;
case CATEGORY_DIR:
deleteRows = db.delete("Category", selection, selectionArgs);
break;
case CATEGORY_ITEM:
String categoryId = uri.getPathSegments().get(1);
deleteRows = db.delete("Category", "id = ?", new String[]{categoryId});
break;
default:
break;
}
return deleteRows;
}
@Override
public String getType(Uri uri) {
switch (uriMatcher.match(uri)) {
case BOOK_DIR:
return "vnd.android.cursor.dir/vnd.com.shu.databasesave.provider.book";
case BOOK_ITEM:
return "vnd.android.cursor.item/vnd.com.shu.databasesave.provider.book";
case CATEGORY_DIR:
return "vnd.android.cursor.dir/vnd.com.shu.databasesave.provider.category";
case CATEGORY_ITEM:
return "vnd.android.cursor.item/vnd.com.shu.databasesave.provider.category";
}
return null;
}
}
package com.shu;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
/**
* @author shu
* @date 2022/3/29
* @description 自定义工具类
*/
public class MyDatabaseHelper extends SQLiteOpenHelper {
private Context context;
public static final String CREATE_BOOK = "create table Book(" +
"id integer primary key autoincrement," +
"author text," +
"price real," +
"pages integer," +
"name text)";
public static final String CREATE_CATEGORY = "create table Category(" +
"id integer primary key autoincrement," +
"category_name text," +
"category_code integer)";
public MyDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
this.context = context;
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_BOOK);//执行sql语句创建Book表
db.execSQL(CREATE_CATEGORY);//执行sql语句创建Category表
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("drop table if exists Book");
db.execSQL("drop table if exists Category");
onCreate(db);
}
}
<provider
android:name=".DatabaseProvider"
android:authorities="com.shu.databasesave.provider"
android:enabled="true"
android:exported="true">
provider>
再定义一个测试
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/btn_add"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Add Data To Book"
android:textAllCaps="false"
android:textSize="18sp"
android:textStyle="bold" />
<Button
android:id="@+id/btn_query"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Query Data From Book"
android:textAllCaps="false"
android:textSize="18sp"
android:textStyle="bold" />
<Button
android:id="@+id/btn_update"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Update Book"
android:textAllCaps="false"
android:textSize="18sp"
android:textStyle="bold" />
<Button
android:id="@+id/btn_delete"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Delete Data From Book"
android:textAllCaps="false"
android:textSize="18sp"
android:textStyle="bold" />
LinearLayout>
package com.example.providertest;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = "MainActivity";
private Button btn_add, btn_query, btn_update, btn_delete;
private String newId;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();//初始化UI控件
}
private void initView() {
btn_add = (Button) findViewById(R.id.btn_add);
btn_query = (Button) findViewById(R.id.btn_query);
btn_update = (Button) findViewById(R.id.btn_query);
btn_delete = (Button) findViewById(R.id.btn_delete);
btn_add.setOnClickListener(this);
btn_query.setOnClickListener(this);
btn_update.setOnClickListener(this);
btn_delete.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_add:
add();//添加数据
Toast.makeText(this, "add successfully", Toast.LENGTH_SHORT).show();
break;
case R.id.btn_query:
query();//查询数据
Toast.makeText(this, "query successfully", Toast.LENGTH_SHORT).show();
break;
case R.id.btn_update:
update();//更新数据
Toast.makeText(this, "update successfully", Toast.LENGTH_SHORT).show();
break;
case R.id.btn_delete:
delete();//删除数据
Toast.makeText(this, "delete successfully", Toast.LENGTH_SHORT).show();
break;
default:
break;
}
}
private void add() {
Uri uri = Uri.parse("content://com.shu.databasesave.provider/book");
ContentValues cv = new ContentValues();
cv.put("name", "A Clash of Kings");
cv.put("author", "George Martin");
cv.put("pages", 1040);
cv.put("price", 22.85);
Uri newUri = getContentResolver().insert(uri, cv);
newId = newUri.getPathSegments().get(1);
}
private void query() {
Uri uri = Uri.parse("content://com.shu.databasesave.provider/book");
Cursor cursor = getContentResolver().query(uri, null, null, null, null);
if (cursor != null) {
while (cursor.moveToNext()) {
String name = cursor.getString(cursor.getColumnIndex("name"));
String author = cursor.getString(cursor.getColumnIndex("author"));
int pages = cursor.getInt(cursor.getColumnIndex("pages"));
double price = cursor.getDouble(cursor.getColumnIndex("price"));
Log.e(TAG, "book name is " + name);
Log.e(TAG, "book author is " + author);
Log.e(TAG, "book pages are " + pages);
Log.e(TAG, "book price is " + price);
}
cursor.close();
}
}
private void update() {
Uri uri = Uri.parse("content://com.shu.databasesave.provider/book/" + newId);
ContentValues cv = new ContentValues();
cv.put("name", "A Storm of Swords");
cv.put("pages", 1216);
cv.put("price", 24.05);
getContentResolver().update(uri, cv, null, null);
}
private void delete() {
Uri uri = Uri.parse("content://com.shu.databasesave.provider/book/" + newId);
getContentResolver().delete(uri, null, null);
}
}