Android笔记之ContentProvider与Service

使用内容提供者ContentProvider实现数据的共享

学习的内容:

  •     内置的内容提供者;
  •     自定义的内容提供者;
  •     Content URI含义。

Android的系统是基于Linux的,文件访问权限控制很严格,不同的用户启动不同的应用。

内置的内容提供者:(可自定义)

  • 多媒体音频文件
  • 视频文件
  • 图片
  • 联系人
  • 电话记录
  • 短信访问

Content URI:(识别寻找内容提供者)

    Android平台内容资源定位符,是一种URL,全球唯一。    

  • 协议名字
  • 权限
  • 路径
  • id

通过下面Content URI获取系统资源:联系人、电话、短信、音视频、图片。

访问联系人信息:

//创建SimpleCursorAdapter游标适配器对象
simpleCursorAdapter = new SimpleCursorAdapter(
                this, 
                R.layout.listitem,
                null, //使用CursorLoader不需要游标对象了
                new String[]{ContactsContract.Contacts._ID,ContactsContract.Contacts.DISPLAY_NAME},
                new int[]{R.id.textview_no, R.id.textview_name},
                CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER //游标适配器注册内容监听器,监听游标内容变化
                );

创建CursorLoader对象:构造方法API:

CursorLoader(context context, //上下文对象
             Uri uri,                    //内容提供者URI
             String [] projection,       //要查询的字段名的String数组
             String [] selection,         //查询条件
             String [] selectionArgs,     //查询条件的参数
             String sortOrder             //排序字段
            )

普通权限和运行时权限(包括Android6.0及其之后)

普通权限:

不会导致危险的操作,只需要在AndroidManifest.xml中注册就可以

AndroidManifest.xml被打包成APK,所以称为安装时授权。

网址:权限网址

<uses-permission android:name = “android.permission.INTERNET”>

运行时权限:

运行时权限称为危险权限,由用户同意或者在应用中进行设置

网址:权限网址

1.代码ActivityCompat.checkSelfPermission()方法检查是否授权

2.代码ActivityCompat.requestPermissions()方法请求授权

  • getContentResolver()返回ContentResolve对象(内容提供者的代理对象)
  • ContentResolver提供对共享数据的insert()/delete()/query()/update()

query()方法API定义如下:

Cursor query(Uri uri,
            String [] projection,
            String selection,
            String selectionArgs,
            String sortOrder)

访问电话、短信:

    //创建CursorLoader时调用
    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        //创建CursorLoader对象
        return new CursorLoader(this, CONTENT_URI, null, null, null, null);
    }

    //加载数据完成时调用
    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor c) {
        //采用新的游标与老游标交换,老游标不关闭
        simpleCursorAdapter.swapCursor(c);
    }

    //CursorLoader对象被重置时调用
    @Override
    public void onLoaderReset(Loader<Cursor> loader) {
        //采用新的游标与老游标交换,老游标不关闭
        simpleCursorAdapter.swapCursor(null);
    }

Service服务: 应用不与用户交互,在后台处理任务,并且仍然能运行其他应用。服务在Android中是一种长生命周期的后台运行组件,且无界面。

例如媒体播放程序,后台运行仍可以播放歌曲

创建服务:

    1.编写组件类

    2.在AndroidManifest.xml文件注册

public class MyService extends Service{

    Public IBinder onBind(Intent intent){
    }

    Public void onCreate(){
    }

    Public void onDestroy(){
    }

    Public int onStartCommand(Intent intent, int flags, int startId){
    }

}

注册:

<service
    android:name=”.MyService” //name属性名字
    android:enabled =”true” //服务是否能被系统实例化
    Android:exported=”true”/> //服务能否能够被其他应用启动

注:不要隐式意图启动服务

服务的分类:

    1.启动类型服务:

  • 活动、组件通过startService()启动服务,服务立即处于启动状态
  • 松耦合关系,服务执行单一操作,不将结果返回给调用方

    2.绑定类型服务:

  • 活动、组件通过bindService()绑定服务,服务立即处于“绑定”状态
  • 提供一个C/S接口,能够与服务进行交互、发送请求、返回数据,甚至可以通过进程间的通信跨进程操作
  • 高耦合关系,多个组件可以同时绑定到该服务,全部取消绑定后,该服务会被销毁

启动服务的类型:(活动或者服务,一旦启动服务就不再管服务了,是一种松耦合的关系)

启动服务的生命周期:

    两个嵌套循环:

    整个生命周期的循环:

  •         通过startService()方法并传递意图对象来启动服务
  •         系统根据意图查找这个服务
  •         系统调用服务的onCreate()
  •         接着是onStartCommand()方法:启动组件数据(意图传递给服务)
  •         开始运行服务后,在其他组件调用stopService()或当前服务调用stopself()
  •         服务销毁时调用onDetory():释放资源

    有效生命周期的循环:

  •         在onStartCommand()与onDestroy()调用之间
  •         组件多次启动会调用onStartCommand()

三个方法:

  • onCreate():    第一次创建服务时调用该方法,在onStartCommand()之前
  • onStartCommand():启动组件调用StartService()请求服务时,系统调用此方法
  • onDestroy()                服务不再使用时,释放资源

实例启动类型服务:

  • 创建启动服务:(extends Service)
  • 注册服务:(略)

启动组件代码:

//启动服务
Intent serviceIntent = new Intent(MainActivity.this,MyService.class);

startService(serviceIntent);

//停止服务
Intent serviceIntent = new Intent(MainActivity.this,MyService.class);

stopService(serviceIntent);

绑定类型服务:

    绑定服务生命周期:

    整个生命周期的循环:

  •         通过bindService()方法
  •         系统调用服务的onCreate()
  •         接着是onBind()方法:
  •         所有的绑定接触系统调用onUnbind()方法
  •         服务销毁时调用onDetory():释放资源

     有效生命周期的循环:

  •         在onBind()与onUnbind()调用之间

四个方法:

  • onCreate()
  • onBind():  绑定服务成功,系统调用此方法,必须返回IBinder接口类型对象,客户端与服务端的通信
  • onUnbind():所有客户端通过调用unbindService()解除绑定
  • onDestroy()

实例:绑定类型服务

  • 创建启动服务:(extends Service)
  • 启动组件代码:
//启动服务
Intent serviceIntent = new Intent(this,BinderService.class);

bindService(intent,mConnection,Context.BIND_AUTO_CREATE);

//停止服务
unbindService(mConnection);

总结:

  1. 被启动的服务的生命周期:如果一个Service被某个Activity 调用 Context.startService 方法启动,那么不管是否有Activity使用bindService绑定或unbindService解除绑定到该Service,该Service都在后台运行。如果一个Service被startService 方法多次启动,那么onCreate方法只会调用一次,onStart将会被调用多次(对应调用startService的次数),并且系统只会创建Service的一个实例(因此你应该知道只需要一次stopService调用)。该Service将会一直在后台运行,而不管对应程序的Activity是否在运行,直到被调用stopService,或自身的stopSelf方法。当然如果系统资源不足,android系统也可能结束服务。
  2.  被绑定的服务的生命周期:如果一个Service被某个Activity 调用 Context.bindService 方法绑定启动,不管调用 bindService 调用几次,onCreate方法都只会调用一次,同时onStart方法始终不会被调用。当连接建立之后,Service将会一直运行,除非调用Context.unbindService 断开连接或者之前调用bindService 的 Context 不存在了(如Activity被finish的时候),系统将会自动停止Service,对应onDestroy将被调用。
  3. 被启动又被绑定的服务的生命周期:如果一个Service又被启动又被绑定,则该Service将会一直在后台运行。并且不管如何调用,onCreate始终只会调用一次,对应startService调用多少次,Service的onStart便会调用多少次。调用unbindService将不会停止Service,而必须调用 stopService 或 Service的 stopSelf 来停止服务。
  4. 当服务被停止时清除服务:当一个Service被终止(1、调用stopService;2、调用stopSelf;3、不再有绑定的连接(没有被启动))时,onDestroy方法将会被调用,在这里你应当做一些清除工作,如停止在Service中创建并运行的线程。

注意:

  1. 你应当知道在调用 bindService 绑定到Service的时候,你就应当保证在某处调用 unbindService 解除绑定(尽管 Activity 被 finish 的时候绑定会自      动解除,并且Service会自动停止);
  2. 你应当注意 使用 startService 启动服务之后,一定要使用 stopService停止服务,不管你是否使用bindService;
  3. 同时使用 startService 与 bindService 要注意到,Service 的终止,需要unbindService与stopService同时调用,才能终止 Service,不管 startService 与 bindService 的调用顺序,如果先调用 unbindService 此时服务不会自动终止,再调用 stopService 之后服务才会停止,如果先调用 stopService 此时服务也不会终止,而再调用 unbindService 或者 之前调用 bindService 的 Context 不存在了(如Activity 被 finish 的时候)之后服务才会自动停止;
  4. 当在旋转手机屏幕的时候,当手机屏幕在“横”“竖”变换时,此时如果你的 Activity 如果会自动旋转的话,旋转其实是 Activity 的重新创建,因此旋转之前的使用 bindService 建立的连接便会断开(Context 不存在了),对应服务的生命周期与上述相同。
  5. 在 sdk 2.0 及其以后的版本中,对应的 onStart 已经被否决变为了 onStartCommand,不过之前的 onStart 任然有效。这意味着,如果你开发的应用程序用的 sdk 为 2.0 及其以后的版本,那么你应当使用 onStartCommand 而不是 onStart。

生命周期方法说明:

onStartCommand() 
当另一个组件(如 Activity)通过调用 startService() 请求启动服务时,系统将调用此方法。一旦执行此方法,服务即会启动并可在后台无限期运行。 如果您实现此方法,则在服务工作完成后,需要由您通过调用 stopSelf() 或 stopService() 来停止服务。(如果您只想提供绑定,则无需实现此方法。)

onBind() 
当另一个组件想通过调用 bindService() 与服务绑定(例如执行 RPC)时,系统将调用此方法。在此方法的实现中,您必须通过返回 IBinder 提供一个接口,供客户端用来与服务进行通信。请务必实现此方法,但如果您并不希望允许绑定,则应返回 null。

onCreate() 
首次创建服务时,系统将调用此方法来执行一次性设置程序(在调用 onStartCommand() 或 onBind() 之前)。如果服务已在运行,则不会调用此方法。

onDestroy() 
当服务不再使用且将被销毁时,系统将调用此方法。服务应该实现此方法来清理所有资源,如线程、注册的侦听器、接收器等。 这是服务接收的最后一个调用。

IntentService:(特殊的服务类)

IntentService优势:

  1. 创建默认工作线程,用于在主线程之后执行传递给onStartCommand()所有意图
  2. 创建工作队列,将意图传递给onHandleIntent()方法来实现
  3. 处理完所有启动请求后自动停止服务,不需要调用stopSelf()方法
  4. 提供onBind()的默认实现,返回NUll
  5. 提供了onStartCommand()默认实现,将意图依次发送到工作队列和onHandleIntent()实现。

IntentService与Service比较

多次启动普通服务,则会引起ANR问题,启动IIntentService则不会出现

普通服务:

public class MyService extends Service {

    private static String TAG = "MyService";

    @Override
    public IBinder onBind(Intent intent) {

        return null;
    }

    @Override
    public void onCreate() {

        Log.v(TAG, "调用onCreate...");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        Log.v(TAG, "调用onStartCommand... startId = " + startId);
        synchronized (this) {

            try {
                wait(5 * 1000);
                stopSelf();
            } catch (Exception e) {
            }
        }

        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {

        Log.v(TAG, "调用onDestroy...");
    }
}

IIntentService:

public class MyIntentService extends IntentService {

    private static String TAG = "MyIntentService";

    public MyIntentService() {
        super("MyIntentService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {//不是主线程,不会ANR
        Log.v(TAG, "调用onHandleIntent...");

        synchronized (this) {
            try {
                wait(5 * 1000);
            } catch (Exception e) {

            }
        }
    }

    @Override
    public void onDestroy() {//不需要重写
        super.onDestroy();
        Log.v(TAG, "调用onDestroy...");

    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值