1.Client端代码编写
1.1activity_content_write.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="5dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="40dp" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="center" android:text="姓名:" android:textColor="@color/black" android:textSize="17sp" /> <EditText android:id="@+id/et_name" android:layout_width="0dp" android:layout_height="match_parent" android:layout_marginTop="3dp" android:layout_marginBottom="3dp" android:layout_weight="1" android:background="@drawable/editext_selector" android:hint="请输入姓名" android:inputType="text" android:maxLength="12" android:text="Jack" android:textColor="@color/black" android:textSize="17sp" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="40dp" android:orientation="horizontal"> <TextView android:id="@+id/tv_age" android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="center" android:text="年龄:" android:textColor="@color/black" android:textSize="17sp" /> <EditText android:id="@+id/et_age" android:layout_width="0dp" android:layout_height="match_parent" android:layout_marginTop="3dp" android:layout_marginBottom="3dp" android:layout_weight="1" android:background="@drawable/editext_selector" android:hint="请输入年龄" android:inputType="number" android:maxLength="2" android:text="18" android:textColor="@color/black" android:textSize="17sp" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="40dp" android:orientation="horizontal"> <TextView android:id="@+id/tv_height" android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="center" android:text="身高:" android:textColor="@color/black" android:textSize="17sp" /> <EditText android:id="@+id/et_height" android:layout_width="0dp" android:layout_height="match_parent" android:layout_marginTop="3dp" android:layout_marginBottom="3dp" android:layout_weight="1" android:background="@drawable/editext_selector" android:hint="请输入身高" android:inputType="number" android:maxLength="3" android:text="180" android:textColor="@color/black" android:textSize="17sp" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="40dp" android:orientation="horizontal"> <TextView android:id="@+id/tv_weight" android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="center" android:text="体重:" android:textColor="@color/black" android:textSize="17sp" /> <EditText android:id="@+id/et_weight" android:layout_width="0dp" android:layout_height="match_parent" android:layout_marginTop="3dp" android:layout_marginBottom="3dp" android:layout_weight="1" android:background="@drawable/editext_selector" android:hint="请输入体重" android:inputType="numberDecimal" android:maxLength="5" android:text="180" android:textColor="@color/black" android:textSize="17sp" /> </LinearLayout> <CheckBox android:id="@+id/ck_married" android:layout_width="wrap_content" android:layout_height="wrap_content" android:checked="false" android:gravity="center" android:text="已婚" android:textColor="@color/black" android:textSize="17sp" /> <Button android:id="@+id/btn_save" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="保存" android:textColor="@color/black" android:textSize="17sp" /> <Button android:id="@+id/btn_read" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="读取" android:textColor="@color/black" android:textSize="17sp" /> <Button android:id="@+id/btn_delete" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="删除" android:textColor="@color/black" android:textSize="17sp" /> </LinearLayout>
1.2ContentWriteActivity.java
package com.example.chapter07_client; import androidx.appcompat.app.AppCompatActivity; import android.annotation.SuppressLint; import android.content.ContentValues; import android.database.Cursor; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.CheckBox; import android.widget.EditText; import com.example.chapter07_client.entity.User; import com.example.chapter07_client.util.ToastUtil; public class ContentWriteActivity extends AppCompatActivity implements View.OnClickListener{ private EditText et_name; private EditText et_age; private EditText et_height; private EditText et_weight; private CheckBox ck_married; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_content_write); et_name = findViewById(R.id.et_name); et_age = findViewById(R.id.et_age); et_height = findViewById(R.id.et_height); et_weight = findViewById(R.id.et_weight); ck_married = findViewById(R.id.ck_married); findViewById(R.id.btn_save).setOnClickListener(this); findViewById(R.id.btn_delete).setOnClickListener(this); findViewById(R.id.btn_read).setOnClickListener(this); } @SuppressLint("Range") @Override public void onClick(View v) { switch(v.getId()) { case R.id.btn_save: ContentValues values = new ContentValues(); values.put(UserInfoContent.USER_NAME, et_name.getText().toString()); values.put(UserInfoContent.USER_AGE, Integer.parseInt(et_age.getText().toString())); values.put(UserInfoContent.USER_HEIGHT, Integer.parseInt(et_height.getText().toString())); values.put(UserInfoContent.USER_WEIGHT, Float.parseFloat(et_weight.getText().toString())); values.put(UserInfoContent.USER_MARRIED, ck_married.isChecked()); getContentResolver().insert(UserInfoContent.CONTENT_URI, values); ToastUtil.show(this, "保存成功"); break; case R.id.btn_read: Cursor cursor = getContentResolver().query(UserInfoContent.CONTENT_URI, null, null, null, null); if (cursor != null) { while(cursor.moveToNext()) { User info = new User(); info.id = cursor.getInt(cursor.getColumnIndex(UserInfoContent._ID)); info.name = cursor.getString(cursor.getColumnIndex(UserInfoContent.USER_NAME)); info.age = cursor.getInt(cursor.getColumnIndex(UserInfoContent.USER_AGE)); info.height = cursor.getInt(cursor.getColumnIndex(UserInfoContent.USER_HEIGHT)); info.weight = cursor.getFloat(cursor.getColumnIndex(UserInfoContent.USER_WEIGHT)); info.married = cursor.getInt(cursor.getColumnIndex(UserInfoContent.USER_MARRIED)) == 1 ? true : false; Log.d("ning", info.toString()); } cursor.close(); } break; } } }
1.3UserInfoContent.java
package com.example.chapter07_client; import android.net.Uri; import android.provider.BaseColumns; public class UserInfoContent implements BaseColumns { public static final String AUTHORITIES = "com.example.chapter07_server.provider.UserInfoProvider"; // content://com.example.chapter07_server.provider.UserInfoProvider // 访问内容提供器的URI public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITIES + "/user"); // 下面是该表的各个字段名称 public static final String USER_NAME = "name"; public static final String USER_AGE = "age"; public static final String USER_HEIGHT = "height"; public static final String USER_WEIGHT = "weight"; public static final String USER_MARRIED = "married"; }
1.4效果:
先启动server端:
控制台输出:
D/ning: UserInfoProvider onCreate
再启动client:
点“保存”:
控制台输出:
D/ning: UserInfoProvider insert
再点“读取”: 控制台输出:
D/ning: UserInfoProvider query D/ning: User{id=1, name='Jack', age=18, height=180, weight=180.0, married=false}
再点击“保存”、“读取”,控制台输出:
D/ning: UserInfoProvider query D/ning: User{id=1, name='Jack', age=18, height=180, weight=180.0, married=false} D/ning: User{id=2, name='Jack', age=18, height=180, weight=180.0, married=false}
2.数据删除
2.1chapter07-server应用的UserInfoProvider.java新增内容:
private static final UriMatcher URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
private static final int USERS = 1;
private static final int USER = 2;
static {
// 往Uri匹配器中添加指定的数据路径
URI_MATCHER.addURI(UserInfoContent.AUTHORITIES, "/user", USERS);
URI_MATCHER.addURI(UserInfoContent.AUTHORITIES, "/user/#", USER);
}
// content://com.example.chapter07_server.provider.UserInfoProvider/user
@Override
public Uri insert(Uri uri, ContentValues values) {
Log.d("ning", "UserInfoProvider insert");
if (URI_MATCHER.match(uri) == USERS) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
db.insert(UserDBHelper.TABLE_NAME, null, values);
}
return uri;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
Log.d("ning", "UserInfoProvider query");
if (URI_MATCHER.match(uri) == USERS) {
SQLiteDatabase db = dbHelper.getReadableDatabase();
return db.query(UserDBHelper.TABLE_NAME, projection, selection, selectionArgs, null, null, null);
}
return null;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
int count = 0;
switch (URI_MATCHER.match(uri)) {
// content://com.example.chapter07_server.provider.UserInfoProvider/user
// 删除多行
case USERS:
SQLiteDatabase db1 = dbHelper.getWritableDatabase();
count = db1.delete(UserDBHelper.TABLE_NAME, selection, selectionArgs);
db1.close();
break;
// content://com.example.chapter07_server.provider.UserInfoProvider/user/2
// 删除单行
case USER:
String id = uri.getLastPathSegment();
SQLiteDatabase db2 = dbHelper.getWritableDatabase();
count = db2.delete(UserDBHelper.TABLE_NAME, "_id=?", new String[]{id});
db2.close();
break;
}
return count;
}
2.2charpter07-client应用的清单文件,新增内容:
<!-- 出于安全考虑,Android 11 要求应用事先说明需要访问的其他软件包 --> <queries> <package android:name="com.example.chapter07_server"/> </queries>
2.3charpter07-client应用的ContentWriteActivity.java中新增内容:
@SuppressLint("Range") @Override public void onClick(View v) { switch(v.getId()) { case R.id.btn_save: ContentValues values = new ContentValues(); values.put(UserInfoContent.USER_NAME, et_name.getText().toString()); values.put(UserInfoContent.USER_AGE, Integer.parseInt(et_age.getText().toString())); values.put(UserInfoContent.USER_HEIGHT, Integer.parseInt(et_height.getText().toString())); values.put(UserInfoContent.USER_WEIGHT, Float.parseFloat(et_weight.getText().toString())); values.put(UserInfoContent.USER_MARRIED, ck_married.isChecked()); getContentResolver().insert(UserInfoContent.CONTENT_URI, values); ToastUtil.show(this, "保存成功"); break; case R.id.btn_read: Cursor cursor = getContentResolver().query(UserInfoContent.CONTENT_URI, null, null, null, null); if (cursor != null) { while(cursor.moveToNext()) { User info = new User(); info.id = cursor.getInt(cursor.getColumnIndex(UserInfoContent._ID)); info.name = cursor.getString(cursor.getColumnIndex(UserInfoContent.USER_NAME)); info.age = cursor.getInt(cursor.getColumnIndex(UserInfoContent.USER_AGE)); info.height = cursor.getInt(cursor.getColumnIndex(UserInfoContent.USER_HEIGHT)); info.weight = cursor.getFloat(cursor.getColumnIndex(UserInfoContent.USER_WEIGHT)); info.married = cursor.getInt(cursor.getColumnIndex(UserInfoContent.USER_MARRIED)) == 1 ? true : false; Log.d("ning", info.toString()); } cursor.close(); } break; case R.id.btn_delete: // 单行删除: // content://com.example.chapter07_server.provider.UserInfoProvider/user/2 // Uri uri = ContentUris.withAppendedId(UserInfoContent.CONTENT_URI, 10); // int count = getContentResolver().delete(uri, null, null); // 多行删除: // content://com.example.chapter07_server.provider.UserInfoProvider/user int count = getContentResolver().delete(UserInfoContent.CONTENT_URI, "name=?", new String[]{"Jack"}); if (count > 0) { ToastUtil.show(this, "删除成功"); } break; } }
2.4charpter07-client及charpter07-server应用的UserInfoContent.java新增内容:
public static final String AUTHORITIES = "com.example.chapter07_server.provider.UserInfoProvider"; // content://com.example.chapter07_server.provider.UserInfoProvider // 访问内容提供器的URI public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITIES + "/user");
2.5效果:
2.5.1单条删除:
点“读取”:
D/ning: User{id=8, name='Jack', age=18, height=180, weight=180.0, married=false}
D/ning: User{id=9, name='Jack', age=18, height=180, weight=180.0, married=false}
D/ning: User{id=10, name='Jack', age=18, height=180, weight=180.0, married=false}
D/ning: User{id=11, name='Jack', age=18, height=180, weight=180.0, married=false}
点“删除”,删除id=10的,再点“读取”,可以看到id=10的已经被删除了:
D/ning: User{id=8, name='Jack', age=18, height=180, weight=180.0, married=false}
D/ning: User{id=9, name='Jack', age=18, height=180, weight=180.0, married=false}
D/ning: User{id=11, name='Jack', age=18, height=180, weight=180.0, married=false}
2.5.2多条删除:
点“读取”:
D/ning: User{id=8, name='Jack', age=18, height=180, weight=180.0, married=false} D/ning: User{id=9, name='Jack', age=18, height=180, weight=180.0, married=false} D/ning: User{id=11, name='Jack', age=18, height=180, weight=180.0, married=false}
点“删除”,删除所有名字等于"Jack"的,再点“读取”,可以看到全都删除了(因为名字都等于Jack):
(备注:这里直接点“读取”,会报WaitForGcToComplete blocked Instrumentation on None for 6.246ms。所以我采用先点一下“保存”,再点“读取”的方式。查出来id=12,说明点击“删除”时,当时所有name=Jack的记录即id=8,9,11的,已经都被删掉了。)
D/ning: User{id=12, name='Jack', age=18, height=180, weight=180.0, married=false}