Content Provider 介绍
Content Provider属于Android应用程序的组件之一,作为应用程序的组件之一,作为应用程序之间唯一的共享数据的途径,Content Provider为存储和读取数据提供了统一的接口。Content Provider主要的功能就是存储并检索数据以及向其他应用程序提供访问数据的接口。Android系统为一些常见的数据类型(如音乐、视频、图像、手机通讯录联系人信息等)内置了一系列的Content Provider,这些都位于android.provider包下。持有特定的许可,可以在自己开发的应用程序中,可以在自己开发的应用程序中访问这些Content Provider,应用程序可以实现数据共享让自己的数据和其他应用程序共享
让自己的数据和其他应用程序共享有两种方式:
创建自己的Content Provider(即继承ContentProvider子类)将自己的数据添加到已有的Content Provider中去
后者需要保证现有的Content Provider和自己的数据类型相同且具有该Content Provider的写入权限
数据模型
Content Provider将其存储的数据以数据表形式提供给访问者,在数据表中,每一行为一条记录,每一列为具有特定类型和意义的数据。每一条数据记录都包括一个”ID“数值字段,该字段标识一条数据
访问Content Provider中的数据:
访问Content Provider中的数据主要ContentResolver对象,ContentResolver可以用来对Content Provider中的数据进行查询query()、插入insert()、修改update()和删除delete()等操作,以查询为例,查询一个Content Provider需要掌握如下的信息:
唯一标识Content Provider的URI需要访问的数据字段名称该数据字段的数据类型
查询Content Provider的方法有两个:ContentResolver的query()和Activity对象的managedQuery()
提供的函数
query()查询,insert()插入,update()更新,delete()删除,getType()得到数据 类型,onCreate()创建时的回调函数
实现过程
定义一个CONTENT_URI常量
定义一个类,继承Content Provider
实现query(),delete(),update(),insert(),onCreate(),getType()方法
在自己创建的模块的AndroidManifest.xml中创建权限
<permission android:name="myDB.permossion" android:protectionLevel="normal"></permission>
|
在AndroidManifest中申请权限
<uses-permission android:name="myDb.permisson"></uses-permission>
|
db 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"> <uses-permission android:name="myDb.permisson"></uses-permission>
<application android:allowBackup="true" android:dataExtractionRules="@xml/data_extraction_rules" android:fullBackupContent="@xml/backup_rules" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.MyApplication" tools:targetApi="31"> <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> <activity android:name=".SubActivity02"> </activity> <activity android:name=".SubActivity03"> </activity> <service android:name=".service.MyService01">
</service> <service android:name=".service.MyBindService">
</service> <receiver android:name=".MyReceiver.MyReceiver" android:exported="false"> <intent-filter android:priority="10"> <action android:name="guolvRuleaaa"> </action> </intent-filter> </receiver> <receiver android:name=".MyReceiver.OrderReceiver01" android:exported="false"> <intent-filter android:priority="1000"> <action android:name="guolvRuleaaa">
</action> </intent-filter>
</receiver> <receiver android:name=".MyReceiver.OrderReceiver02" android:exported="false"> <intent-filter android:priority="500"> <action android:name="guolvRuleaaa">
</action> </intent-filter> </receiver> <receiver android:name=".MyReceiver.OrderReceiver03" android:exported="false"> <intent-filter android:priority="200"> <action android:name="guolvRuleaaa">
</action> </intent-filter> </receiver> </application> </manifest>
|
DBHelper.java
package a.b.c.db2;
import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper;
import androidx.annotation.Nullable;
public class DBHelper extends SQLiteOpenHelper { private static final String DBNAME = "myDbName.db"; private static final int VERSION = 1; public static final String TABLE_USER = "user";
public DBHelper(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) { super(context, DBNAME, factory, VERSION); }
@Override public void onCreate(SQLiteDatabase sqLiteDatabase) { String sqlStr = "CREATE TABLE IF NOT EXISTS " + TABLE_USER+ "(uid INTERGER PRIMARY KEY AUTOINCREMENT,"+ "name VARCHAR(30),"+ "age INTERGER,"+ "score DOUBLE)"; sqLiteDatabase.execSQL(sqlStr);
}
@Override public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
} }
|
MyProvider.java
package a.b.c.db2;
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; import android.text.TextUtils; import android.util.Log;
import androidx.annotation.NonNull; import androidx.annotation.Nullable;
public class MyProvider extends ContentProvider {
private static final UriMatcher uriMacher; private static final String AUTHRITY_PROVIDER = "a.b.c.db2.authority"; private static final int CODE_PROVIDER_USER = 11; private DBHelper dbHelper; private SQLiteDatabase db; static { uriMacher = new UriMatcher(UriMatcher.NO_MATCH); uriMacher.addURI(AUTHRITY_PROVIDER,DBHelper.TABLE_USER,CODE_PROVIDER_USER); } @Override public boolean onCreate() { dbHelper = new DBHelper(getContext(),"",null,1); db = dbHelper.getWritableDatabase(); db.execSQL("insert into "+DBHelper.TABLE_USER+" values(1,'张三',19,87)" ); db.execSQL("insert into "+DBHelper.TABLE_USER+" values(2,'李四',18,87)" ); return true; } @Nullable @Override public Cursor query(@NonNull Uri uri, @Nullable String[] strings, @Nullable String s, @Nullable String[] strings1, @Nullable String s1) { return null; } @Nullable @Override public String getType(@NonNull Uri uri) { return ""; }
public String getTableName(Uri uri) { String tableName = ""; if(uriMacher.match(uri)==CODE_PROVIDER_USER) { tableName = DBHelper.TABLE_USER; } return tableName; }
@Nullable @Override public Uri insert(@NonNull Uri uri, @Nullable ContentValues contentValues) { String tableName = getTableName(uri); if(TextUtils.isEmpty(tableName)) { return null; } long insertCount = db.insert(tableName,null,contentValues); if(insertCount>0) { Log.i("MyProvider","insert ok"); } else { Log.i("MyProvier","insert fail"); } return uri; } @Override public int delete(@NonNull Uri uri, @Nullable String s, @Nullable String[] strings) { String tableName = getTableName(uri); if(TextUtils.isEmpty(tableName)) { return 0; } int deleteCount = db.delete(tableName,s,strings); if(deleteCount>0) { Log.i("MyProvider","delete ok"); } else { Log.i("MyProvider","delete fail"); } return deleteCount; } @Override public int update(@NonNull Uri uri, @Nullable ContentValues contentValues, @Nullable String s, @Nullable String[] strings) { String tableName = getTableName(uri); if(TextUtils.isEmpty(tableName)) { return 0; } int updateCount = db.update(tableName,contentValues,s,strings); if(updateCount > 0) { Log.i("MyProvider","update ok"); } else { Log.i("MyProvider","updata fail"); } return updateCount; } }
|
四大组件汇总代码
MainActivity.java
package a.b.c.myapplication; import android.annotation.SuppressLint; import android.app.Activity; import android.content.ComponentName; import android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.util.Log; import android.view.View; import android.widget.Button;
import androidx.activity.EdgeToEdge; import androidx.activity.result.ActivityResult; import androidx.activity.result.ActivityResultCallback; import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.contract.ActivityResultContract; import androidx.activity.result.contract.ActivityResultContracts; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; import androidx.core.graphics.Insets; import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat;
import a.b.c.myapplication.MyReceiver.MyReceiver; import a.b.c.myapplication.MyReceiver.OrderReceiver01; import a.b.c.myapplication.MyReceiver.OrderReceiver02; import a.b.c.myapplication.MyReceiver.OrderReceiver03; import a.b.c.myapplication.service.MyBindService; import a.b.c.myapplication.service.MyService01; public class MainActivity extends AppCompatActivity { Button btn_start,btn_startForResult; Button btn_startService,btn_stopService; Button btn_binService,btn_unBindService; Button btn_sendBroadcast,btn_orderBroadcast; MyBindService.MyBinder myBinder; String logtag="qqqqqq"; Button btn_add,btn_del,btn_update,btn_search; int uid = 40; static final Uri uri = Uri.parse("content://a.b.c.db.authority/user");
@SuppressLint("MissingInflatedId") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); EdgeToEdge.enable(this); setContentView(R.layout.activity_main); ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> { Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()); v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom); return insets; }); btn_start = findViewById(R.id.btn_startActivity); btn_start.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(MainActivity.this, SubActivity02.class); startActivity(intent); } }); ActivityResultLauncher launcher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() { @Override public void onActivityResult(ActivityResult result) { Log.i(logtag,result.getData().getStringExtra("key1")); } }); btn_startForResult = findViewById(R.id.btn_startActivityGetResult); btn_startForResult.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(MainActivity.this,SubActivity03.class);
launcher.launch(intent); } }); btn_startService = findViewById(R.id.btn_startService); btn_startService.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(MainActivity.this, MyService01.class); startService(intent); } }); btn_stopService = findViewById(R.id.btn_stopService); btn_stopService.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(MainActivity.this, MyService01.class); stopService(intent); } }); ServiceConnection conn = new ServiceConnection() { @Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) { if(iBinder instanceof MyBindService.MyBinder) { myBinder = (MyBindService.MyBinder) iBinder; } }
@Override public void onServiceDisconnected(ComponentName componentName) {
Log.i(logtag, "onServiceDisconnected"); } }; btn_binService = findViewById(R.id.btn_bindService); btn_binService.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(MainActivity.this,MyBindService.class); bindService(intent,conn, Context.BIND_AUTO_CREATE); } }); btn_unBindService = findViewById(R.id.btn_unbindService); btn_unBindService.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(MainActivity.this, MyBindService.class); try { unbindService(conn); } catch (Exception e) { e.printStackTrace(); } } }); btn_sendBroadcast = findViewById(R.id.btn_broadcast); btn_sendBroadcast.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intetnt = new Intent(MainActivity.this, MyReceiver.class); intetnt.setAction("guolvRuleaaa"); intetnt.putExtra("key2","这是无序广播内容1"); sendBroadcast(intetnt); } });
OrderReceiver01 orderReceiver01 = new OrderReceiver01(); OrderReceiver02 orderReceiver02 = new OrderReceiver02(); OrderReceiver03 orderReceiver03 = new OrderReceiver03(); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction("guolvRuleaaa"); registerReceiver(orderReceiver01, intentFilter); registerReceiver(orderReceiver02,intentFilter); registerReceiver(orderReceiver03,intentFilter);
btn_orderBroadcast = findViewById(R.id.btn_orderBroadcast); btn_orderBroadcast.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(); intent.setAction("guolvRuleaaa"); String data = "这是原始数据"; Bundle extData = new Bundle();
sendOrderedBroadcast(intent,null,new MyReceiver(),null,0,data,extData); } }); btn_add = findViewById(R.id.btn_add); btn_add.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { ContentValues values = new ContentValues(); values.put("uid",uid++); values.put("name","王五"); values.put("age","20"); values.put("socre","78"); ContentResolver contentResolver = getContentResolver(); contentResolver.insert(uri,values); } }); btn_del = findViewById(R.id.btn_del); btn_del.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { ContentResolver contentResolver = getContentResolver(); int delCount = contentResolver.delete(uri,"uid> ?",new String[]{"4"}); if(delCount > 0) { Log.i(logtag,"del Count: " + delCount); } } }); btn_update = findViewById(R.id.btn_update); btn_update.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { ContentValues values = new ContentValues();
values.put("age","20"); ContentResolver contentResolver = getContentResolver(); int updateCount = contentResolver.update(uri,values,"uid=?",new String[]{"3"}); if(updateCount>0) { Log.i(logtag,"updata Count"+updateCount); }
} }); btn_search = findViewById(R.id.btn_search); btn_search.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { ContentResolver contentResolver = getContentResolver(); Cursor cursor = contentResolver.query(uri,new String[]{"uid","name","age","score"},null,null,null); if(cursor==null) { return ; } while(cursor.moveToNext()) { @SuppressLint("Range") int uid = cursor.getInt(cursor.getColumnIndex("uid")); @SuppressLint("Range") String name = cursor.getString(cursor.getColumnIndex("name")); @SuppressLint("Range") int age = cursor.getInt(cursor.getColumnIndex("age")); @SuppressLint("Range") int score= cursor.getInt(cursor.getColumnIndex("score")); Log.i(logtag,"uid="+uid+",name="+name+",age="+age+",score="+score);
}
} }); } }
|
Activity生命周期
activity三种状态:
(1)active:当Activity运行在屏幕前台(处于当前任务活动栈的最上面),此时它获取了焦点能响应用户的操作,属于活动状态,同一个时刻只会有一个Activity处于活动(Active)。
(2)paused:当Activity失去焦点但仍对用户可见(如在它之上有另一个透明的Activity或Toast、AlertDialog等弹出弹窗时)它处于暂停状态。暂停的Activity仍然是存活状态(它保留者所有的状态和成员信息并保持窗口管理器的连接),但是在系统内存极小时可以被系统杀掉。
(3)stopped:完全被另一个Activity遮挡时处于停止状态,它仍然在内存中保留着所有的状态和成员信息。这是对用户不可见,当其他地方需要内存时它往往被系统杀掉。
Activity七个方法
(1)onCreate():在Activity创建时调用,通常做一些初始化设置,不可见,只在Activity创建时执行一次
(2)onStart():在Activity即将可见时调用,可见,在Activity中多次调用,不在前台,不可交互,初始化工作
(3)onResume:在Activity获取焦点开始与用户交互时调用,在前台,开启动画和独占设备
(4)onPause():在当前Activity被其它Activity覆盖或锁屏时调用,可见,程序状态的保持,独占设备和动画的关闭,以及一些数据的保存最好在onPause中进行,但不能太耗时
(5)onStop():在Activity对用户不可见时调用,不可见,其对象还在内存中,系统内存不足时可能不会执行onStop()方法
(6)onDestroy():在Activity销毁时调用
(7)onRestart():在Activity从停止状态再次启动时调用
android三个嵌套循环
(1)Activity完整的生命周期:从第一次调用onCreate()开始直到调用onDestroy()结束。
(2)Activity的可视生命周期:从调用onStart()到相应的调用onStop()。在这两个方法之间,可以保持显示Activity所需要的资源。如在onStart()注册一个广播接收者监听影响你的UI的改变,在onStop()中注销。
(3)Activity的前台生命周期:从调用onResume()到相应的调用onPause()。
Service的生命周期
Service的完整生命周期从调用onCreate()开始知道调用onDestroy()结束。
Service有两种使用方法:
(1)以调用Context.startService()启动,而以调用Context.stopService结束。这种情况下的Service是通过其他组件调用startService()被创建。这种service方法可以无限地运行下去,必须调用stopSelf()方法或者其他组件调用stopService()来停止它,当service被停止时,系统会销毁它
(2)以调用Context.bindService()方法建立,以调用Context.unbindService()关闭。这种情况下的Service时通过其他组件(一个客户)调用unbindService()方法来关闭这种连接。一个service可以同时和多个客户绑定,当多个客户都解除绑定之后,系统会销毁service。
BroadcastReceive广播接收器生命周期
生命周期只有十秒左右,如果在onReceive()内做超过十秒内的事情,就会报ANR(Application No Response)程序无响应的错误信息。它的生命周期为从回调onReceive()方法开始到该方法返回结果后结束
一个activity的启动过程
每一个Activity都处于某一个状态,对于开发者来说,是无法控制其应用程序处于某一个状态的,这些均由系统来完成。
(1)第一个Activity的启动顺序:onCreate()->onStart()->onResume()
(2)当另一个Activity启动时:第一个Activity onPause()->第二个Activity onCreate()->onStart()->onResume()->第一个Activity onStop();
(3)当返回到第一个Activity时:第二个Activity onPause()->第一个Activity onRestart()->onStart()->onResume()->第二个Activity onStop()->onDestroy()