剛開始學習ContentProvider時是學的系統的ContentProvider,沒碰到什么問題,但是在學習自定義ContentProvider的實作時,唉,碰到好幾個問題,花了我好多時間,
我碰到的問題:
1. java.lang.IllegalArgumentException: column '_id' does not exist
解決方法:創建資料表時插入一個名為_id的列,型別為自增量,因為在使用Cursor相關的Adapter時需要用到這個列
2.Failed to find provider <authority> for user 0 ; expected to find a valid ContentProvider for
解決方法:在第一個應用的AndroidManifest.xml中添加如下代碼
<provider
android:authorities="cn.sch.myprovider"
android:name=".MyProvide"
android:exported="true"
android:multiprocess="false"
android:grantUriPermissions="true"
android:writePermission="cn.sch.myprovider.Write"
android:readPermission="cn.sch.myprovider.Read"
>
</provider>
但是當我使用API 30時卻還是會報錯,報空指標例外,到現在還沒解決,真的菜啊,所以為了讓程式運行起來,我就選擇API 29 ,就能正常運行了
3.注意:在資料庫類里寫sql陳述句時,最容易出錯,比如少了空格拼接起來就是錯誤的sql陳述句,英文逗號寫成中文逗號,進行增刪改查時表名,列名要寫正確
4.Uri里的authorities也非常容易搞錯,搞錯了就會報 uri 找不到例外
5.還有很多小問題就不一一描述了,細心認真點,相信你們自己能解決
為了讓你們(新手,包括我自己)能正確的運行起我的程式來,我把所有類,布局檔案和配置資訊都貼出來,如果你去看別人寫的自定義ContentProvider的實作,你會發現有這幾個問題,不敢說全部,大多數是這樣,自定義ContentProvider的實作本來就是面向新手的,所以把資訊都寫全來才好去學習和模仿加創新,
1.缺少布局檔案,對于我這種小白來說真的就離譜,id都不知道哪個是哪個
2.缺少一些類,不如資料庫類,
3.只貼出一些重要代碼片段來,對于小白來說,的確不好搞
4.缺少配置資訊,這只能看看,要想模仿就難了,一大堆BUG等著你
5.完整的原始碼要VIP或者收費
專案里的代碼詳解我就不說了,大多數都有解釋,實在不懂的,可以自行百度,肯定比我在這說的清楚詳細易懂,我這篇給文章主要還是讓各位實作自定義ContentProvider,能跑起來
先來看看我效果
20211021
注意:視頻中的洗掉我是按序號洗掉的,比如表中有一條記錄:
序號:1 姓名:小明 作業:Android Development
然后我在輸入框中輸入,只要序號是1,不管姓名和作業輸的是什么,都會將
序號:1 姓名:小明 作業:Android Development 這條記錄洗掉,
(感興趣的可以自己去改改)
首先看一下我的專案結構,你就知道要寫哪些類和布局檔案了



模塊gamedemo是第一個應用
MainActivity代碼如下
import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity implements View.OnClickListener {
private static final String TAG = "lzs";
private DbHelp dbHelp;
private SQLiteDatabase db;
private TextView userTv;
private Button btn_query;
private Button btn_insert;
private Button btn_delete;
private Button btn_update;
private int m=2;
private int n=3;
private EditText xuhao;
private EditText xingming;
private EditText zhiye;
private int id;
private String name;
private String job;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.dbHelp = new DbHelp(this); //創建資料庫
this.db = this.dbHelp.getWritableDatabase();
init(); //初始化控制元件
}
private void init() {
btn_query = findViewById(R.id.btn_query);
btn_insert = findViewById(R.id.btn_insert);
btn_delete = findViewById(R.id.btn_delete);
btn_update = findViewById(R.id.btn_update);
xuhao = findViewById(R.id.xuhao);
xingming = findViewById(R.id.xingming);
zhiye = findViewById(R.id.zhiye);
btn_query.setOnClickListener(this);
btn_insert.setOnClickListener(this);
btn_delete.setOnClickListener(this);
btn_update.setOnClickListener(this);
}
@Override
protected void onStart() {
super.onStart();
}
@Override
protected void onDestroy() {
super.onDestroy();
db.close();
dbHelp.close();
}
@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.btn_query:
btn_query();
break;
case R.id.btn_insert:
btn_insert();
break;
case R.id.btn_delete:
btn_delete();
break;
case R.id.btn_update:
btn_update();
break;
}
}
//查詢函式
private void btn_query(){
Cursor user = this.db.query("user", null, null, null, null, null, null);
this.userTv = findViewById(R.id.id_user_db);
//清空文本,防止重復查詢而多次顯示
if(!TextUtils.isEmpty(this.userTv.getText()))
{
this.userTv.setText("");
}
while (user.moveToNext()){
String id = user.getString(0);
String name = user.getString(1);
String jobs = user.getString(2);
this.userTv.append("序號:"+id+" 姓名:"+name+" 作業:"+jobs+"\n");
}
}
//插入函式(沒有用SQL陳述句,用的是Android的方式)
private void btn_insert(){
if(!TextUtils.isEmpty(xuhao.getText())&&!TextUtils.isEmpty(xingming.getText())&&!TextUtils.isEmpty(zhiye.getText())){
id = Integer.parseInt(xuhao.getText().toString());
name = xingming.getText().toString();
job = zhiye.getText().toString();
Cursor result=db.rawQuery("select * from user where _id = "+id,null);
if(!result.isAfterLast()){
Toast.makeText(MainActivity.this,"插入失敗,改記錄已存在或序號重復!",Toast.LENGTH_SHORT).show();
}else {
Uri uri_user = Uri.parse("content://cn.sch.myprovider/user");
// 向user表插入資料
ContentValues values3 = new ContentValues();
values3.put("_id", id);
values3.put("name", name);
values3.put("jobs", job);
// 獲取ContentResolver
ContentResolver resolver3 = getContentResolver();
// 通過ContentResolver 根據URI 向ContentProvider中插入資料
resolver3.insert(uri_user, values3);
Toast.makeText(MainActivity.this,"插入成功",Toast.LENGTH_SHORT).show();
}
}else {
Toast.makeText(MainActivity.this,"請填寫完整,不能為空!",Toast.LENGTH_SHORT).show();
}
}
//洗掉函式(利用SQL陳述句洗掉,你也可以用Android的方式洗掉),因為序號是唯一的,所以直接根據提供的序號洗掉就可以了
private void btn_delete(){
if(!TextUtils.isEmpty(xuhao.getText())){
id = Integer.parseInt(xuhao.getText().toString());
Cursor result=db.rawQuery("select _id from user where _id="+id,null);
if(!result.isAfterLast()){
db.execSQL("delete from user where _id="+id);
Toast.makeText(MainActivity.this,"洗掉成功",Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(MainActivity.this,"洗掉失敗,沒有該條記錄!",Toast.LENGTH_SHORT).show();
}
}else {
Toast.makeText(MainActivity.this,"請填寫完整,不能為空!",Toast.LENGTH_SHORT).show();
}
}
//更新函式(利用SQL陳述句更新,你也可以用Android的方式更新),因為序號唯一,所以直接根據輸入的序號更改就可以了
private void btn_update(){
if(!TextUtils.isEmpty(xuhao.getText())&&!TextUtils.isEmpty(xingming.getText())&&!TextUtils.isEmpty(zhiye.getText())){
id = Integer.parseInt(xuhao.getText().toString());
name = xingming.getText().toString();
job = zhiye.getText().toString();
Cursor result=db.rawQuery("select * from user where _id="+id,null);
if(!result.isAfterLast()){
db.execSQL("update user set _id="+id +" where _id="+id);
db.execSQL("update user set name='"+name +"' where _id="+id);//注意是 set='name' 如果不清楚可以再去看看資料庫的知識
db.execSQL("update user set jobs='"+job +"' where _id="+id);
Toast.makeText(MainActivity.this,"更新成功",Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(MainActivity.this,"更新失敗,改記錄不存在!",Toast.LENGTH_SHORT).show();
}
}else {
Toast.makeText(MainActivity.this,"請填寫完整,不能為空!",Toast.LENGTH_SHORT).show();
}
}
}
MainActivity的布局檔案activity_main.xml 代碼如下
<?xml version="1.0" encoding="utf-8"?>
<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"
android:orientation="vertical"
android:gravity="center">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="50dp"
android:text="第一個應用"
android:textSize="30dp"/>
<TextView
android:id="@+id/id_user_db"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="250dp"
android:text="" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="2"
android:gravity="center"
android:orientation="vertical">
<EditText
android:id="@+id/xuhao"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:hint="請輸入序號"
android:inputType="number" />
<EditText
android:id="@+id/xingming"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:hint="請輸入姓名"
android:inputType="textPersonName" />
<EditText
android:id="@+id/zhiye"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:hint="請輸入職業"
android:inputType="textPersonName" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="2"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:orientation="horizontal">
<Button
android:id="@+id/btn_query"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="查詢資料" />
<Button
android:id="@+id/btn_insert"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:text="插入資料" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_horizontal"
android:orientation="horizontal">
<Button
android:id="@+id/btn_delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="洗掉資料" />
<Button
android:id="@+id/btn_update"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:text="更新資料" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
MyProvide代碼如下
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
public class MyProvide extends ContentProvider {
private Context mContext;
private DbHelp dbHelp = null;
private SQLiteDatabase db = null;
public static final String AUTHORITY = "cn.sch.myprovider";
public static final int User_Code = 1;
private UriMatcher mMatcher;
@Override
public boolean onCreate() {
mContext = getContext();
mMatcher = new UriMatcher(UriMatcher.NO_MATCH);
//初始化
// 若URI資源路徑 = content://cn.sch.myprovider/user ,則回傳注冊碼User_Code
mMatcher.addURI(AUTHORITY, "user", User_Code);
dbHelp = new DbHelp(mContext);
this.db = dbHelp.getWritableDatabase();
// 初始化表的資料
db.execSQL("delete from user");
db.execSQL("insert into user values(1,'xiaoming','Android Development')");
db.execSQL("insert into user values(2,'xiaohua','Java Development')");
return true;
}
@Override
public Cursor query( Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
String tableName = getTableName(uri);
return db.query(tableName,projection,selection,selectionArgs,null,null,sortOrder,null);
}
@Override
public String getType( Uri uri) {
return null;
}
@Override
public Uri insert( Uri uri, ContentValues values) {
String tableName = getTableName(uri);
//向表中插入資料
db.insert(tableName,null,values);
mContext.getContentResolver().notifyChange(uri,null);
return uri;
}
@Override
public int delete( Uri uri, String selection, String[] selectionArgs) {
String tableName = getTableName(uri);
int count=db.delete(tableName, null, null);
if(count>0){
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
return 0;
}
@Override
public int update( Uri uri, ContentValues values, String selection, String[] selectionArgs) {
String tableName = getTableName(uri);
int count = db.update(tableName, values, selection,selectionArgs);
if(count>0){
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
return 0;
}
private String getTableName(Uri uri) {
String tableName = null;
switch (mMatcher.match(uri)){
case User_Code:
tableName = DbHelp.USER_TABLE_NAME;
break;
}
return tableName;
}
}
DbHelp代碼如下
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class DbHelp extends SQLiteOpenHelper {
// 資料庫名
private static final String DATABASE_NAME = "finch.db";
// 表名
public static final String USER_TABLE_NAME = "user";
//資料庫版本號
private static final int DATABASE_VERSION = 1;
public DbHelp(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
//創建資料庫表
//注意;如果你第一次運行后第二次又改動創建資料陳述句時,并且只改動了屬性,沒有該表名,那么當你再次運行App時會發現會報錯,新改動的屬性不存在
//解決方法:手動將已建好的那個表洗掉,或者洗掉App重新安裝,這樣你改動的屬性才能生效
db.execSQL("CREATE TABLE IF NOT EXISTS "+USER_TABLE_NAME+"(_id INTEGER PRIMARY KEY AUTOINCREMENT,"+" name TEXT,"+"jobs TEXT)");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
第一個應用的AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.gamedemo">
<uses-permission android:name="android.permission.READ_PERSON_DB" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="cn.sch.myprovider.Read"/>
<uses-permission android:name="cn.sch.myprovider.Write"/>
<permission android:name="cn.sch.myprovider.Read"
android:label="Permission for read content provider"
android:protectionLevel="normal"
></permission>
<permission android:name="cn.sch.myprovider.Write"
android:label="Permission for write content provider"
android:protectionLevel="normal"
></permission>
<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/Theme.MyApplication1">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<provider
android:authorities="cn.sch.myprovider"
android:name=".MyProvide"
android:exported="true"
android:multiprocess="false"
android:grantUriPermissions="true"
android:writePermission="cn.sch.myprovider.Write"
android:readPermission="cn.sch.myprovider.Read"
>
</provider>
</application>
</manifest>
第一個應用的build.gradle
plugins {
id 'com.android.application'
}
android {
compileSdk 29
defaultConfig {
applicationId "com.example.gamedemo"
minSdk 21
targetSdk 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.3.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}
模塊contentprovidertest是第二個應用
MainActivity代碼如下
package com.example.contentprovidertest;
import android.Manifest;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = "lzs";
private TextView userTv;
private Button btn_query2;
private Button btn_insert2;
private Button btn_delete2;
private Button btn_update2;
private EditText xuhao2;
private EditText xingming2;
private EditText zhiye2;
private int id;
private String name;
private String job;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.userTv = findViewById(R.id.id_tv);
//動態獲取權限
if(ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)==PackageManager.PERMISSION_GRANTED
||ActivityCompat.checkSelfPermission
(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)==PackageManager.PERMISSION_GRANTED) {
init(); //初始化控制元件
}else {
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE},0x10);
}
}
private void init() {
xuhao2 = findViewById(R.id.xuhao2);
xingming2 = findViewById(R.id.xingming2);
zhiye2 = findViewById(R.id.zhiye2);
btn_query2 = findViewById(R.id.btn_query2);
btn_insert2 = findViewById(R.id.btn_insert2);
btn_delete2 = findViewById(R.id.btn_delete2);
btn_update2 = findViewById(R.id.btn_update2);
btn_query2.setOnClickListener(this);
btn_insert2.setOnClickListener(this);
btn_delete2.setOnClickListener(this);
btn_update2.setOnClickListener(this);
}
@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.btn_query2:
btn_query2();
break;
case R.id.btn_insert2:
btn_insert2();
break;
case R.id.btn_delete2:
btn_delete2();
break;
case R.id.btn_update2:
btn_update2();
break;
}
}
private void btn_update2() {
id = Integer.parseInt(xuhao2.getText().toString());
name = xingming2.getText().toString();
job = zhiye2.getText().toString();
if(!TextUtils.isEmpty(xuhao2.getText())&&!TextUtils.isEmpty(xingming2.getText())&&!TextUtils.isEmpty(zhiye2.getText())){
Uri uri = Uri.parse("content://cn.sch.myprovider/user");
ContentResolver resolver2 = getContentResolver();
ContentValues values2 = new ContentValues();
values2.put("_id", id);
values2.put("name", name);
values2.put("jobs", job);
resolver2.update(uri,values2,"_id="+id,null);
Toast.makeText(MainActivity.this, "更新成功", Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(MainActivity.this,"請填寫完整,不能為空!",Toast.LENGTH_SHORT).show();
}
}
private void btn_delete2() {
id = Integer.parseInt(xuhao2.getText().toString());
if(!TextUtils.isEmpty(xuhao2.getText())){
Uri uri = Uri.parse("content://cn.sch.myprovider/user");
ContentResolver resolver2 = getContentResolver();
resolver2.delete(uri,"_id ="+id,null);
Toast.makeText(MainActivity.this, "洗掉成功", Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(MainActivity.this,"請填寫完整,不能為空!",Toast.LENGTH_SHORT).show();
}
}
private void btn_insert2() {
this.userTv.setText("");
id = Integer.parseInt(xuhao2.getText().toString());
name = xingming2.getText().toString();
job = zhiye2.getText().toString();
if(!TextUtils.isEmpty(xuhao2.getText())&&!TextUtils.isEmpty(xingming2.getText())&&!TextUtils.isEmpty(zhiye2.getText())){
Uri uri = Uri.parse("content://cn.sch.myprovider/user");
// 插入表中資料
ContentValues values2 = new ContentValues();
values2.put("_id", id);
values2.put("name", name);
values2.put("jobs", job);
// 獲取ContentResolver
ContentResolver resolver2 = getContentResolver();
// 通過ContentResolver 根據URI 向ContentProvider中插入資料
resolver2.insert(uri, values2);
// 通過ContentResolver 向ContentProvider中查詢資料
Cursor cursor2 = resolver2.query(uri, new String[]{"_id", "name","jobs"}, null, null, null);
while (cursor2.moveToNext()) {
// 將表中資料全部輸出
this.userTv.append(" 序號:" + cursor2.getInt(0) + " 姓名:" + cursor2.getString(1) +" 作業:"+cursor2.getString(2)+ "\n");
}
Toast.makeText(MainActivity.this,"插入成功",Toast.LENGTH_SHORT).show();
// 關閉游標
cursor2.close();
}else {
Toast.makeText(MainActivity.this,"請填寫完整,不能為空!",Toast.LENGTH_SHORT).show();
}
}
private void btn_query2() {
Uri uri = Uri.parse("content://cn.sch.myprovider/user");
Cursor query = getContentResolver().query(uri, null, null, null, null);
//清空文本,防止重復查詢而多次顯示
if(!TextUtils.isEmpty(this.userTv.getText()))
{
this.userTv.setText("");
}
while (query.moveToNext()) {
int id = query.getInt(0);
String name = query.getString(1);
String job = query.getString(2);
this.userTv.append(" 序號:" + id + " 姓名:" + name +" 作業:"+job+ "\n");
}
query.close();
}
}
MainActivity的activity_main.xml代碼如下
<?xml version="1.0" encoding="utf-8"?>
<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"
android:orientation="vertical"
android:gravity="center">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="50dp"
android:text="第二個應用"
android:textSize="30dp" />
<TextView
android:id="@+id/id_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="250dp"
android:text="" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="2"
android:gravity="center"
android:orientation="vertical">
<EditText
android:id="@+id/xuhao2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:hint="請輸入序號"
android:inputType="number" />
<EditText
android:id="@+id/xingming2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:hint="請輸入姓名"
android:inputType="textPersonName" />
<EditText
android:id="@+id/zhiye2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:hint="請輸入職業"
android:inputType="textPersonName" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="2"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:orientation="horizontal">
<Button
android:id="@+id/btn_query2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="查詢資料" />
<Button
android:id="@+id/btn_insert2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:text="插入資料" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_horizontal"
android:orientation="horizontal">
<Button
android:id="@+id/btn_delete2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="洗掉資料" />
<Button
android:id="@+id/btn_update2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:text="更新資料" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
第二個應用的AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.contentprovidertest">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permissions.READ_DATABASE"/>
<uses-permission android:name="android.permissioms.WRITE_DATABASE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="cn.sch.myprovider.Read"/>
<uses-permission android:name="cn.sch.myprovider.Write"/>
<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/Theme.MyApplication1">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
第二個應用的build.gradle
plugins {
id 'com.android.application'
}
android {
compileSdk 29
defaultConfig {
applicationId "com.example.contentprovidertest"
minSdk 21
targetSdk 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.3.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}
如果又遇到啥問題,可以留言,一起來解決,
到此所有代碼展示完畢,希望你們喜歡,覺得不錯的可以給我個贊哈,嘿嘿,
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/332118.html
標籤:其他
下一篇:Hilt部分筆記
