Android Content Provider 基础详解

Android开发核心组件:Content Provider详解与实战 在Android应用开发中,是实现跨应用数据共享的关键组件。它不仅为应用程序之间的数据访问提供了统一的接口规范,还通过标准的URI机制和MIME类型支持实现了资源的抽象化管理。然而,系统提供的MediaStore等内置仅能满足特定场景需求。对于需要暴露私有数据库或自定义数据结构的应用而言,必须实现一个自定义 ContentProvider,并正确重写其生命周期及六大核心抽象方法。本章将深入探讨如何从零开始构建一个功能完整的。 阅读详情

内容提供器(Content Provider)主要用于在不同的应用程序之间实现数据共享的功能,它提供一套完整的机制,允许一个程序访问另一个程序中的数据,同时还能保证被访问程序中的数据安全性。它的用法有两种:1.使用现有的内容提供器来读取或操作相应程序的数据。2.自己创建一个内容提供器给我们程序的数据提供外部访问接口。



1.Content Resolver的基本用法

要想访问内容提供器中共享的数据,就一定要借助ContentResolver类,具体是通过Context的getContentResolver()方法来拿到ContentResolver实例。而利用这个实例的query()、update()、insert()、delete()方法就可以实现对数据的操作。显然这些方法都需要接受一个参数,那就是URI。

这个参数URI被称为内容URI,它由三部分组成:协议声明,内容URI的协议声明写上"content://"即可;权限,通常采用程序包名进行命名,如接下来将举一个例子包名为company.contactstest,权限则命名为company.contactstest.provider;路径,用于对同一程序中的不同表做区分,如/Book,/Category。

上面拿到的URI还不是Uri对象,需要通过解析才能得到对象。Uri uri = Uri.parse("content://company.contactstest.provider/Book")。(括号中即为一个标准的内容URI写法)

关于具体的增删改查方法与SQLiteDatabase类似,我们就在例子中来介绍吧。



2.使用现有的内容提供器

下面通过读取手机通讯录中的联系人来介绍如何使用系统现有的内容提供器。事先在通讯录中随便增加了两个联系人。


然后新建一个ContactsTest项目,并在主活动的布局中简单的放入一个ListView控件,代码略。

package company.contactstest;

import android.database.Cursor;
import android.provider.ContactsContract;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    ListView contactListView;
    ArrayAdapter<String> adapter;
    List<String> contactsList = new ArrayList<String>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        contactListView = (ListView) findViewById(R.id.contacts_list_view);
        adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, contactsList);
        contactListView.setAdapter(adapter);
        readContacts();
    }

    private void readContacts() {
        Cursor cursor = null;
        try {
            cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);

            while (cursor.moveToNext()) {
                String displayName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
                String number = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                contactsList.add(displayName + "\n" + number);
            }
        }catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
    }
}

可以看到,首先准备了ListView的相关代码,都是ListView的基本用法不作过多解释。然后将重点放在我们创建的readContacts方法上。getContentResolver()得到实例,然后调用query()方法,其中传入的第一个参数就是URI,只不过这里是一个系统封装后提供的CONTENT_URI常量,因此不需要再用Uri.parse()方法解析,后面四个参数都传入null就表示我们要查询该表中的所有行且结果无需排序。最后将查询到的结果返回给一个Cursor对象,并且将其中两个数据DISPLAY_NAME和NUMBER都取出来传给contactsList即可显示在ListView上了。




3.创建自己的内容呢提供器

接下来创建一个自己的内容提供器并为我之前一篇SQL的博客建立的项目提供外部接口,这里先打开之前的项目,在里面新建一个DatabaseProvider类并让其继承自ContentProvider,这个父类中有六个抽象方法:onCreate()、qeury()、insert()、update()、delete()、getType(),我们在使用子类继承它的时候需要将这六个方法全部重写。

package geekband.testsql;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.support.annotation.Nullable;

/**
 * Created by samyang on 2016/8/31.
 */
public class DatabaseProvider extends ContentProvider {

    public static final int BOOK_DIR = 0;
    public static final int BOOK_ITEM = 1;
    public static final int CATEGORY_DIR = 2;
    public static final int CATEGORY_ITEM = 3;
    public static final String AUTHORITY = "geekband.testsql.provider";
    private static UriMatcher mUriMatcher;
    private MyDatabaseHelper dbHelper;
    static {
        mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
        mUriMatcher.addURI(AUTHORITY, "book", BOOK_DIR);
        mUriMatcher.addURI(AUTHORITY, "book/#", BOOK_ITEM);
        mUriMatcher.addURI(AUTHORITY, "category", CATEGORY_DIR);
        mUriMatcher.addURI(AUTHORITY, "category/#", CATEGORY_ITEM);
    }

    @Override
    public boolean onCreate() {
        dbHelper = new MyDatabaseHelper(getContext(), "BookStore.db", null, 4);
        return true;
    }

    @Nullable
    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        //查询数据
        SQLiteDatabase db = dbHelper.getReadableDatabase();
        Cursor cursor = null;
        switch (mUriMatcher.match(uri)) {
            case BOOK_DIR:
                cursor = db.query("Book", projection, selection, selectionArgs, null, null, sortOrder);
                break;
            case BOOK_ITEM:
                String bookId = uri.getPathSegments().get(1);
                cursor = db.query("Book", projection, "id = ?", new String[] {bookId}, null, null, sortOrder);
                break;
            case CATEGORY_DIR:
                cursor = db.query("Category", projection, selection, selectionArgs, null, null, sortOrder);
                break;
            case CATEGORY_ITEM:
                String categoryId = uri.getPathSegments().get(1);
                cursor = db.query("Category", projection, "id = ?", new String[]{categoryId}, null, null, sortOrder);
                break;
            default:
                break;
        }
        return cursor;
    }

    @Nullable
    @Override
    public String getType(Uri uri) {
        switch (mUriMatcher.match(uri)) {
            case BOOK_DIR:
                return "vnd.android.cursor.dir/vnd.geekband.testsql.provider.book";
            case BOOK_ITEM:
                return "vnd.android.cursor.item/vnd.geekband.testsql.provider.book";
            case CATEGORY_DIR:
                return "vnd.android.cursor.dir/vnd.geekband.testsql.provider.category";
            case CATEGORY_ITEM:
                return "vnd.android.cursor.item/vnd.geekband.testsql.provider.category";
        }
        return null;
    }

    @Nullable
    @Override
    public Uri insert(Uri uri, ContentValues values) {
        //增加数据
        SQLiteDatabase db = dbHelper.getWritableDatabase();
        Uri uriReturn = null;
        switch (mUriMatcher.match(uri)) {
            case BOOK_DIR:
            case BOOK_ITEM:
                long newBookId = db.insert("Book", null, values);
                uriReturn = Uri.parse("content://" + AUTHORITY + "/book/" + newBookId);
                break;
            case CATEGORY_DIR:
            case CATEGORY_ITEM:
                long newCategoryId = db.insert("Category", null, values);
                uriReturn = Uri.parse("content://" + AUTHORITY + "/category/" + newCategoryId);
                break;
            default:
                break;
        }
        return uriReturn;
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        //删除数据
        SQLiteDatabase db = dbHelper.getWritableDatabase();
        int deleteRows = 0;
        switch (mUriMatcher.match(uri)) {
            case BOOK_DIR:
                deleteRows = db.delete("Book", selection, selectionArgs);
                break;
            case BOOK_ITEM:
                String bookId = uri.getPathSegments().get(1);
                deleteRows = db.delete("Book", "id = ?", new String[] {bookId});
                break;
            case CATEGORY_DIR:
                deleteRows = db.delete("Book", selection, selectionArgs);
                break;
            case CATEGORY_ITEM:
                String categoryId = uri.getPathSegments().get(1);
                deleteRows = db.delete("Book", "id = ?", new String[] {categoryId});
                break;
            default:
                break;
        }
        return deleteRows;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        //更新数据
        SQLiteDatabase db = dbHelper.getWritableDatabase();
        int updateRows = 0;
        switch (mUriMatcher.match(uri)) {
            case BOOK_DIR:
                updateRows = db.update("Book", values, selection, selectionArgs);
                break;
            case BOOK_ITEM:
                String bookId = uri.getPathSegments().get(1);
                updateRows = db.update("Book", values, "id = ?", new String[] {bookId});
                break;
            case CATEGORY_DIR:
                updateRows = db.update("Category", values, selection, selectionArgs);
                break;
            case CATEGORY_ITEM:
                String categoryId = uri.getPathSegments().get(1);
                updateRows = db.update("Category", values, "id = ?", new String[] {categoryId});
                break;
            default:
                break;
        }
        return updateRows;
    }
}

然后你会发现除了刚才提到的六个抽象方法外还多了很多别的代码,下面逐一来分析它:

首先回顾一下URI的标准写法,在这里应该写为:content://geekband.testsql.provider/book。除此之外,我们还可以在这个内容URI后面加上ID,就可以表示访问这个表中拥有这个ID的数据了。所以一个能匹配任意表的内容URI格式就是:content://geekband.testsql.provider/*,其中“*”表示匹配任意长度的任意字符;一个能匹配book表中任意一行数据的内容URI格式就是:content://geekband.testsql.provider/book/#,其中“#”表示匹配任意长度的数字。

接着,我们再借助UriMatcher()这个类就可以轻松地实现匹配内容URI的功能。这个类提供了一个addURI()方法,其中传入三个参数:权限、路径、一个自定义的代码。这样,当调用UriMatcher的match()方法时,就可以将一个Uri对象传入,返回值是某个能够匹配这个Uri对象所对应的自定义代码,利用这个代码,我们就可以判断出调用方期望访问的是哪张表中的数据了。于是我在重写抽象方法之前先定义了4个常量,然后在静态块中创建了mUriMatcher这个实例,并调用了addURI方法传入参数来将自定义代码和调用方期望访问的数据联系起来了。

然后就是getType()方法,它是所有内容提供器都必须提供的一个方法。用于根据传入的内容URI来返回相应的MIME类型。至于内容URI所对应的MIME字符串Android做了如下格式规定:1.必须以vnd开头。2.如果内容URI以路径结尾,则后接android.cursor.dir/,如果内容URI以id结尾,则后接android.cursor.item/。3.最后接上vnd.<authority>.<path>。然后在这个方法内写入switch case,这时传入的是URI所以通过UriMatcher类的match()方法就能让URI返回一个刚才我们建立了特定联系的自定义代码。这样case到不同的自定义代码程序就可以判断调用方期望的是什么数据从而返回相应的MIME类型。

再接着是onCreate()方法,因为我们需要在这里完成数据库的创建或者升级的操作,当然还是要借助数据库的帮助类是实现。但这里不同之处在于这里的onCreate()方法会返回一个布尔型值表示是否创建成功。因为只有当ContentResolver尝试访问我们程序中的数据时ContentProvider才会被初始化。

最后是qeury()、insert()、update()、delete()四个方法,他们传入的第一个参数都是uri,用来指定要操作的表。以及注意一下各方法的返回值:query()方法查询的结果都保存在Cursor对象中因此返回的是一个Cursor对象、insert()方法返回的是增加的那条信息的Uri、update()和delete()的操作都是针对某一行因此返回的是程序操作那一行的Int型变量。其他参数都跟SQL中的用法一样,不再赘述。另外注意当访问单条数据的时候有一个细节,这里调用了Uri对象getPathSegment()方法,它会将内容URI权限之后的部分以"/"符号进行分割,并把分割后的结果放入到一个字符串列表中,那这个列表的第0个位置存放的就是路径,第1个位置存放的就是ID了,得到ID之后才可以进行相关的约束。

最后的最后,当然provider是需要注册的。

<provider
    android:authorities="geekband.testsql.provider"
    android:name=".DatabaseProvider"
    android:exported="true">
</provider>


这样我们在TestSQL项目中的内容提供器就构建好了,接下来我们要新建一个ProviderTest项目、看一下新建的这个项目是否能通过刚才建立的ContentProvider对TestSQL项目进行数据访问。

布局很简单,仍然是放上几个按钮,指定ID。代码略。

package company.providertest;

import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {

    private String newId;

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

        Button addData = (Button) findViewById(R.id.add_data);
        addData.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //添加数据
                Uri uri = Uri.parse("content://geekband.testsql.provider/book");
                ContentValues values = new ContentValues();
                values.put("name", "A Clash Of Kings");
                values.put("author", "George Martin");
                values.put("pages", 1040);
                values.put("price", 22.85);
                Uri newUri = getContentResolver().insert(uri, values);
                newId = newUri.getPathSegments().get(1);
            }
        });

        Button queryData = (Button) findViewById(R.id.query_data);
        queryData.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //查找数据
                Uri uri = Uri.parse("content://geekband.testsql.provider/book");
                Cursor cursor = getContentResolver().query(uri, null, null, null, null);
                if (cursor != null) {
                    while (cursor.moveToNext()) {
                        String name = cursor.getString(cursor.getColumnIndex("name"));
                        String author = cursor.getString(cursor.getColumnIndex("author"));
                        int pages = cursor.getInt(cursor.getColumnIndex("pages"));
                        double price = cursor.getDouble(cursor.getColumnIndex("price"));

                        Log.d("MainActivity", "book name is " + name);
                        Log.d("MainActivity", "book author is " + author);
                        Log.d("MainActivity", "book page is " + pages);
                        Log.d("MainActivity", "book price is " + price);
                    }
                    cursor.close();
                }
            }
        });

        Button updateData = (Button) findViewById(R.id.update_data);
        updateData.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //更新数据
                Uri uri = Uri.parse("content://geekband.testsql.provider/book/" + newId);
                ContentValues values = new ContentValues();
                values.put("name", "The Lord of the Rings");
                values.put("author", "John Ronald Reuel Tolkien");
                values.put("pages", 3699);
                values.put("price", 129.00);
                getContentResolver().update(uri, values, null, null);
            }
        });

        Button deleteData = (Button) findViewById(R.id.delete_data);
        deleteData.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //删除数据
                Uri uri = Uri.parse("content://geekband.testsql.provider/book/" + newId);
                getContentResolver().delete(uri, null, null);
            }
        });
    }
}

拿到四个按钮后,分别在里面添加了点击事件,处理了增删改查的逻辑。

添加数据的时候,首先调用了Uri.parse()方法将一个内容URI解析成Uri对象,然后把要添加的数据存放到ContentValues对象中,接着调用ContentResolver的insert()方法执行添加操作就可以了。在insert()方法中,我们返回了一个Uri对象,然后通过getPathSegment()方法得到了新增这条数据的id,这是给下面的delete()、update()方法操作这条数据而准备的。

其他操作跟添加数据操作一样,都要先调用了Uri.parse()方法将一个内容URI解析成Uri对象。除此之外,查询数据仍然要借助Cursor对象,更新数据也是用的ContentValues,删除数据直接删掉uri即可。当然我们还在query()中打了log以便观察。

点击ADD TO BOOK 然后点击QUERY FROM BOOK可以看到如下图所示Log:


然后点击UPDATE BOOK再点击QUERY FROM BOOK后如下:


可以看出,我们已经成功实现了通过给一个程序构建内容提供器并提供接口从而让外部程序访问该程序数据内容的功能。



至此,Android四大组件中的Content Provider的常见用法已经介绍完毕。

数据中心GPU芯片性能参数速查表(Nvidia+国产算力卡) 本文提供了一份数据中心GPU芯片性能参数速查表,涵盖Nvidia与国产算力卡两大阵营。文章详细解读了算力、显存、互连技术及功耗等关键性能指标,并对比了A100、H100、昇腾910B等主流型号,旨在帮助用户根据AI训练、推理等实际场景,做出高效的硬件选型与成本评估决策。 阅读详情

相关推荐

基于DSP28335的Matlab/Simulink代码生成实验七:A/D采样

实验七:讲解如何使用DSP的ADC模块,通过代码生成技术控制DSP进行电流采样,是后续实现电机闭环控制的重要环节。通过简单的实验来熟悉代码生成的过程。最终实现复杂算法代码自动生成,进行高性能电机控制!

m0_73869369的博客 4725

Android之 ContentProvider内容提供者详解

所有的数据库都是私有的,只能被创建它们的应用程序访问。2.1 ContentProvider 主要用于在不同的应用程序之间实现数据共享的功能,它提供了一套完整的机制,允许一个程序访问另外一个程序的数据,同时还能保证被访问数据的安全性。ContentValues:是一个类似map的键值对,使用put可以添加数据,如values.put("列名","值");ContentValues:是一个类似map的键值对,使用put可以添加数据,如values.put("列名","值");

qq_29848853的博客 3682

从Multibit到Debanking:芯片设计中的时序优化完整流程解析(含真实案例)

本文深入解析芯片设计中Multibit技术与Debanking的时序优化完整流程,结合7nm移动SoC真实案例,详细探讨Multibit的核心优势、实施条件及潜在风险,并提供Debanking的触发时机与操作策略。通过平衡Multibit与Debanking,工程师可有效优化PPA(Power-Performance-Area),提升芯片设计效率。

weixin_30316097的博客 462

【Android 四大组件之Content Provider】一文吃透Content Provider 内容提供者

Content Provider 是安卓系统中四大组件之一,被称为内容提供者,内容提供者组件通过请求从一个应用程序向其他的应用程序提供数据。这些请求由类 ContentResolver 的方法来处理。内容提供者可以使用不同的方式来存储数据。数据可以被存放在数据库,文件,甚至是网络。有时候需要在应用程序之间共享数据,就一定要借助ContentResolver类,通过getContent -Resolver获取实例,在ContentResolver中提供了一系CRUD(增删改查)的方法进行操作其中。多数情况下数

半身风雪 3420

Innovus Function ECO实战:5步搞定数字后端设计中的网表修正(含Calibre LVS验证技巧)

本文提供了一份完整的Innovus Function ECO实战指南,详细解析了数字后端设计中网表修正的五步流程。从理解Function ECO概念、准备关键文件,到在Innovus中执行逻辑比对、自动布线及GUI检查,并重点攻克了ECO后Calibre LVS验证的难点与调试技巧,帮助工程师高效、精准地完成流片前的设计微调。

day7的博客 950

ACM算法模板 · 一些常用的算法模板-模板合集(打比赛专用)

萌新常用的都在这了,本萌新的模板集。

张天枭の博客 5万+

Android四大组件之一 ContentProvide

四大组件之一 content provide

fry3309的博客 3845

1.07---共识机制详解(PoW、PoS、DPoS 对比)

【摘要】区块链能成为“无需信任的协作网络”,靠的正是它的“共识机制”。本节将深入剖析 PoW、PoS、DPoS 等核心共识模型,并结合以太坊从 PoW 到 PoS 的转型与 Solana 等新型方案,为你拆解这一决定区块链运行方式、性能、安全性的“发动机系统”。什么是共识机制?为何不是多数投票这么简单?三大主流共识算法(PoW、PoS、DPoS)机制对比与演化路线以太坊从 PoW 到 PoS 的转型细节(The Merge)Solana 的 PoH + PoS 混合共识机制解析。

鄙人kunzhi96,感恩遇见! 1万+

android四大组件——内容提供器(Content Provider)详解

四大组件——内容提供器(Content Provider)详解 @author 无忧少年 @createTime 2021/08/15 1.内容提供器简介 ​ 内容提供器(Content Provider)主要用于再不同的应用程序之间实现数据共享的功能,他提供了一台完整的机制,允许一个程序访问另一个程序中的数据,同时还能保证被访问的数据的安全性。目前,使用内容提供器是Android实现跨程序共享数据的标准方式。 ​ 不同于文件存储和SharedPreferences存储中的两种全局可读写的操作模式,内容

无忧少年的博客 7202

MIKE21 教程 3.2 随空间变化的网格文件制作(.dfsu文件制作) 曼宁值网格文件制作

上一节讲解了如何制作时间序列文件。本节讲解如何制作仅随空间变化的文件。 目录 1 数据准备 1.1 基于地形设置 1.2 基于地形水深设置: 2 数据导入 3 数据导出

Hello Word 3941

在 SAP BTP 中玩转工厂日历 Maintain Factory Calendars 实战指南

工厂日历是企业关键的时间主数据,基于国家假日历定义工作日与非工作日,广泛应用于生产计划、采购交期、财务结账等业务场景。SAP系统通过三类应用(维护节假日、假日历和工厂日历)实现分层配置。工厂日历作为顶层配置,支持工作日模式设定和例外规则添加。在多系统架构中,工厂日历可通过集成场景同步,确保数据一致性。应用支持创建、编辑和查看功能,包含有效期设置、例外规则管理和多语言文本维护。合理设置工厂日历对业务运营至关重要,需注意命名规范和有效期选择,避免历史数据问题。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 223

Android基础知识(十七):Content Provider

Android基础知识(十七):Content Provider 一、Content Provider简介 Content Provider主要用于在不同的应用程序之间实现数据共享的功能,其提供了一套完整的机制,允许一个程序访问另一个程序中的数据,同时还能保证被访数据的安全性。目前,使用内容提供器是Android实现跨程序共享数据的标准方式。 Content Provider使一个应用程序的指定数...

weixin_38196407的博客 1468

基于机器学习的网络入侵检测系统设计与实现

本文设计并实现了一个基于机器学习的网络入侵检测系统,采用随机森林模型结合KMM算法优化,使用CICIDS2017数据集进行训练。系统包含完整的数据预处理流程、特征工程、模型调优和远程部署方案。实验结果表明,该系统能有效识别多种网络攻击类型,在检测准确率和误报率方面表现优异。研究为网络安全防护提供了新的技术思路和实用工具,具有重要的应用价值。

huanghm88的专栏 318

[Android]【安卓】Content Provider详解

[Android]【安卓】Content Provider详解 本篇博客已收录到我的安卓开发小结中——点击【安卓开发小结】 参考资料: 《第一行代码》 一、内容提供器简介 内容提供器(Content Provider)主要用于在不同的应用程序之间实现数据共享的功能,它提供了一套完整的机制,允许一个程序访问另一个程序中的数据,同时还能保证被访数据的安全性。目前,使用内容提供器是 A...

Hy的博客 1964

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

android Content Provider详解三

Content Provider 的权限 一个具有provider的应用可以指定其它要操作自己的数据所应具有的权限.这些权限保证了用户能了解一个应用将要操作那个数据.其它应用需基于provider的需求请求相应的权限.用户在安装应用时会看到它们所请求的权限. 如果一个provider的应用没有指定任务权限,那么其它应用就不能操作provider的数据.然而,provider所在的应用的组件们却

daizheng521的专栏 996

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

android Content Provider详解一

目录(?)[-] 内容提供者Content Provider Content Provider 基础 概述操作一个provider Content URIs 内容提供者-Content Provider Content providers管理对结构化数据集的使用.它们封装数据,并提供了数据安全的机制.Content providers是从一个

Mr.Simple的专栏 4517

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

android Content Provider详解(1)

内容提供者-ContentProvider Contentproviders管理对结构化数据集的使用.它们封装数据,并提供了数据安全的机制.Contentproviders是从一个进程连接另一个进程中的数据的标准接口. 当你想使用一个contentprovider中的数据,你需在你的应用的Context中使用ContentResolver对象作为客户端与provide...

diaoyinji6441的博客 127

Android之Content provider 详解

Android是如何实现应用程序之间数据共享的?一个应用程序可以将自己的数据完全暴露出去,外界更本看不到,也不用看到这个应用程序暴露的数据是如何存储的,或者是使用数据库还是使用文件,还是通过网上获得,这些一切都不重要,重要的是外界可以通过这一套标准及统一的接口和这个程序里的数据打交道,例如:添加(insert)、删除(delete)、查询(query)、修改(update),当然需要一定的权限才可...

人生就是一种修行 325

android Content Provider 详解

android Content Provider 详解 Android中的Contentprovider机制可支持在多个应用中存储和读取数据。这也是跨应用共享数据的唯一方式。在android系统中,没有一个公共的内存区域,供多个应用共享存储数据。 Android提供了一些主要数据类型的Contentprovider,比如音频、视频、图

qq_15575641的专栏 452

android Content Provider详解六

创建一个Content Provider content provider管理对中央数据仓库的存取。你实现一个provider,就是在一个Android应用中实现一个或多个类,再加上manifest文件中的一些元素。你实现一个 ContentProvider的子类,它作为你的provider和其它应也之间的接口。尽管content providers的目的是向其它应用提供数据,但当然

Mr.li 的博客∮ 615

android provider,Android Content Provider详解及示例代码

Android:Content Provider的使用。1、Content Provider 简介2、使用现成的Content Provider3、定义自己的Content Provider一、Content Provider 简介我们说Android应用程序的四个核心组件是:Activity、Service、Broadcast Receiver 和 Content Provider。在Andro...

weixin_39743824的博客 495

android Content Provider详解四

Provider数据类型Contentproviders能识别多种不同的数据类型.用户词典只识别文本类型,但其它provider可以识别下列格式:整型长整型(long)浮点长浮点(double)另一个provider经常使用的数据类型是"大二进对象"(BLOB) ,它就像一个64KB的字节数组.你可以通过Cursor类的"get"方法查看可用的数据类型.provider中的每列的数据类型都是在它们

nkmnkm的专栏 4316

android content provider 短信,Android ContentProvider实例详解

原标题:Android ContentProvider实例详解新媒体管家1ContentProvider是什么?ContentProvider(内容提供者)是Android的四大组件之一,管理android以结构化方式存放的数据,以相对安全的方式封装数据(表)并且提供简易的处理机制和统一的访问接口供其他程序调用。Android的数据存储方式总共有五种,分别是:Shared Preferences、...

weixin_42519514的博客 554

android Content Provider详解九

元素就像Activity和Service组件,ContentProvider的子类必须在应用的manifest文件中进行定义。使用元素。Android系统从元素中获取以下信息:Authority(android:authorities)在系统中标志整个provider的代号。此属性在设计ContentURI 一节中有更详细的描述。Provider类名(android:name)实现了Content

nkmnkm的专栏 7188
上一篇: Android Service 基础详解
下一篇: Android Activity 基础详解
edcSam
博客等级 码龄11年 5粉丝 28原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值