涉及文件:

frameworks\base\core\java\android\content\pm\PackageParser.java

frameworks\base\core\java\android\app\ContextImpl.java

frameworks\base\core\java\android\app\ActivityThread.java

frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java

frameworks\base\core\java\android\content\ContentResolver.java

frameworks\base\core\java\android\content\ContentProvider.java

 

contentProvider使用示例:

Manifest文件中定义provider,指定authorities,permission,权限还可以细分为readpermission和writepermission。

新建类继承自ContentProvider,重载query,insert,delete,update四个接口,分别实现数据库的增删改查

public class HealthProvider extends ContentProvider {private final static String TAG = "HealthProvider:";private DbHelper dbHelper;private static final UriMatcher matcher;static {    matcher = new UriMatcher(UriMatcher.NO_MATCH);    matcher.addURI(DbConstant.AUTHOR,DbConstant.TB_FATIGUE,DbConstant.CODE_FATIGUE);    matcher.addURI(DbConstant.AUTHOR,DbConstant.TB_HEALTH_REPORT,DbConstant.CODE_HEALTH_REPORT);    matcher.addURI(DbConstant.AUTHOR,DbConstant.TB_SLEEP,DbConstant.CODE_SLEEP);    matcher.addURI(DbConstant.AUTHOR,DbConstant.TB_TIME_SET,DbConstant.CODE_TIME);    matcher.addURI(DbConstant.AUTHOR,DbConstant.TB_SCREEN,DbConstant.CODE_SCREEN);}@Overridepublic boolean onCreate() {    dbHelper = new DbHelper(getContext());    return true;}@Nullable@Overridepublic Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection,                    @Nullable String[] selectionArgs, @Nullable String sortOrder) {    String table = getType(uri);    SQLiteDatabase database = dbHelper.getReadableDatabase();    if(table==null || database==null) {        return null;    }    Cursor cursor = database.query(table,projection,selection,selectionArgs,null,null,sortOrder);    return cursor;}@Nullable@Overridepublic String getType(@NonNull Uri uri) {    String table = null;    switch (matcher.match(uri)) {        case DbConstant.CODE_FATIGUE:            table = DbConstant.TB_FATIGUE;            break;        case DbConstant.CODE_HEALTH_REPORT:            table = DbConstant.TB_HEALTH_REPORT;            break;        case DbConstant.CODE_SLEEP:            table = DbConstant.TB_SLEEP;            break;        case DbConstant.CODE_TIME:            table = DbConstant.TB_TIME_SET;            break;        case DbConstant.CODE_SCREEN:            table = DbConstant.TB_SCREEN;            break;        default:            break;    }    return table;}@Nullable@Overridepublic Uri insert(@NonNull Uri uri, @Nullable ContentValues contentValues) {    String table  = getType(uri);    SQLiteDatabase database = dbHelper.getWritableDatabase();    database.insert(table,null,contentValues);    return uri;}@Overridepublic int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {    String table = getType(uri);    SQLiteDatabase database = dbHelper.getWritableDatabase();    int i = database.delete(table,selection,selectionArgs);    return 0;}@Overridepublic int update(@NonNull Uri uri, @Nullable ContentValues contentValues, @Nullable String selection,                  @Nullable String[] selectionArgs) {    String table = getType(uri);    SQLiteDatabase database = dbHelper.getWritableDatabase();    int i = database.update(table,contentValues,selection,selectionArgs);    return 0;}}

新建类继承自SQLiteOpenHelper,分别实现构造方法和onCreate(完成数据库新建操作)、onUpgrade(完成数据库升级)、onDowngrade(完成数据库的降级)

public class DbHelper extends SQLiteOpenHelper {    public static String CREATE_FATIGUE="CREATE TABLE IF NOT EXISTS fatigue(" +            "id INTEGER PRIMARY KEY," +            "total_s INT DEFAULT 0," +            "total_m INT DEFAULT 0," +            "total_mi INT DEFAULT 0," +            "total_f INT DEFAULT 0," +            "unlock_s INT DEFAULT 0," +            "unlock_m INT DEFAULT 0," +            "unlock_mi INT DEFAULT 0," +            "unlock_f INT DEFAULT 0," +            "app_s INT DEFAULT 0," +            "app_m INT DEFAULT 0," +            "app_mi INT DEFAULT 0," +            "app_f INT DEFAULT 0" +            ");";    public static final String CREATE_SLEEP = "CREATE TABLE IF NOT EXISTS sleep_data(" +            "id INTEGER PRIMARY KEY," +            "start_time INTEGER DEFAULT 0," +            "end_time INTEGER DEFAULT 0," +            "sleep_time INTEGER DEFAULT 0," +            "weekdata VARCHAR(50) DEFAULT NULL," +            "modify_time LONG);";    public static final String CREATE_TIME = "CREATE TABLE IF NOT EXISTS time_data(" +            "id INTEGER PRIMARY KEY," +            "notice_enable INTEGER DEFAULT 1," +            "device_oneday LONG DEFAULT 28800000," +            "device_once LONG DEFAULT 7200000," +            "app_once LONG DEFAULT 7200000" +            ");";    public static final String CREATE_SCREEN = "CREATE TABLE IF NOT EXISTS screen_data(" +            "id INTEGER PRIMARY KEY," +            "modify_date LONG," +            "screen_on LONG," +            "screen_off LONG," +            "screen_on_off_duration INTEGER" +            ");";    public static final String DROP_FATIGUE = "drop table fatigue";    public static final String DROP_SLEEP = "drop table sleep_data";    public static final String DROP_TIME = "drop table time_data";    public static final String DROP_SCREEN = "drop table screen_table";    public DbHelper(Context cn) {        super(cn, DbConstant.DATABASE, null, DbConstant.DB_VERSION);    }    public DbHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {        super(context, DbConstant.DATABASE, factory, DbConstant.DB_VERSION);    }    @Override    public void onCreate(SQLiteDatabase sqLiteDatabase) {        sqLiteDatabase.execSQL(CREATE_FATIGUE);        sqLiteDatabase.execSQL(CREATE_SLEEP);        sqLiteDatabase.execSQL(CREATE_TIME);        sqLiteDatabase.execSQL(CREATE_SCREEN);    }    @Override    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {        db.execSQL(DROP_FATIGUE);        db.execSQL(DROP_SLEEP);        db.execSQL(DROP_TIME);        onCreate(db);    }    @Override    public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {        db.execSQL(DROP_FATIGUE);        db.execSQL(DROP_SLEEP);        db.execSQL(DROP_TIME);        onCreate(db);    }}

以上就完成了数据库的准备工作,需要使用数据库时如下调用即可:

ContentResolver cr = context.getContentResolver();Uri uri = Uri.parse(UriStr);//uri组成:content://+manifest中定义的authorities+/+数据库表名Cursor cursor = cr.query(uri,null,null,null,null);ArrayList list = new ArrayList<>();if(cursor == null) {    return list;}while(cursor.moveToNext()) {    SleepData data = new SleepData();    data.setStartTime(cursor.getInt(cursor.getColumnIndexOrThrow("start_time")));    data.setEndTime(cursor.getInt(cursor.getColumnIndexOrThrow("end_time")));    data.setSleepTime(cursor.getInt(cursor.getColumnIndexOrThrow("sleep_time")));    data.setDate(cursor.getString(cursor.getColumnIndexOrThrow("weekdata")));    data.setModifyTime(cursor.getLong(cursor.getColumnIndexOrThrow("modify_time")));    list.add(data);}

query调用流程如下图:

ContentProvider使用与query流程分析_第1张图片

通过调用contentresolver获得需要读写的数据库的provider的代理对象,获取过程分为当前进程下的和跨进程的获取,如果跨进程,并且对应进程当前并没有在后台中,

则会启动该进程,然后再考虑从该进程的activitythread中获取安装的provider对象,然后在这个代理对象上进行增删改查的操作。

 

query方法如下:获得cursor指针主要查看ActivithThread中acquireProvider方法

public final @Nullable Cursor query(final @RequiresPermission.Read @NonNull Uri uri,        @Nullable String[] projection, @Nullable Bundle queryArgs,        @Nullable CancellationSignal cancellationSignal) {    Preconditions.checkNotNull(uri, "uri");    IContentProvider unstableProvider = acquireUnstableProvider(uri);    if (unstableProvider == null) {        return null;    }    IContentProvider stableProvider = null;    Cursor qCursor = null;    try {        long startTime = SystemClock.uptimeMillis();        //......        try {            qCursor = unstableProvider.query(mPackageName, uri, projection,                    queryArgs, remoteCancellationSignal);        } catch (DeadObjectException e) {            //如果进程不存在的情况下            unstableProviderDied(unstableProvider);            stableProvider = acquireProvider(uri);            if (stableProvider == null) {                return null;            }            qCursor = stableProvider.query(                    mPackageName, uri, projection, queryArgs, remoteCancellationSignal);        }        if (qCursor == null) {            return null;        }        // Force query execution.  Might fail and throw a runtime exception here.        qCursor.getCount();        long durationMillis = SystemClock.uptimeMillis() - startTime;        maybeLogQueryToEventLog(durationMillis, uri, projection, queryArgs);        // Wrap the cursor object into CursorWrapperInner object.        final IContentProvider provider = (stableProvider != null) ? stableProvider                : acquireProvider(uri);        final CursorWrapperInner wrapper = new CursorWrapperInner(qCursor, provider);        stableProvider = null;        qCursor = null;        return wrapper;    } catch (RemoteException e) {        // Arbitrary and not worth documenting, as Activity        // Manager will kill this process shortly anyway.        return null;    } finally {       //......    }}

 

ApplicationContentResolver如下:

 private static final class ApplicationContentResolver extends ContentResolver {    private final ActivityThread mMainThread;    public ApplicationContentResolver(Context context, ActivityThread mainThread) {        super(context);        mMainThread = Preconditions.checkNotNull(mainThread);    }    @Override    protected IContentProvider acquireProvider(Context context, String auth) {        return mMainThread.acquireProvider(context,                ContentProvider.getAuthorityWithoutUserId(auth),                resolveUserIdFromAuthority(auth), true);    }    @Override    protected IContentProvider acquireUnstableProvider(Context c, String auth) {        return mMainThread.acquireProvider(c,                ContentProvider.getAuthorityWithoutUserId(auth),                resolveUserIdFromAuthority(auth), false);    }    //......}

ActivityThread中acquireProvider如下:

public final IContentProvider acquireProvider(        Context c, String auth, int userId, boolean stable) {    //已存在,则直接返回            final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable);    if (provider != null) {        return provider;    }    ContentProviderHolder holder = null;    try {        //同步,保证先到先得        synchronized (getGetProviderLock(auth, userId)) {            holder = ActivityManager.getService().getContentProvider(                    getApplicationThread(), auth, userId, stable);        }    } catch (RemoteException ex) {        throw ex.rethrowFromSystemServer();    }    if (holder == null) {        Slog.e(TAG, "Failed to find provider info for " + auth);        return null;    }    // 安装该provider    holder = installProvider(c, holder, holder.info,            true /*noisy*/, holder.noReleaseNeeded, stable);    return holder.provider;}

AMS中获取方法如下:

private ContentProviderHolder getContentProviderImpl(IApplicationThread caller,        String name, IBinder token, boolean stable, int userId) {    ContentProviderRecord cpr;    ContentProviderConnection conn = null;    ProviderInfo cpi = null;    synchronized(this) {       //无法根据caller查找到对应app,则抛出security异常        boolean checkCrossUser = true;        checkTime(startTime, "getContentProviderImpl: getProviderByName");        // 首先检查该content provider是否已发布        cpr = mProviderMap.getProviderByName(name, userId);        //......        boolean providerRunning = cpr != null && cpr.proc != null && !cpr.proc.killed;        //该provider正在运行        if (providerRunning) {            cpi = cpr.info;            String msg;            checkTime(startTime, "getContentProviderImpl: before checkContentProviderPermission");            //检查调用者是否拥有读取数据库权限,如没有,则抛出异常            if ((msg = checkContentProviderPermissionLocked(cpi, r, userId, checkCrossUser))                    != null) {                throw new SecurityException(msg);            }            checkTime(startTime, "getContentProviderImpl: after checkContentProviderPermission");            if (r != null && cpr.canRunHere(r)) {                //provider存在,并且进程存在,则直接返回                ContentProviderHolder holder = cpr.newHolder(null);                // don't give caller the provider object, it needs                // to make its own.                holder.provider = null;                return holder;            }            // 正常app与instant ap之间不互相暴露            try {                if (AppGlobals.getPackageManager()                        .resolveContentProvider(name, 0 /*flags*/, userId) == null) {                    return null;                }            } catch (RemoteException e) {            }            final long origId = Binder.clearCallingIdentity();            checkTime(startTime, "getContentProviderImpl: incProviderCountLocked");            //......        if (!providerRunning) {            try {                checkTime(startTime, "getContentProviderImpl: before resolveContentProvider");                cpi = AppGlobals.getPackageManager().                    resolveContentProvider(name,                        STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS, userId);                checkTime(startTime, "getContentProviderImpl: after resolveContentProvider");            } catch (RemoteException ex) {            }            if (cpi == null) {                return null;            }            //检查singleton 属性,并且检查调用者权限            //system ready前调用system provider 返回异常            //system providers 未安装,抛出异常            //明确provider归属用户,如果用户管理尚未启动,则不允许该provider运行            if (!mUserController.isUserRunning(userId, 0)) {                Slog.w(TAG, "Unable to launch app "                        + cpi.applicationInfo.packageName + "/"                        + cpi.applicationInfo.uid + " for provider "                        + name + ": user " + userId + " is stopped");                return null;            }            ComponentName comp = new ComponentName(cpi.packageName, cpi.name);            checkTime(startTime, "getContentProviderImpl: before getProviderByClass");            cpr = mProviderMap.getProviderByClass(comp, userId);            checkTime(startTime, "getContentProviderImpl: after getProviderByClass");            final boolean firstClass = cpr == null;            if (firstClass) {                final long ident = Binder.clearCallingIdentity();                // If permissions need a review before any of the app components can run,                // we return no provider and launch a review activity if the calling app                // is in the foreground.                if (mPermissionReviewRequired) {                    if (!requestTargetProviderPermissionsReviewIfNeededLocked(cpi, r, userId)) {                        return null;                    }                }                try {                    checkTime(startTime, "getContentProviderImpl: before getApplicationInfo");                    ApplicationInfo ai =                        AppGlobals.getPackageManager().                            getApplicationInfo(                                    cpi.applicationInfo.packageName,                                    STOCK_PM_FLAGS, userId);                    checkTime(startTime, "getContentProviderImpl: after getApplicationInfo");                    if (ai == null) {                        Slog.w(TAG, "No package info for content provider "                                + cpi.name);                        return null;                    }                    ai = getAppInfoForUser(ai, userId);                    cpr = new ContentProviderRecord(this, cpi, ai, comp, singleton);                } catch (RemoteException ex) {                    // pm is in same process, this will never happen.                } finally {                    Binder.restoreCallingIdentity(ident);                }            }                        //......            //如果provider尚未启动,则拉起它            if (i >= N) {                try {                    // Content provider is now in use, its package can't be stopped.                    // Use existing process if already started                    if (proc != null && proc.thread != null && !proc.killed) {                        if (!proc.pubProviders.containsKey(cpi.name)) {                            try {                                //进程存在后台,未被kill掉,调用该进程,安装provider                                proc.thread.scheduleInstallProvider(cpi);                            } catch (RemoteException e) {                            }                        }                    } else {                        //启动该provider所在进程,指定provider所在component                        proc = startProcessLocked(cpi.processName,                                cpr.appInfo, false, 0, "content provider",                                new ComponentName(cpi.applicationInfo.packageName,                                        cpi.name), false, false, false);                                                    }        //......    }    //等待 provider 发布出来    synchronized (cpr) {        while (cpr.provider == null) {            //......            try {                if (DEBUG_MU) Slog.v(TAG_MU,                        "Waiting to start provider " + cpr                        + " launchingApp=" + cpr.launchingApp);                if (conn != null) {                    conn.waiting = true;                }                cpr.wait();            } catch (InterruptedException ex) {            } finally {                if (conn != null) {                    conn.waiting = false;                }            }        }    }    return cpr != null ? cpr.newHolder(conn) : null;}
private void installContentProviders(        Context context, List providers) {    final ArrayList results = new ArrayList<>();    for (ProviderInfo cpi : providers) {        if (DEBUG_PROVIDER) {            StringBuilder buf = new StringBuilder(128);            buf.append("Pub ");            buf.append(cpi.authority);            buf.append(": ");            buf.append(cpi.name);            Log.i(TAG, buf.toString());        }        //安装provider,通过将该provider加入到mProviderMap队列中        ContentProviderHolder cph = installProvider(context, null, cpi,                false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);        if (cph != null) {            cph.noReleaseNeeded = true;            results.add(cph);        }    }    try {        //将列表中的provider发布到AMS中的mProviderMap下的mSingletonByName队列中        ActivityManager.getService().publishContentProviders(            getApplicationThread(), results);    } catch (RemoteException ex) {        throw ex.rethrowFromSystemServer();    }}
private ContentProviderHolder installProvider(Context context,        ContentProviderHolder holder, ProviderInfo info,        boolean noisy, boolean noReleaseNeeded, boolean stable) {    ContentProvider localProvider = null;    IContentProvider provider;        //参数检查,provider的获取过程    ContentProviderHolder retHolder;    synchronized (mProviderMap) {        IBinder jBinder = provider.asBinder();        if (localProvider != null) {            ComponentName cname = new ComponentName(info.packageName, info.name);            ProviderClientRecord pr = mLocalProvidersByName.get(cname);            //已存在,则世界使用            if (pr != null) {                provider = pr.mProvider;            } else {                holder = new ContentProviderHolder(info);                holder.provider = provider;                holder.noReleaseNeeded = true;                //如果不存在,则将其加入到mProviderMap、 mLocalProviders、mLocalProvidersByName三个队列中                pr = installProviderAuthoritiesLocked(provider, localProvider, holder);                mLocalProviders.put(jBinder, pr);                mLocalProvidersByName.put(cname, pr);            }            retHolder = pr.mHolder;        } else {            ProviderRefCount prc = mProviderRefCountMap.get(jBinder);            if (prc != null) {                if (!noReleaseNeeded) {                    incProviderRefLocked(prc, stable);                    try {                        ActivityManager.getService().removeContentProvider(                                holder.connection, stable);                    } catch (RemoteException e) {                        //do nothing content provider object is dead any way                    }                }            } else {                //加入到mProviderMap队列中                ProviderClientRecord client = installProviderAuthoritiesLocked(                        provider, localProvider, holder);                if (noReleaseNeeded) {                    prc = new ProviderRefCount(holder, client, 1000, 1000);                } else {                    prc = stable                            ? new ProviderRefCount(holder, client, 1, 0)                            : new ProviderRefCount(holder, client, 0, 1);                }                ////加入到mProviderRefCountMap队列中                mProviderRefCountMap.put(jBinder, prc);            }            retHolder = prc.holder;        }    }    return retHolder;}
private ProviderClientRecord installProviderAuthoritiesLocked(IContentProvider provider,        ContentProvider localProvider, ContentProviderHolder holder) {    final String auths[] = holder.info.authority.split(";");    final int userId = UserHandle.getUserId(holder.info.applicationInfo.uid);    if (provider != null) {        // If this provider is hosted by the core OS and cannot be upgraded,        // then I guess we're okay doing blocking calls to it.        for (String auth : auths) {            switch (auth) {                case ContactsContract.AUTHORITY:                case CallLog.AUTHORITY:                case CallLog.SHADOW_AUTHORITY:                case BlockedNumberContract.AUTHORITY:                case CalendarContract.AUTHORITY:                case Downloads.Impl.AUTHORITY:                case "telephony":                    Binder.allowBlocking(provider.asBinder());            }        }    }    final ProviderClientRecord pcr = new ProviderClientRecord(            auths, provider, localProvider, holder);    for (String auth : auths) {        final ProviderKey key = new ProviderKey(auth, userId);        final ProviderClientRecord existing = mProviderMap.get(key);        if (existing != null) {            Slog.w(TAG, "Content provider " + pcr.mHolder.info.name                    + " already published as " + auth);        } else {            mProviderMap.put(key, pcr);        }    }    return pcr;}
public final void publishContentProviders(IApplicationThread caller,        List providers) {    if (providers == null) {        return;    }    enforceNotIsolatedCaller("publishContentProviders");    synchronized (this) {        final ProcessRecord r = getRecordForAppLocked(caller);        if (DEBUG_MU) Slog.v(TAG_MU, "ProcessRecord uid = " + r.uid);        if (r == null) {           //抛出异常        }        final long origId = Binder.clearCallingIdentity();        final int N = providers.size();        for (int i = 0; i < N; i++) {            ContentProviderHolder src = providers.get(i);            if (src == null || src.info == null || src.provider == null) {                continue;            }            ContentProviderRecord dst = r.pubProviders.get(src.info.name);            if (DEBUG_MU) Slog.v(TAG_MU, "ContentProviderRecord uid = " + dst.uid);            if (dst != null) {                ComponentName comp = new ComponentName(dst.info.packageName, dst.info.name);                //加入到mProviderMap类的mSingletonByClass队列中                mProviderMap.putProviderByClass(comp, dst);                String names[] = dst.info.authority.split(";");                for (int j = 0; j < names.length; j++) {                    //加入mProviderMap类的mSingletonByName队列中                    mProviderMap.putProviderByName(names[j], dst);                }                //处理等待启动provider队列,如果启动了,则会从队列中移出                int launchingCount = mLaunchingProviders.size();                int j;                boolean wasInLaunchingProviders = false;                for (j = 0; j < launchingCount; j++) {                    if (mLaunchingProviders.get(j) == dst) {                        mLaunchingProviders.remove(j);                        wasInLaunchingProviders = true;                        j--;                        launchingCount--;                    }                }                if (wasInLaunchingProviders) {                    mHandler.removeMessages(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG, r);                }                synchronized (dst) {                    dst.provider = src.provider;                    dst.proc = r;                    dst.notifyAll();                }                updateOomAdjLocked(r, true);                maybeUpdateProviderUsageStatsLocked(r, src.info.packageName,                        src.info.authority);            }        }        Binder.restoreCallingIdentity(origId);    }}

 

更多相关文章

  1. Android 数据库Sqlite的使用(1)
  2. Android夸进程通信机制九:AIDL深入了解
  3. Android夸进程通信机制三:Messenger与Message
  4. Android夸进程通信机制六:使用ContentProvider进行进程间通信
  5. Android夸进程通信机制八:使用 AIDL进行进程间通信

随机推荐

  1. gravity与layout_gravity的区别
  2. 浅谈Android 动画,带你进入动画的世界
  3. Android(安卓)Network - 架构
  4. Android中资源管理机制详细分析
  5. Android 中Parcelable的作用
  6. 【Android UI设计与开发】第15期:顶部标题
  7. android 6.0运行时权限的申请(微信在andro
  8. android下解析xml文件遇到中文问题
  9. Android 沉浸式状态栏 头部可拉伸带有一
  10. Android NoSQL之SnappyDB