四大组件

四大组件

标签(空格分隔):Activity ContentProvider BroadcastReceiver Service Android


一. ContentProvider

1. 如何实现ContentProvider

  1. 继承自抽象类ContentProvider实现一系列针对于数据的增、删、改、查等方法。
  2. 需要在AndroidMainfest.xml中完成对ContentProvider的注册
<provider 
        android:name=".MyProvider"
        android:authorities:"com.excavator.myprovider.provider">
</provider>

注:注册的authorities属性值是全局唯一的。

2.何为URI

URI指通用资源标识符

  • content://com.excavator.myprovider.provider/contacts/#
    第一部分:前缀表明数据受控于一个内容提供者。它从不修改,也就是schema
    第二部分:是指在AndroidMainfest.xml中我们注册的provider中的android:authorities属性所对应的。
    第三部分:具体操作于哪个条目
    第四部分:具体指定到哪个条目下的哪条记录(#标识通配符)

3.UriMatcher类

  • UriMatcher matcher=new UriMatcher(UriMatcher.NO_MATCH);
    UriMatcher.NO_MATCH表示不匹配任何路径的返回码
  • mathcher.addURI(“com.excavator.myprovider.provider”,”table1”,1);
    UriMatcher为一个Uri的容器,容器里面包含着我们即将可能要操作的Uri
    如果通过match()方法匹配成功就返回code值
  • matcher.match(uri)
    首先通过addURI()方法添加进来的Uri匹配
    匹配成功则返回设置的code值,反之,返回一个UriMatcher.NO_MATCH常量(-1)

4.ContentResolver

  • 使用ContentResolver操作ContentProvider中的数据
    当外部应用需要对ContentProvider中的数据进行添加、删除、修改和查询时,可以使用ContentResolver类来完成
    使用Activity提供的getContentResolver()方法获取ContentResolver对象
  • ContentResolver类提供了与ContentProvider类相同签名的方法
    • public Uri insert(Uri uri,ContentValues values)
      该方法用于往ContentProvider添加数据
    • public int delete(Uri uri,String selection,String[] selectionArgs)
      该方法用于从ContentProvider删除数据
    • public int update(Uri uri,ContentValues values,String selection,String[] selectionArgs)
      该方法用于更新ContentProvider中的数据
    • public Cursor query(Uri uri,String[] projection,String selection,String[] selectionArgs,String sortOrder)
      该方法用于从ContentProvider中获取数据
  1. 使用系统提供的ContentProvider
    • 查询联系人
    • 增加联系人
    • 短信的读取
    • 通话记录
    • 多媒体 图片 视频 音频
    • 。。。
  2. 使用自定义的ContentProvider
    • 自定义

源代码

package com.excavator.contentproviderdemo;
import android.app.Activity;
import android.content.ContentResolver;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.ContactsContract.CommonDataKinds.Email;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.Contacts;
import android.util.Log;


public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ContentResolver contentResolver = getContentResolver();
        Cursor cursor=contentResolver.query(Contacts.CONTENT_URI, new String[]{Contacts._ID, Contacts.DISPLAY_NAME}, null, null, null);
        if (cursor!=null){
            while (cursor.moveToNext()) {
                int id=cursor.getInt(cursor.getColumnIndex(Contacts._ID));
                Log.i("info", "_id:" + id);
                Log.i("info", "name:" + cursor.getString(cursor.getColumnIndex(Contacts.DISPLAY_NAME)));
                Cursor cursor1=contentResolver.query(Phone.CONTENT_URI, new String[]{Phone.NUMBER, Phone.TYPE}, Phone.CONTACT_ID + "=" + id, null, null);
                //根据联系人ID查询出联系人的电话号码
                if (cursor1!=null){
                    while (cursor1.moveToNext()) {
                        int type=cursor1.getInt(cursor1.getColumnIndex(Phone.TYPE));
                        if (type==Phone.TYPE_HOME) {
                            Log.i("info", "家庭电话:" + cursor1.getString(cursor1.getColumnIndex(Phone.NUMBER)));
                        }else if (type==Phone.TYPE_MOBILE){
                            Log.i("info", "手机号:" + cursor1.getString(cursor1.getColumnIndex(Phone.NUMBER)));
                        }
                    }
                    cursor1.close();
                }
                //根据联系人的ID去查询联系人的邮箱地址
                Cursor cursor2 = contentResolver.query(Email.CONTENT_URI, new String[]{Email.DATA, Email.TYPE}, Email.CONTACT_ID + "=" + id, null, null);
                if (cursor2!=null){
                    while (cursor2.moveToNext()) {
                        int type = cursor2.getInt(cursor2.getColumnIndex(Email.DATA));
                        if (type==Email.TYPE_WORK){
                            Log.i("info", "工作邮箱:" + cursor2.getString(cursor2.getColumnIndex(Email.DATA)));
                        }
                    }
                    cursor2.close();
                }
            }
            cursor.close();
        }
    }
}
package com.excavator.contentproviderdemo2;

import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.RawContacts;

public class MainActivity extends Activity {
    Uri uri;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ContentResolver contentResolver = getContentResolver();
        //向联系人中插入一行数据
        ContentValues contentValues = new ContentValues();
        uri = contentResolver.insert(RawContacts.CONTENT_URI, contentValues);
        Long raw_contact_id = ContentUris.parseId(uri);
        contentValues.clear();
        //插入人名
        contentValues.put(StructuredName.RAW_CONTACT_ID, raw_contact_id);
        contentValues.put(StructuredName.DISPLAY_NAME,"张三");
        contentValues.put(StructuredName.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
        uri = contentResolver.insert(Data.CONTENT_URI,contentValues);
        //插入电话信息
        contentValues.clear();
        contentValues.put(Phone.RAW_CONTACT_ID, raw_contact_id);
        contentValues.put(Phone.NUMBER, "123456789");
        contentValues.put(Phone.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
        uri = contentResolver.insert(Data.CONTENT_URI, contentValues);
    }
}

二. BroadcastReceiver

Broadcast(广播): 是一种广泛运用在应用程序之间传输信息的机制。
BroadcastReceiver(广播接收器): 是对发送出来的广播进行过滤接收并响应的一类组件,它就是用来接收来自系统和应用中的广播。

1.使用方法

  • 发送:
    • 把信息装入一个Intent对象(如Action、Category)
    • 通过调用相应的方法将Intent对象以广播方式发送出去
      sendBraodcast()
      sendOrderBroadcast()
      sendStickyBroadcast()
  • 接收:

    当Intent发送以后,所有已经注册的BroadcastReceiver会检查注册时的IntentFilter是否与发送的Intent匹配,若匹配则就会调用BroadcastReceiver的onReceive()方法。所以当我们定义一个BroadcastReceiver时,都需要实现onReceive()方法。
    注意:
    BroadcastReceiver需要注册
    静态注册
    代码注册


注意!!!
  • BroadcastReceiver生命周期只有十秒左右
  • 在BroadcastReceiver里不能做一些比较耗时的操作
  • 耗时操作应该通过发送Intent给Service,由Service来完成
  • 不能使用子线程

2.广播的种类及使用

  • 普通广播(Normal broadcast)
    所有监听该广播的广播接收者都可以监听到该广播
    • 同级别接收先后是随机的(无序)。
    • 级别低的后接收到广播。
    • 接收器不能截断广播的继续传播也不能处理广播。
    • 同级别动态注册高于静态注册。
  • 有序广播(Ordered broadcast)
    按照接收者的优先级顺序接收广播,优先级别在intent-filter中的priority中声明,-1000到1000之间,值越大,优先级越高。可以终止广播意图的继续传播。接收者可以篡改内容。
    • 同级别接收顺序是随机的。
    • 能截断广播的继续传播,高级别的广播接收器收到该广播后,可以决定把该广播是否截断。
    • 接收器能截断广播的继续传播,也能处理广播。
    • 同级别动态注册高于静态注册。
  • 异步广播(粘滞性滞留广播)
    不能将处理结果传给下一个接收者,无法终止广播。

发送标准广播代码:

Intent intent = new Intent();
intent.putExtra("msg","这是一条普通广播");
intent.setAction("BC_One");
sendBroadcast(intent);

接收器代码实现:

package com.excavator.broadcastreceiverdemo;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class BC1 extends BroadcastReceiver {
    public BC1() {
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        // TODO: This method is called when the BroadcastReceiver is receiving
        // an Intent broadcast.
        String s = intent.getStringExtra("msg");
        System.out.println("receiver1接收到消息:"+s);
    }
}

静态注册代码:

<receiver
            android:name=".BC1"
            android:enabled="true"
            android:exported="true" >
            <intent-filter>
                <action android:name="BC_One" />
            </intent-filter>
        </receiver>

动态注册代码:

IntentFilter intentFilter = new IntentFilter("BC_One");
BC2 bc2 = new BC2();
registerReceiver(bc2, intentFilter);

注意:动态注册的最后需要在onDestroy()方法中调用unregisterReceiver()方法卸载掉
发送有序广播:

Intent intent2 = new Intent();
intent2.putExtra("msg","这是一条有序广播");
intent2.setAction("BC_One");
sendOrderedBroadcast(intent2, null);

发送异步广播:

Intent intent3 = new Intent();
intent3.putExtra("msg", "这是一条有序广播");
intent3.setAction("BC_Three");
sendStickyBroadcast(intent3);

//先发送后注册
IntentFilter intentFilter = new IntentFilter("BC_Three");
BC3 bc3 = new BC3();
registerReceiver(bc3,intentFilter);

最后需要在清单文件中加权限

<uses-permission android:name="android.permission.BROADCAST_STICKY"/>

三. Service

定义:

  • 后台运行,不可见,没有界面
  • 优先级高于Activity

用途:

  • 播放音乐、记录地理信息位置的改变、监听某种动作

注意:

  • 运行在主线程,不能用来做耗时的请求或者动作
  • 可以在服务中开一个线程,在线程中做耗时动作

类型:

  • 本地服务(Local Service)
    • 应用程序内部
    • startService stopService stopSelf stopSelfResult
    • bindService unbingService
  • 远程服务(Remote Service)
    • Android系统内部的应用程序之间
    • 定义IBind接口

Service生命周期:

Service-lifecycle

Start方式特点:

  • 服务跟启动源(活动)没有任何联系
  • 无法得到服务对象

Bind方式特点:

  • 通过Ibinder接口实例,返回一个ServiceConnection对象给启动源
  • 通过ServiceConnection对象的相关方法可以得到Service对象

MyStartService.java

public class MyStartService extends Service {
    public MyStartService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        Log.i("info","Service--onBind");
        return null;
    }

    @Override
    public void onCreate() {
        Log.i("info","Service--onCreate");
        super.onCreate();
    }

    @Override
    public void onDestroy() {
        Log.i("info","Service--onDestroy");
        super.onDestroy();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i("info","Service--onStartCommand");
        return super.onStartCommand(intent, flags, startId);
    }
}

注意:onCreate()方法是在服务第一创建时调用,而onStartCommand()方法则在每次启动服务时都会调用,第一次启动服务时,由于服务此时还未创建,所以两个方法都会执行,之后启动服务只会有onSartCommand()方法得到执行。

MyBindService.java

public class MyBindService extends Service {

    public MyBindService() {
    }

    //在活动新建一个继承自Binder的类,然后在里面提供各种方法
    public class MyBinder extends Binder{
        public MyBindService getService() {
            return MyBindService.this;
        }
    }

    //在onBind()中返回实例
    @Override
    public IBinder onBind(Intent intent) {
        Log.i("info", "BindService--onBind");
        return new MyBinder();
    }

    @Override
    public void onCreate() {
        Log.i("info","BindService--onCreate");
        super.onCreate();
    }

    @Override
    public void onDestroy() {
        Log.i("info","BindService--onDestroy");
        super.onDestroy();
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.i("info", "BindService--onUnbind");
        return super.onUnbind(intent);
    }

    public void Play() {
        Log.i("info","播放");
    }

    public void Pause() {
        Log.i("info","暂停");
    }

    public void Previous() {
        Log.i("info","上一首");
    }

    public void Next() {
        Log.i("info","下一首");
    }
}

MainActivity.java

public class MainActivity extends Activity {

    Intent intent1;
    Intent intent2;
    MyBindService service;

    ServiceConnection conn=new ServiceConnection() {

        //当启动源跟Service成功连接之后会自动调用这个方法
        @Override
        public void onServiceConnected(ComponentName name, IBinder binder) {
            service=((MyBindService.MyBinder) binder).getService();
        }

        //当启动源跟Service连接意外丢失会调用这个方法
        //比如Service崩溃或者被强行杀死
        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void doClick(View v){
        switch (v.getId()){
            case R.id.start:
                intent1 = new Intent(MainActivity.this, MyStartService.class);
                startService(intent1);
                break;
            case R.id.stop:
                stopService(intent1);
                break;
            case R.id.bind:
                intent2 = new Intent(MainActivity.this,MyBindService.class);
                bindService(intent2,conn,Service.BIND_AUTO_CREATE);
                break;
            case R.id.play:
                service.Play();
                break;
            case R.id.pause:
                service.Pause();
                break;
            case R.id.next:
                service.Next();
                break;
            case R.id.previous:
                service.Previous();
                break;
            case R.id.unbind:
                unbindService(conn);
                break;
            default:
                break;
        }
    }
}

四.Activity

Activity

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值