Articles of android contentprovider

主细节使用ContentResolver.applyBatch()?

我想知道是否可以在同一操作中使用android.content.ContentResolver.applyBatch()方法将主和详细记录保存到内容提供者,其中providers参数中的后续ContentProviderOperation项取决于先前项的结果。 我遇到的问题是,当调用ContentProviderOperation.newInsert(Uri)方法并且Uri是不可变的时,实际的Uri是未知的。 我想出的内容如下所示: Uri大师:内容://com.foobar.masterdetail/master 细节Uri:内容://com.foobar.masterdetail/master/#/detail ArrayList operations = new ArrayList(); operations.add(ContentProviderOperation.newInsert(intent.getData()) .withValue(Master.NAME, “”) .withValue(Master.VALUE, “”) .build()); operations.add(ContentProviderOperation.newInsert(intent.getData() .buildUpon() .appendPath(“#”) /* ACTUAL VALUE NOT KNOWN UNTIL MASTER ROW IS SAVED */ .appendPath(“detail”) .build()) .withValue(Detail.MASTER_ID, /* WHAT GOES HERE? */) .withValue(Detail.NAME, “”) .withValue(Detail.VALUE, “”) .build()); ContentProviderResult[] results = this.getContentResolver().applyBatch(MasterDetail.AUTHORITY, operations); for (ContentProviderResult result : results) { Uri […]

房间持久性库和内容提供商

最近几天我一直在花时间学习新的Android架构组件 。 在跟进了一些博客文章,文档和教程后,每个组件都变得清晰。 但突然间,我意识到我们的老朋友内容提供商 。 我可能听起来很傻,因为在写这个问题之前我花了很长时间搜索,我是唯一一个提出这个问题的人。 我没有任何有用的解决方案。 无论如何,如果我想用本地数据库建立一个应用程序,我现在显然会选择新的架构组件(实时数据,视图模型,房间),而不需要进一步思考,这将非常有助于使应用程序10x健壮。 但是如果我希望我的数据库数据可以访问其他应用程序,例如To Widget如何将Content Provider与Room集成?

Android ContentProvider getType()调用的时间和原因

我在getType()方法中记录了一个永远不会被打印的日志。 我正在使用记事本示例代码。 请解释Java doc评论的第1行。 从getType()返回null也正常工作。 getType()方法的目的是什么? /** * This is called when a client calls {@link android.content.ContentResolver#getType(Uri)}. * Returns the MIME data type of the URI given as a parameter. * * @param uri The URI whose MIME type is desired. * @return The MIME type of the URI. * @throws IllegalArgumentException if the incoming […]

Android联系人提供商仅获取所有电子邮件的电话联系人

我需要获取所有手机联系人及其电子邮件地址和照片uri: 这就是我在做什么: private void getContacts() { ContentResolver cr = getContentResolver(); Cursor cur = cr.query(Contacts.CONTENT_URI, null, null, null, Contacts.DISPLAY_NAME); if (cur.getCount() > 0) { while (cur.moveToNext()) { // if // (Integer.parseInt(cur.getString(cur.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) // > 0) { Contact contact = new Contact(); String id = cur.getString(cur.getColumnIndex(ContactsContract.Contacts._ID)); Uri uri = getContactPhotoUri(Long.parseLong(id)); // set photoUri contact.setContactPhotoUri(uri); // set name contact.setContactName(cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME))); […]

在ContentProvider中使用rawQuery是一个好习惯吗?

我正在使用我的自定义ContentProvider与sqlite数据库进行通信。 我想在列表(使用ListFragment)上显示来自两个表(具有多对多关系)的数据。 我能想到的唯一解决方案就是使用rawQuery。 问题是,如果这是一个好习惯,还是应该以其他方式解决这个问题? 表格示例: 表A:ID,COLUMN_FROM_A 表B:ID,COLUMN_FROM_B 连接表AB:ID,FK_ID_A,FK_ID_B ContentProvider中重写的查询方法示例: @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder(); Cursor cursor = null; int uriType = URIMatcher.match(uri); switch (uriType) { case TABLE_A_URI: queryBuilder.setTables(“TABLE_A”); cursor = queryBuilder.query(databaseHelper.getReadableDatabase(), projection, selection, selectionArgs, null, null, sortOrder); break; case TABLE_B_URI: queryBuilder.setTables(“TABLE_B”); […]

数据库处理有2个进程

我有一个有2个部分的应用程序。 创建内容的服务。 使用内容的应用程序 每个都作为不同的进程运行。 问题是它们都共享一个数据库。 当服务尝试写入某些内容并且UI正在读取数据时,我经常会遇到数据库锁定错误。 反之亦然。 怎么办呢? 用于访问DB的类是单例类。 但由于UI和服务都是两个不同的过程,我认为有两个单身。 所以这没有用。 因为2个不同的过程,即使是synchronise也无济于事。 Content Providers可能是一个选项,但由于我使用复杂的查询来挖掘信息,因此也很难使用它。 如何让两个进程共享数据库。 任何提示将不胜感激。

API Level <11的Cursor.getType()

我正在查询CallLog内容提供程序,需要检测列types。 在Honeycomb和更新版本(API Level 11+)中,您可以通过调用Cursor.getType(int columnIndex)方法获取列首选数据types,该方法返回以下types之一: FIELD_TYPE_NULL(0) FIELD_TYPE_INTEGER(1) FIELD_TYPE_FLOAT(2) FIELD_TYPE_STRING(3) FIELD_TYPE_BLOB(4) 如何在Honeycomb <11设备上实现这一目标? 我尝试过以下方法: for ( int i = 0; i < cursor.getColumnCount(); i++ ) { int columnType = -1; try { cursor.getInt( i ); columnType = Cursor.FIELD_TYPE_INTEGER; } catch ( Exception ignore ) { try { cursor.getString( i ); columnType = Cursor.FIELD_TYPE_STRING; } catch ( […]

cursor.setNotificationUri()用于什么?

我在本教程中研究了如何使用ContentProviders和Loaders 我怎么看:我们有一个ListView , SimpleCursorAdapter和CursorLoader的Activity 。 我们还实现了ContentProvider 。 在一个Activity我们可以调用getContentResolver().insert(URI, contentValues); 点击按钮。 在我们的ContentProvider实现中,在insert()方法的末尾,我们调用getContentResolver().notifyChange(URI, null); 我们的CursorLoader将收到消息,它应该重新加载数据并更新UI。 此外,如果我们在SimpleCursorAdapter使用FLAG_REGISTER_CONTENT_OBSERVER ,它也将接收消息,并且将调用其onContentChanged()方法。 因此,如果我们插入,更新或删除数据,我们的ListView将会更新。 Activity.startManagingCursor(cursor); 不推荐使用cursor.requery() ,所以我没有看到cursor.setNotificationUri()任何实践意义。 我查看了setNotificationUri()方法的源代码,发现它在方法中调用了mContentResolver.registerContentObserver(mNotifyUri, true, mSelfObserver) 。 CursorLoader也是这样做的。 最后,游标将接收消息,并在Cursor内部调用以下方法: protected void onChange(boolean selfChange) { synchronized (mSelfObserverLock) { mContentObservable.dispatchChange(selfChange, null); // … } } 但我无法理解这一点。 所以我的问题是: 我们为什么要在ContentProvider实现的query()方法中调用cursor.setNotificationUri() ?

Android / SQLite:插入 – 更新表列以保留标识符

目前,我使用以下语句在Android设备上的SQLite数据库中创建表。 CREATE TABLE IF NOT EXISTS ‘locations’ ( ‘_id’ INTEGER PRIMARY KEY AUTOINCREMENT, ‘name’ TEXT, ‘latitude’ REAL, ‘longitude’ REAL, UNIQUE ( ‘latitude’, ‘longitude’ ) ON CONFLICT REPLACE ); 最后的conflict-clause导致在完成具有相同坐标的新插入时删除行。 SQLite文档包含有关conflict-clause的更多信息。 相反,我想保留以前的行,只是更新他们的列。 在Android / SQLite环境中执行此操作的最有效方法是什么? 作为CREATE TABLE语句中的conflict-clause。 作为INSERT触发器。 作为ContentProvider#insert方法中的条件子句。 ……你能想到的更好 我认为在数据库中处理这种冲突更有效。 此外,我发现很难重写ContentProvider#insert方法来考虑插入更新方案。 这是insert方法的代码: public Uri insert(Uri uri, ContentValues values) { final SQLiteDatabase db = mOpenHelper.getWritableDatabase(); long […]

如何在同一设备上运行的Android应用程序之间传输文件?

我正在编写一个与RESTful服务接口的Android应用程序。 此Web服务基本上是文件系统的前端,并提供元数据以及对文件的CRUD访问。 我的应用程序检索元数据,并通过ContentProvider将其公开给第三方应用程序。 我需要添加第三方应用程序的能力,在与我的应用程序相同的设备上运行,通过向我/我的应用程序发送请求(而不是直接与服务器)来CRUD实际文件。 这意味着他们需要通过我的应用程序发送或接收文件的内容(通常是XML或图像)。 我想到了实现这个的两种方法: 选项1 – 使用ContentProvider.openFile 这似乎是让第三方应用程序能够从我的ContentProvider读取文件的明显选择。 我认为当这些应用程序需要通过我的`ContentProvider’创建或更新文件时,它开始变得棘手。 完成后我需要回调才能知道何时将新的/更改的文件发送回服务器。 我相信我可以为此目的使用FileObserver 。 选项2 – 通过服务使用Messenger 通过这种方法,我可以通过Messenger在我的应用程序和客户端应用程序之间发送文件。 这些文件必须通过Bundle传递,所以我不确定传输它们的最佳格式是什么( File , FileDescriptor ,byte array,还有其他什么?)。 如果文件变得很大,我不能很好地处理这会导致问题。 选项3 – 混合方法 将外部存储上的文件夹用作下拉框 通过Messenger / Service传达CRUD请求和删除框内容 使用ContentProvider存储请求的状态 第三方应用通过ContentObserver接收状态更新 概要 我认为使用ContentProvider将是理想的解决方案,但似乎API并不完全支持我的用例。 我担心尝试沿着这条路走下去可能会导致一个愚蠢的实施。 如果我使用Messenger和Service方法,我不确定通过Bundle传输文件的最强大的方法。 混合方法似乎非常强大,但实现起来最复杂。 文件实际上并没有被传递,因此性能应该很好。 但是,我担心这会过度设计解决方案。 在同一Android设备上运行的应用程序之间传输文件的最佳方法是什么? 当然,我对我在问题中没有概述的其他选项持开放态度。