目录
有序广播:按照广播的优先级接受,broadcastReceiver可以在onReceive中使用abortBroastcast()终止广播下传
本地广播:只在本应用内接收得到,需将exported置为false
粘留广播:Api21后已经废弃了,其作用是可以在发出广播之后注册的接收器仍然可以接收到广播
有兴趣可以看前面的Activity介绍:https://blog.csdn.net/wzhworld/article/details/83443862
一、BroadcastReceiver
详见:https://blog.csdn.net/carson_ho/article/details/52973504
1、定义
- BroadcastReceiver,本质上是一个全局的监听器,属于Android四大组件之一。主要扮演角色是发送者以及接收者
2、作用
- 广播主要可以用于不同组件、App之间的通信
3、生命周期
- onReceive进行接收广播之后的广播处理
public class mBroadcastReceiver extends BroadcastReceiver {
//接收到广播后自动调用该方法
@Override
public void onReceive(Context context, Intent intent) {
//写入接收广播后的操作
}
}
4、广播注册方式
-
动态注册
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//实例化BroadcastReceiver子类 & IntentFilter
mBroadcastReceiver mBroadcastReceiver = new mBroadcastReceiver();
IntentFilter intentFilter = new IntentFilter();
//设置接收广播的类型
intentFilter.addAction(android.net.conn.CONNECTIVITY_CHANGE);
//调用Context的registerReceiver()方法进行动态注册
registerReceiver(mBroadcastReceiver, intentFilter);
}
//注册广播后,要在相应位置记得销毁广播
//即在onDestroy()中unregisterReceiver(mBroadcastReceiver)
@Override
protected void onDestroy() {
super.onDestroy();
//销毁在onCreate()方法中的广播
unregisterReceiver(mBroadcastReceiver);
}
}
-
静态注册
- 首先在manifest中注册
<receiver //此广播接收者类是MyBroadcastReceiver android:name=".MyBroadcastReceiver" > //用于接收网络状态改变时发出的广播 <intent-filter> <action android:name="android.net.conn.CONNECTIVITY_CHANGE" /> </intent-filter> </receiver>
后在自定义的BroadcastReceiver的onReceive进行处理即可,注意静态注册的广播需要进行一定的处理,因为在Android中为了防止恶意攻击之类,不可以随便定义静态注册,所以简单的上述代码的注册可能会接收不到广播,可以加上包名的设定,详见https://blog.csdn.net/u011386173/article/details/82889275
intent.setPackage(getPackageName());
- 首先在manifest中注册
5、广播类型
-
普通广播:即发出广播后所有接收者都能收
<receiver
//此广播接收者类是MyBroadcastReceiver
android:name=".MyBroadcastReceiver" >
//用于接收网络状态改变时发出的广播
<intent-filter>
<action android:name="ANY_ACTION" />
</intent-filter>
</receiver>
Intent intent = new Intent();
intent.setAction("ANY_ACTION");
sendBroadcase(intent);
-
有序广播:按照广播的优先级接受,broadcastReceiver可以在onReceive中使用abortBroastcast()终止广播下传
sendOrderedBroadcast(intent);
abortBroastcast();
-
系统广播:系统的广播,如电量、锁屏等
-
本地广播:只在本应用内接收得到,需将exported置为false
-
//注册应用内广播接收器 //步骤1:实例化BroadcastReceiver子类 & IntentFilter mBroadcastReceiver myBroadcastReceiver = new MyBroadcastReceiver(); IntentFilter intentFilter = new IntentFilter(); //步骤2:实例化LocalBroadcastManager的实例 localBroadcastManager = LocalBroadcastManager.getInstance(this); //步骤3:设置接收广播的类型 intentFilter.addAction(android.net.conn.CONNECTIVITY_CHANGE); //步骤4:调用LocalBroadcastManager单一实例的registerReceiver()方法进行动态注册 localBroadcastManager.registerReceiver(myBroadcastReceiver , intentFilter); //取消注册应用内广播接收器 localBroadcastManager.unregisterReceiver(myBroadcastReceiver ); //发送应用内广播 Intent intent = new Intent(); intent.setAction(BROADCAST_ACTION); localBroadcastManager.sendBroadcast(intent);
粘留广播:Api21后已经废弃了,其作用是可以在发出广播之后注册的接收器仍然可以接收到广播
6、返回值
-
不同注册方式的onReceive中Context返回值是不一样的
-
对于静态注册(全局+应用内广播),回调onReceive(context, intent)中的context返回值是:ReceiverRestrictedContext;
-
对于全局广播的动态注册,回调onReceive(context, intent)中的context返回值是:Activity Context;
-
对于应用内广播的动态注册(LocalBroadcastManager方式),回调onReceive(context, intent)中的context返回值是:Application Context。
-
对于应用内广播的动态注册(非LocalBroadcastManager方式),回调onReceive(context, intent)中的context返回值是:Activity Context;
-
二、ContentProvider
1、定义
内容提供者,实现应用内、应用间建数据共享https://blog.csdn.net/carson_ho/article/details/76101093
2、URI
3、使用
- 自定义的ContentProvider类:ContentProvider的数据一般是以"数据库"或"网络数据"的方式存储的。如果是数据库,则需要实现SQLiteOpenHelper类。通过SQLiteOpenHelper类新建/管理数据库。
- 我们需要以继承ContentProvider的方式自定义ContentProvider时,需要实现query(), insert(), update(), delete(), getType(), onCreate()这六个函数。
- 创建表格
// 创建表格的SQL语句 private static final String SQL_CREATE_ENTRIES = "CREATE TABLE " + Entry.TABLE_NAME + " (" + Entry._ID + " INTEGER PRIMARY KEY," + Entry.NAME + " TEXT NOT NULL, " + Entry.BIRTH_DAY + " TEXT, " + Entry.EMAIL + " TEXT, " + Entry.GENDER + " INTEGER " + " )"; ... private class DBLiteHelper extends SQLiteOpenHelper { public static final int DATABASE_VERSION = 1; public static final String DATABASE_NAME = "MyProvider.db"; public DBLiteHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL(SQL_CREATE_ENTRIES); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } }
在创建时execSQL语句创建数据库
- 注册Uri
// Uri的authority public static final String AUTHORITY = "com.skw.myprovider"; // Uri的path public static final String PATH = "table01"; // UriMatcher中URI对应的序号 public static final int ITEM_ALL = 1; public static final int ITEM_ID = 2; private static final UriMatcher URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH); static { URI_MATCHER.addURI(AUTHORITY, PATH, ITEM_ALL); URI_MATCHER.addURI(AUTHORITY, PATH+"/#", ITEM_ID); }
注册Uri的目的是为了添加侦听,将Uri注册到UriMatcher中,AUTHORITY需要与manifest中的android:authorities相同一致
- delete()、insert()、update()、query()这几个方法都是相同类似的操作,如果底层使用的是Sqlite,那么增删查改其实就是对于这四个的封装,到这里不禁就要思考问啥不直接使用sqlite要加一层ContentProvider这么麻烦了。设想一下,假如当需要数据从网络取而不是从数据库取得,那么底层的取数据操作我们又要重新实现一遍,这很不合理,通过CP的提供接口而不关心底层实现,当需要变动了无需改动过多。
- Manifest注册
<provider android:name=".MyProvider" android:authorities="上述定义的协议" />
- 对ContentProvider进行操作时,我们使用的是ContentResolver而不是CP,目的是为了统一封装接口对应用内、应用外使用
ContentResolver cr = new ContentResolver(); cr.insert(...); cr.query(...); cr.delete(...); cr.query(...);
详细使用可见https://blog.csdn.net/carson_ho/article/details/76101093
- 跨应用使用后续待修改,与权限应用相关
三、Service
1、定义
运行在后台不直接与用户交互的,比如可开启线程作网络操作等
2、生命周期
https://blog.csdn.net/carson_ho/article/details/53160137
此处应该注意的是startService与bindService的区别,start后Service无法控制。而bindService启动后可通信,通过Binder
3、PS
-
startService()和stopService()只能开启和关闭Service,无法操作Service;
-
bindService()和unbindService()可以操作Service
-
startService开启的Service,调用者退出后Service仍然存在;
-
BindService开启的Service,调用者退出后,Service随着调用者销毁
4、Service类型
可见https://www.jianshu.com/p/e04c4239b07e
- 本地服务:即正常使用只在主线程运作
- 远程服务:跑在独立进程,需使用AIDL进行IPC操作
- 前台服务:结合Notification显示在通知栏的
- 后台服务:处于后台如更新天气此类
- 详见上述的网址,讲得比较详细
5、IntentService
待后续补充,这个Service通常是用来做耗时的操作,其底层实现是通过Handler、Thread实现耗时,在onHandleIntent接收到Intent识别判断类型后可以操作