REST和SOAP
表征状态转移(英文:Representational State Transfer,简称REST)是Roy Fielding博士在2000年他的博士论文中提出来的一种软件架构风格。
目前在三种主流的Web服务实现方案中,因为REST模式的Web服务与复杂的SOAP和XML-RPC对比来讲明显的更加简洁,越来越多的web服务开始采用REST风格设计和实现。
需要注意的是,REST是设计风格而不是标准。REST通常基于使用HTTP,URI,和XML以及HTML这些现有的广泛流行的协议和标准。
- 资源是由URI来指定。
- 对资源的操作包括获取、修改、创建和删除资源,这些操作正好对应HTTP协议提供的GET、POST、PUT和DELETE方法。
- 通过操作资源的表现形式来操作资源。
- 资源的表现形式则是XML或者HTML,取决于读者是机器还是人,是消费web服务的客户软件还是web浏览器。当然也可以是任何其他的格式。
简单对象访问协议(SOAP,全写为Simple Object Access Protocol)
是交换数据的一种协议规范,使用在计算机网络Web服务(web service)中,交换带结构信息。SOAP为了简化网页服务器(Web Server)从XML数据库中提取数据时,节省去格式化页面时间,以及不同应用程序之间按照HTTP通信协议,遵从XML格式执行资料互换,使其抽象于语言实现、平台和硬件。
简单对象访问协议(SOAP)是一种轻量的、简单的、基于 XML 的协议,它被设计成在 WEB 上交换结构化的和固化的信息。 SOAP 可以和现存的许多因特网协议和格式结合使用,包括超文本传输协议( HTTP),简单邮件传输协议(SMTP),多用途网际邮件扩充协议(MIME)。它还支持从消息系统到远程过程调用(RPC)等大量的应用程序。
sqlite3 命令行
Note:adb的提示符为#,sqlite3的提示符为sqlite>
adb shell 进入到shell
设备上的每个ContentProvider都会使用字符串注册自身,这个字符串类似于域名,但称为授权(authority)。这个可唯一标识的字符串是此ContentProvider可提供的一组URI的基础,授权的注册在AndroidManifest.xml中时进行。
ls -R /data/data/*/databases 列出所有*.db文件:
sqlite3 进入到sqlite3
.exit 退出sqlite3
.tables 列出数据库中的所有表
.schema people contacts.db的people表的create语句
.help 帮助
ContentProvider的架构
设备上的每个ContentProvider都会使用字符串注册自身,这个字符串类似于域名,但称为授权(authority)。这个可唯一标识的字符串是此ContentProvider可提供的一组URI的基础,授权的注册在AndroidManifest.xml中时进行。
标识NotePadProvider数据库中的笔记目录或集合的URI为:
content://com.android.provider.NotePad/Notes
标识具体笔记的URI为:
content://com.android.provider.NotePad/Notes(其中#是特定的笔记的id)
1.Android内容URI的结构
从ContentProvider中获取的数据是由Android Cursor 对象表示的一些行和列的集合,Android中的内容URI具有以下通用形式:
content://authority-name/path-segmetl/path-segmet2/etc...
以content://com.android.provider.NotePad/Notes/23为例
- 在content:之后,该URI包含授权的唯一标识符,该标识符用于在提供程序注册表中定位ContentProvider,在示例中com.android.provider.NotePad是URI的授权部分
- /Notes/23是URI中特定于每个ContentProvider的路径部分,路径中的Notes和23称为路径片段。对URI的路径部分和路径片段部分的记录和解释由ContentProvider负责。通常路径的第一部分可以指向一个对象集合,/Notes标识一个笔记集合或目录,而/23指向特定的笔记
2.Android MIME类型的结构
就像网站返回给定URL的MIME类型一样(这使浏览器能够调用正确的程序来查看内容),ContentProvider还负责返回给定URI的MIME类型。这使用户能够灵活地查看数据。知道数据的类型之后,可能有多个程序知道如何处理该数据。例如,如果在硬盘上有一个文本文件,那么许多编辑器都可以显示该文本文件。取决于使用的操作系统,可能还可以选择使用哪个编辑器。
Android MIME类型中的vnd表示这些类型和子类型具有非标准的、供应商特定的的形式。为了实现唯一性,Android使用了多个类似域规范的部分来进一步区分类型和子类型,而且,每个内容类型的Android MIME类型都具有两种形式:一个用于某条具体的记录,另一个用于多条记录。
- 对于单条记录,MIME类型类似于: vnd.android.cursor.item/vnd.yourcompanyname.contenttype
- 对于记录或行的集合,MIME类型类似于: vnd.android.cursor.dir/vnd.yourcompanyname.contenttype
MIME类型广泛用于Android中,尤其是在Intent中,系统在Intent中根据数据的MIME类型来判断调用哪些活动。MIME类型总是通过ContentProvider从它们的URI得出的,在使用MIME类型时,需要注意以下3点:
- 类型和子类型对于它们表表示的内容必须是唯一的
- 如果类型和子类型不是标准的(在谈到具体的记录通常属于这种情况),则需要在它们前面添加vnd
- 它们通常是针对具体需求添加了命名空间
通过Android cursor返回的项集合的主要MIME类型应该始终为 vnd.android.cursor.dir ,通过Android cursor获取的单一项的主要MIME类型应该是vnd.android.cursor.item
3.使用URI读取数据
要从ContentProvider获取数据,需要使用该ContentProvider提供的URI,因为ContentProvider定义的URI对该ContentProvider是唯一的,所以记录这些URI并使其能被程序员看到和调用非常重要。Android中包含的ContentProvider通过定义表示这些URI字符串常量来实现此目的。
给定这些URI,从联系人提供程序获取单行联系人信息的代码类似于:
Uri peopleUri = Contacts.People.CONTENT_URI;
Uri myPersonUri = Uri.withAppendedPath(Contacts.People.CONTENT_URI,"23");
Cursor cur = managedQuery( myPersonUri ,null,null,null,null);
Note:ContentProvider应该实现一组接口或是将列名称作为常量列出,以列出它支持的列。但是,定义列常量的类或接口也应该通过列命名约定、注释或文档清晰地表明列的类型,因为没有正式的方式通过常量指定列的类型
4.使用游标(curosr)
游标的一些知识:
- 游标是一个行集合
- 读取数据之前,需要使用moveToFirst(),因为游标放在第一行之前
- 需要知道列名称
- 需要知道列类型
- 所有字段访问方法都是基于列编号,所以必需首先将列名称转换为列编号
- 游标可以随意移动(可以向前向后移动,也可以跳过一段距离)
- 由于游标可以随意移动,所以可以向它获取行计数
建议首先从游标显式的获取所引,以避免意外。为了找到游标中的行数,Android为游标对象提供了一个getConut()方法。
5.使用where子句
ContentProvider提供了两种方式来传递where子句
a.通过URI
String noteUri = "content://com.google.provider.NotePad/notes/23";
Cursor cur = someActivity.managedQuery(noteUri
projection,//which columns to return
null, //where clause
null); //orderby clause
b.通过String子句与一组可替换的字符串数组参数的组合
Cursor cur = someActivity.managedQuery("content://com.google.provider.NotePad/notes/23"; //Uri
null, //String[] projection
"_id = ?" //String selection
new String[] {23}, //String [] selectionArgs
null); //sortOrder
6.插入记录
Android使用类Android.content.ContentValues来保存将插入的单一录音的值,ContentValues是一个键/值对字典,非常类似于列名称和它们的值。要插入记录,首先将记录填充到ContentValues,然后告诉Android.content.ContentValues使用URI插入该记录。
ContentValues values = new ContentValues();
values.put("tile","New note");
values.put("note","This is a new note");
ContentResolver contentR = activity.getContentResolver();
在NoteP示例中,
Uri uri = contentResolver.insert(NotePad.Notes.CONTENT_URI,values);
此调用返回一个指向新插入记录的URI,回返的URI将具有以下结构:
NotePad.Notes.CONTENT_URI/new_id
7.更新和删除
更新使用的主要是:
int numberOfRowUpdated =
activity.getContentReslover().update(
Uri uri, //数据URI类型
ContentValues values, //要更新的值
String whereClause,
String [] selectionArgs);
删除主要使用的是:
int numberOfRowDeleted =
activity.getContentReslover().update(
Uri uri,
String whereClause,
String [] selectionArgs);
8.使用UriMatcher来解析URI
Android的UriMatcher实用程序类有助于识别URI类型。它的工作原理:你告诉UriMatcher实例需要什么样的URI模式,还将一个唯一编号与每个模式关联,注册这些模式之后,可以询问UriMatcher,传入的URI是否与某个模式匹配。
9.使用投影映射
ContentProvider充当着抽象列集和数据库中真实的列集之间的媒介,这些列集可能是不同的。在构造查询时,必须在客户端指定的where子句列与真实的数据库列之间建立映射。可以借助SQLiteQueryBuilder类建立此投影映射。
实现ContentProvider
要编写ContentProvider,必须扩展android.content.ContentProvider并实现以下重要方法:
- query()
- insert()
- update()
- delete()
- getType()
采取的各种步骤:
- 计划数据库、URI列名称等,创建无数据类来定义所有这些元数据元素的常量
- 扩展抽象类ContentProvider
- 实现方法:query、insert、update、delete和getType
- 在AndroidManifest.xml文件中注册提供程序
getType(uri uri)这个方法何时被调用
当我们在程序中需要启动例外的activity时,很多时候我们是使用的隱式調用,即我们不直接指定要跳转的Activity,而是为Intent提供一些相关的参数,让其自动去和AndroidManifest.xml中已有的Activity去匹配,而IntentFilter(Intent 过滤器)在xml中有三個主要的参数:action,categary,data。
我们通过Intent的构造函数或者Intent提供的方法可以指定这个三个参数,如方法有:
intent.setAction(action);
intent.setData(data);
intent.addCategory(category);
等,比如在记事本程序中有:
<intent-filter android:label="@string/resolve_edit">
<action android:name="android.intent.action.VIEW" />
<action android:name="android.intent.action.EDIT" />
<action android:name="com.android.notepad.action.EDIT_NOTE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="vnd.android.cursor.item/vnd.google.note" />
</intent-filter>
我们很容易看出action和category是很容易匹配的,而我们传的Uri的数据怎么匹配呢,这时系统会去调用你定义的ContentProvider中的getType,取得相关的返回值來和上面的data串进行匹配,当然getType的返回结果你是需要自己去定义的。
但在程序中你也可以自己知道data的类型,就直接匹配了:intent.setType(type);