第8章 Android内容提供者(ContentProvider)应用

Slides:



Advertisements
Similar presentations
第四章 类、对象和接口.
Advertisements

3.2 Java的类 Java 类库的概念 语言规则——程序的书写规范 Java语言 类库——已有的有特定功能的Java程序模块
数据存储.
第13章 繪圖與多媒體 13-1 顯示圖檔-行動相簿 13-2 音樂播放-音樂播放器 13-3 影片播放-視訊播放器
MVC Servlet与MVC设计模式.
實驗五:多媒體播放器選單介面.
Part 2 開發Android應用程式的流程
位置與地圖應用 此投影片為講解Android如何取得定位經緯度和使用Google Map地圖.
第二章 JAVA语言基础.
Android + Web Service 建國科技大學 資管系 饒瑞佶 2017/3 V1.
ArrayAdapter & Spinner
厦门大学数据库实验室 报告人:谢荣东 导师:林子雨 2014年8月30日
實驗四:單位轉換程式.
第7章 Android文件与本地数据库(SQLite)
Chapter 13 Android 實戰演練.
Android + JUnit 單元測試 建國科技大學資管系 饒瑞佶 2012/8/19V4.
程式設計實作.
2.1 基本資料型別 2.2 變數 2.3 運算式與運算子 2.4 輸出與輸入資料 2.5 資料型別轉換 2.6 實例
實驗十三:顯示目前經緯度位置.
Ch06 再談選單元件 物件導向系統實務.
例外處理(Exception Handling)
使用Android控制Arduino 史先强
第10章 App微信分享的实现 倚动实验室.
Java基础 JavaSE异常.
第一个Android程序 本讲大纲: 1、创建Android应用程序 2、Android项目结构说明 3、运行Android应用程序
崑山科技大學資訊管理系 伺服網頁程式設計 系統開發細部流程 教師:游峰碩.
Chapter 7 Android應用元件 Android應用元件可以幫助我們獲得系統資源訊息(ActivityManager)、提供系統服務(Service)、搜尋系統服務(SearchManager)、監聽Intent訊息(Broadcast Receiver)以及資料共享(ContentProvider和ContentResolver)。
Android Intent 建國科技大學 資管系 饒瑞佶 2011/1.
本單元介紹何謂變數,及說明變數的宣告方式。
西南科技大学网络教育系列课程 高级语程序设计(Java) 第五章 继承、接口与范型.
ContentProvider與資料共享
第9章 使用意圖啟動活動與內建應用程式 9-1 意圖的基礎 9-2 使用意圖啟動活動
ANDROID PROGRAMMING2.
授课老师:龚涛 信息科学与技术学院 2018年3月 教材: 《Visual C++程序员成长攻略》 《C++ Builder程序员成长攻略》
Android + Service 建國科技大學 資管系 饒瑞佶.
2018/12/3 面向对象与多线程综合实验-网络编程 教师:段鹏飞.
Java语言程序设计 第五部分 Java异常处理.
第10章 儲存偏好設定、檔案與資料庫 10-1 存取偏好設定 10-2 檔案存取 10-3 關聯式資料庫與SQLite
實驗十四:顯示與控制地圖.
王豐緒 銘傳大學資訊工程學系 問題:JAVA 物件檔輸出入.
第三章 流程控制與例外處理 資訊教育研究室 製作 注意:本投影片僅供上課使用,非經同意,請勿散播或轉載。
第8章 Service解析.
第6章 建立Android使用介面 6-1 介面元件的基礎 6-2 Android的事件處理 6-3 按鈕元件 6-4 文字元件
9.1 程式偵錯 9.2 捕捉例外 9.3 自行拋出例外 9.4 自定例外類別 9.5 多執行緒
Java程序设计 第2章 基本数据类型及操作.
C/C++/Java 哪些值不是头等程序对象
實驗十一:待辦事項程式 (儲存在手機上).
主编:钟元生 赵圣鲁.
第11章 ListView延迟加载效果 授课老师:高成珍 QQ号: QQ群: 、
透過YouTuBe API取得資料 建國科技大學 資管系 饒瑞佶 2018/1 V1.
Android Application Component
JAVA 编 程 技 术 主编 贾振华 2010年1月.
《JAVA程序设计》 语音答疑 辅导老师:高旻.
網路應用.
實驗九:延續實驗八, 製作一個完整音樂播放器
Location Based Services - LBS
第7章 异常处理.
進階UI元件:Spinner與接合器 靜宜大學資管系 楊子青
第二章 Java基本语法 讲师:复凡.
第二章 Java语法基础.
#include <iostream.h>
第二章 Java基本语法 讲师:复凡.
Java程序设计 第17章 异常和断言.
Android Speech To Text(STT)
用Intent啟動程式中的其他Activity、運用WebView顯示網頁 靜宜大學資管系 楊子青
第2章 Java语言基础.
Android进程间通讯.
讀取網路資料及JSON開放資料 靜宜大學資管系 楊子青
第二章 Java基础语法 北京传智播客教育
進階UI元件:Spinner與接合器 靜宜大學資管系 楊子青
Presentation transcript:

第8章 Android内容提供者(ContentProvider)应用 QQ号:1281147324 QQ群:489059718(Android编程-清华版) 287966120(公共版) 网络资源:http://www.xs360.cn/book

主要内容 实例

随着手机上应用的增多,往往在不同的应用之间需要共享数据,比如有一个短信群发的应用,用户需要选择收件人,一个个手机号码输入当然可以达到目的,但是比较麻烦,并且很少有人会记住所有联系人的号码。这时候如果能够获取联系人信息,那就非常方便了。 对于应用之间数据的共享,我们可以在一个应用中直接操作另一个应用所记录的数据,比如前面所学的文件、SharedPreferences或数据库等,但这不仅需要应用程序提供相应的权限,而且还必须知道应用程序中数据存储的细节,不同应用程序记录数据的方式差别也很大,不利于数据的交换。针对这种情况,Android提供了ContentProvider,它是不同应用程序间共享数据的标准API,统一了数据访问方式。

那么ContentProvider是如何对外提供数据的呢?又是如何实现这一机制的呢? ContentProvider以某种URI的形式对外提供数据,数据以类似数据库中表的方式暴露,允许其他应用访问或修改数据; 其他应用程序使用ContentResolver根据URI去访问操作指定的数据。URI是通用资源标识符,即每个ContentProvider都有一个唯一标识的URI,其他应用程序的ContentResolver根据URI就知道具体解析的是哪个ContentProvider,然后调用相应的操作方法; ContentResolver的方法内部实际上是调用该ContentProvider的对应方法,而ContentProvider方法内部是如何实现的,其他应用程序是不知道具体细节的。只是知道有这个方法。这就达到了统一接口的目的。 对于不同的数据的存储方式,该方法内部的实现是不同的,而外部访问方法都是一致的。

8.1 ContentProvider简介 ContentProvider是Android四大组件之一,如果要开发自己的ContentProvider必须实现Android系统提供的ContentProvider基类,并且需要在AndroidManifest.xml文件中进行配置。 1、继承ContentProvider并重写增、删、查、改等方法; 2、在AndroidManifest.xml使用<provider>对该ContentProvider进行配置。<manifest .... > <application....> <provider android:name=".MyProvider" android:authorities="iet.jxufe.cn.android.provider.myprovider"/> </application> </manifest> 注意:authorities是必备属性,如果没有authorities 属性程序会报错。

ContentProvider基类的常用方法 public abstract boolean onCreate():该方法在ContentProvider创建后调用,当其他应用程序第一次访问ContentProvider时,ContentProvider会被创建,并立即调用该方法; public abstract Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder):根据Uri查询符合条件的全部记录,其中projection是所需要获取的数据列; public abstract int update(Uri uri,ContentValues values,String select,String[] selectArgs):根据Uri修改select所匹配的全部记录; public abstract int delete(Uri uri,String selection,String[] selectionArgs):根据Uri删除符合条件的全部记录; public abstract Uri insert(Uri uri, ContentValues values):根据Uri插入values对应的数据,ContentValues类似于map,存放的是键值对; public abstract String getType(Uri uri):该方法返回当前Uri所代表的数据的MIME类型。如果该Uri对应的数据包含多条记录,则MIME类型字符串应该以vnd.android.curor.dir/开头,如果该Uri对应的数据只包含一条记录,则MIME类型字符串应该以vnd.android.cursor.item/开头。

8.2 ContentProvider操作常用类 8.2.1 URI基础 Uri代表了要操作的数据,Uri主要包含了两部分信息: 1、需要操作的ContentProvider; 2、对ContentProvider中的什么数据进行操作。 一个Uri由以下几部分组成: scheme:ContentProvider(内容提供者)的scheme已经由Android所规定, scheme为:content://

8.2.1 URI基础 注意:要操作的数据不一定来自数据库,也可以是文件、xml或网络等其他存储方式。 主机名(或叫Authority)用于唯一标识这个ContentProvider,外部调用者可以根据这个标识来找到它。 路径(path)用于确定我们要操作该ContentProvider中的什么数据,一个ContentProvider内可能包含多种数据,路径的构建应根据业务而定,例如: 要操作person表中id为10的记录,可以构建这样的路径:/person/10 要操作person表中id为10的记录的name字段,路径为:/person/10/name 要操作person表中的所有记录,可以构建这样的路径:/person 要操作xxx表中的记录,可以构建这样的路径:/xxx ID:该部分是可选的,用于指定操作的具体是哪条记录,如果没有设置,则操作的是所有记录。 注意:要操作的数据不一定来自数据库,也可以是文件、xml或网络等其他存储方式。

8.2.1 URI基础 如果要把一个字符串转换成Uri,可以使用Uri类中的parse()方法,例如: Uri uri = Uri.parse("content://iet.jxufe.cn.android.providers.personprovider/person"); 由于Uri代表了要操作的数据,所以我们经常需要解析Uri,并从Uri中获取数据。Android系统提供了两个用于操作Uri的工具类,分别为UriMatcher 和ContentUris 。掌握它们的使用,会便于我们的开发工作。

8.2.2 URI操作类UriMatcher和ContentUris UriMatcher类用于匹配Uri,它的用法如下: 1、注册所有需要匹配的Uri路径: UriMatcher myUri= new UriMatcher(UriMatcher.NO_MATCH); //创建UriMather对象,常量UriMatcher.NO_MATCH表示不匹配任何路径的 //返回码,该常量值为-1。 myUri.addURI(“iet.jxufe.cn.providers.myprovider”, “person”, 1);//添加需匹配的Uri,如果match()方法匹配 ontent://iet.jxufe.cn.providers. //myprovider/person路径,返回匹配码为1。 myUri.addURI(“iet.jxufe.cn.providers.myprovider”, “person/#”, 2);//添加需匹配的Uri,#号为通配符,表示匹配任何ID的Uri,如果匹配则返回2,//例如如果匹配content://iet.jxufe.cn.providers.myprovider/person/230 //路径,返回匹配码为2 2、注册完需要匹配的Uri后,就可以使用myUri.match(uri)方法对输入的Uri进行匹配,如果匹配就返回匹配码,匹配码是调用addURI()方法传入的第三个参数,假设匹配content://iet.jxufe.cn.providers.myprovider/person路径,返回的匹配码为1。

8.2.2 URI操作类UriMatcher和ContentUris ContentUris类用于获取Uri路径后面的ID部分,它有两个比较实用的方法: withAppendedId(uri, id)用于为路径加上ID部分: Uri uri = Uri.parse(“content://iet.jxufe.cn.personprovider/person”); Uri resultUri = ContentUris.withAppendedId(uri, 10); //生成的Uri:为content://iet.jxufe.cn.personprovider/person /10 parseId(uri)方法用于从路径中获取ID部分: Uri uri = Uri.parse(“content://iet.jxufe.cn.personprovider/person /10”); long personid = ContentUris.parseId(uri);//获取的结果为:10

8.2.3 ContentResolver类 ContentProvider的作用是暴露可供操作的数据,其他应用程序主要通过ContentResolver来操作ContentProvider所暴露的数据,ContentResolver相当于客户端。 ContentResolver是一个抽象类,是不能直接实例化的,那么我们如何得到ContentResolver实例呢?Android中Context类提供了getContentResolver()方法用于获取ContentResolver对象。然后即可调用其增删查改方法进行数据操作。 一般来说,ContentProvider是单例模式的,当多个应用程序通过ContentResolver来操作ContentProvider提供的数据时,ContentResolver调用的数据操作将会委托给同一个ContentProvider处理。 使用ContentResolver操作数据的步骤: 调用Activity的getContentResolver()获取ContentResolver; 根据需要调用ContentResolver的insert()、delete()、update()和query()方法操作数据。

8.2.3 ContentResolver类 ContentValues类和Java中的Hashtable类比较相似,都是负责存储一些键值对,但是它存储的键值对当中的键是一个String类型,往往是数据库的某一字段名,而值都是一些简单的数据类型。当我们向数据库中插入一条记录时,可以将这条信息的各个字段值放入ContentValues,然后将该ContentValues直接插入数据库。而不用拼接SQL语句或使用占位符一一赋值。

8.3 ContentProvider应用案例 为备忘录添加ContentProvider

ContentProvider提供的数据 8.3.1 用ContentResolver操纵 ContentProvider提供的数据 向通讯录中添加联系人的事件处理代码,由于通讯录中用户名和号码存放于不同的表中,是根据联系人ID号关联起来的。因此,我们先向联系人中添加一个空的记录,产生新的ID号,然后根据ID号分别在两张表中插入相应的数据。 程序清单:AccessContacts\src\iet\jxufe\cn\android\MainActivity.java public void addPerson() { String nameStr = name.getText().toString(); String numStr = num.getText().toString(); ContentValues values = new ContentValues(); Uri rawContactUri = resolver.insert(RawContacts.CONTENT_URI, values); long contactId = ContentUris.parseId(rawContactUri); System.out.println(contactId); values.clear(); →添加联系人 →获取联系人姓名 →获取联系人号码 →创建一个空的ContentValues →向RawContacts.CONTENT_URI执行一个空值插入,目的是获取返回的ID号 →得到新联系人的ID号 →清空Values的内容

ContentProvider提供的数据 8.3.1 用ContentResolver操纵 ContentProvider提供的数据 程序清单:AccessContacts\src\iet\jxufe\cn\android\MainActivity.java values.put(Data.RAW_CONTACT_ID, contactId); values.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE); values.put(StructuredName.GIVEN_NAME, nameStr); resolver.insert(android.provider.ContactsContract.Data.CONTENT_URI, values); values.clear(); values.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE); values.put(Phone.NUMBER, numStr); values.put(Phone.TYPE, Phone.TYPE_MOBILE); Toast.makeText(MainActivity.this, "联系人数据添加成功!", 1000).show(); } →设置ID号 →设置类型 →设置姓名 →向联系人Uri添加联系人名字 →清空Values的内容 →设置Id号 →设置类型 →设置号码 →设置电话类型 →向联系人电话号码Uri添加电话号码

ContentProvider提供的数据 8.3.1 用ContentResolver操纵 ContentProvider提供的数据 获取通讯录中所有联系人的姓名和手机号时,首先查询出所有的联系人姓名和他的ID号,然后根据ID号查询电话号码表中的的号码,再将每个人的信息放在同一个map对象中,最后将这个map对象添加到列表中,作为结果返回。程序得到列表后将其与下拉列表控件相关联,从而将数据有规律的显示在我们的界面上。 程序清单:AccessContacts\src\iet\jxufe\cn\android\MainActivity.java public ArrayList<Map<String, String>> queryPerson() { ArrayList<Map<String, String>> detail = new ArrayList<Map<String, String>>(); Cursor cursor = resolver.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null); while (cursor.moveToNext()) { Map<String, String> person = new HashMap<String, String>(); String personId = cursor.getString(cursor .getColumnIndex(ContactsContract.Contacts._ID)); String name = cursor.getString(cursor .getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)); person.put("id", personId); person.put("name", name); →创建一个保存所有联系人信息的列表,每项是一个map对象 →查询通讯录中所有联系人 →循环遍历每一个联系人 →每个联系人信息用一个map对象存储 →获取联系人ID号 →获取联系人姓名 →将获取到的信息存入map对象中

ContentProvider提供的数据 8.3.1 用ContentResolver操纵 ContentProvider提供的数据 程序清单:AccessContacts\src\iet\jxufe\cn\android\MainActivity.java Cursor nums = resolver.query( ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "=" + personId, null, null); if(nums.moveToNext()){ String num = nums.getString(nums .getColumnIndex(ContactsContract.CommonDataKinds .Phone.NUMBER)); person.put("num",num); } nums.close(); detail.add(person); } cursor.close(); System.out.println(detail); return detail; →根据ID号,查询手机号码 →将手机号存入map对象中 →关闭资源 →关闭资源 →返回查询列表

ContentProvider提供的数据 8.3.1 用ContentResolver操纵 ContentProvider提供的数据 方法写好后,我们需要在相应的事件处理中调用该方法,代码如下。 程序清单:AccessContacts\src\iet\jxufe\cn\android\MainActivity.java MyOnClickListener myOnClickListener = new MyOnClickListener(); add.setOnClickListener(myOnClickListener); query.setOnClickListener(myOnClickListener); →创建事件监听器 →注册事件监听器 →注册事件监听器 自定义的事件处理器,针对不同事件调用不同的方法。代码如下。 程序清单:AccessContacts/src/iet/jxufe/cn/android/MainActivity.java private class MyOnClickListener implements OnClickListener { public void onClick(View v) { switch (v.getId()) { case R.id.add: addPerson(); break; case R.id.show: title.setVisibility(View.VISIBLE);

ContentProvider提供的数据 8.3.1 用ContentResolver操纵 ContentProvider提供的数据 自定义的事件处理器,针对不同事件调用不同的方法。代码如下。 程序清单:AccessContacts\src\iet\jxufe\cn\android\MainActivity.java ArrayList<Map<String,String>> persons=queryPerson(); SimpleAdapter adapter=new SimpleAdapter(MainActivity.this,persons, R.layout.result, new String[]{ "id","name","num"}, new int[]{R.id.personid, R.id.personname,R.id.personnum}); result.setAdapter(adapter); break; default: }

注意: 8.3.1 用ContentResolver操纵 ContentProvider提供的数据 本程序需要读取、添加联系人信息,因此需要在AndroidManifest.xml文件中为该应用程序授权,授权代码如下。 <uses-permission android:name="android.permission.READ_CONTACTS"/> <uses-permission android:name="android.permission.WRITE_CONTACTS"/> →读的权限 →写的权限

8.3.2 开发自己的ContentProvider 下面我们继续学习如何开发自己的ContentProvider。即将自己的应用数据通过ContentProvider提供给其他应用。 开发自己的ContentProvider主要经历两步: ■ 开发一个ContentProvider子类,该子类需要实现增,删,查,改等方法。 ■ 在AndroidManifest.xml文件中配置该ContentProvider. 下面以一个具体的示例演示如何创建自己的ContentProvider,我们为备忘录示例创建ContentProvider,使得其他应用程序可以访问和修改它的数据。 首先我们定义一个常量类,把备忘录的相关信息以及Uri通过常量的形式进行公开,提供访问该ContentProvider的一些常用入口,代码如下。

8.3.2 开发自己的ContentProvider 程序清单:MementoContent\src\iet\jxufe\cn\android\Mementos.java public class Mementos { public static final String AUTHORITY = "iet.jxufe.cn.providers.memento"; public static final class Memento implements BaseColumns { public static final String _ID = "_id"; public static final String SUBJECT = "subject"; public static final String BODY = "body"; public static final String DATE = "date"; public static final Uri MEMENTOS_CONTENT_URI= Uri.parse("content://" + AUTHORITY + "/mementos"); public static final Uri MEMENTO_CONTENT_URI= Uri.parse("content://" + AUTHORITY + "/memento"); } →memento_tb表中-id字段 →memento_tb表中subject字段 →memento_tb表中body字段 →memento_tb表中date字段 →提供操作mementos集合URI →提供操作单个mementoURI

8.3.2 开发自己的ContentProvider 然后为该应用添加ContentProvider,继承系统中的ContentProvider基类,重写里面的抽象方法,具体代码如下。 程序清单:MementoContent\src\iet\jxufe\cn\android\MementoProvider.java public class MementoProvider extends ContentProvider { private static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH); private static final int MEMENTOS = 1;定义两个常量,用于匹配URI的返回值 private static final int MEMENTO = 2; MyDatabaseHelper dbHelper; SQLiteDatabase db; static { 添加URI匹配规则,用于判断URI的类型 matcher.addURI(Mementos.AUTHORITY, "mementos", MEMENTOS); matcher.addURI(Mementos.AUTHORITY, "memento/#", MEMENTO); } public boolean onCreate() { dbHelper = new MyDatabaseHelper(getContext(), "memento.db", null,1); 创建数据库工具类,并获取数据库实例 db = dbHelper.getReadableDatabase(); return true; }

8.3 访问备忘录数据案例 程序清单:MementoContent\src\iet\jxufe\cn\android\MementoProvider.java public Uri insert(Uri uri, ContentValues values) {//添加记录 long rowID = db.insert("memento_tb", Mementos.Memento._ID, values); if (rowID > 0) { 如果添加成功,则通知数据库记录发生更新 Uri mementoUri = ContentUris.withAppendedId(uri, rowID); getContext().getContentResolver().notifyChange(mementoUri, null); return mementoUri; } return null; } public int delete(Uri uri, String selection, String[] selectionArgs) { int num = 0; 删除记录,用于记录删除的记录数 switch (matcher.match(uri)) { case MEMENTOS: 删除多条记录 num = db.delete("memento_tb", selection, selectionArgs); break;

8.3 访问备忘录数据案例 程序清单:MementoContent\src\iet\jxufe\cn\android\MementoProvider.java case MEMENTO://删除指定ID对应的记录 long id = ContentUris.parseId(uri);//获取ID String where = Mementos.Memento._ID + "=" + id; ID字段需符合的条件 if (selection != null && !"".equals(selection)) { where = where + " and " + selection; 拼接条件语句 } num = db.delete("memento_tb", where, selectionArgs); break; default: throw new IllegalArgumentException("未知Uri:" + uri); getContext().getContentResolver().notifyChange(uri, null); 通知变化 return num;

8.3 访问备忘录数据案例 程序清单:MementoContent\src\iet\jxufe\cn\android\MementoProvider.java public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 更新记录 int num = 0; switch (matcher.match(uri)) { case MEMENTOS: num = db.update("memento_tb", values, selection, selectionArgs); break; case MEMENTO: long id = ContentUris.parseId(uri); String where = Mementos.Memento._ID + "=" + id; if (selection != null && !"".equals(selection)) { where = where + " and " + selection; } num = db.update("memento_tb", values, where, selectionArgs); default: throw new IllegalArgumentException("未知Uri:" + uri); } getContext().getContentResolver().notifyChange(uri, null); return num; }

8.3 访问备忘录数据案例 程序清单:MementoContent\src\iet\jxufe\cn\android\MementoProvider.java public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { switch (matcher.match(uri)) { case MEMENTOS: return db.query("memento_tb", projection, selection, selectionArgs, null, null, sortOrder); case MEMENTO: long id = ContentUris.parseId(uri); String where = Mementos.Memento._ID + "=" + id; if (selection != null && !"".equals(selection)) { where = where + " and " + selection; } return db.query("memento_tb", projection, where, selectionArgs, default: throw new IllegalArgumentException("未知Uri:" + uri); } }

8.3 访问备忘录数据案例 程序清单:MementoContent\src\iet\jxufe\cn\android\MementoProvider.java public String getType(Uri uri) { switch (matcher.match(uri)) { case MEMENTOS: return "vnd.android.cursor.dir/mementos"; case MEMENTO: return "vnd.android.cursor.item/memento"; default: throw new IllegalArgumentException("未知Uri:" + uri); } } } 至此我们的ContentProvider就已经开发好了,下面我们在Manifest.xml中注册,代码如下。 程序清单:MementoContent\AndroidManifest.xml <provider android:name=".MementoProvider" android:authorities="iet.jxufe.cn.providers.memento"> </provider>

8.3 访问备忘录数据案例 在本应用程序中,并没有创建自己备忘录数据库,而是访问MementoContent通过ContentProvider所提供的数据,下面只列出事件处理的关键代码,代码如下。 程序清单:MementoResolver\src\iet\jxufe\cn\android\resolver\MainActivity.java add.setOnClickListener(new OnClickListener() { public void onClick(View v) { ContentValues values = new ContentValues(); values.put(Mementos.Memento.SUBJECT, subject.getText() .toString()); values.put(Mementos.Memento.BODY, body.getText().toString()); values.put(Mementos.Memento.DATE, date.getText().toString()); contentResolver.insert(Mementos.Memento.MEMENTOS_CONTENT_URI, values); Toast.makeText(MainActivity.this, "添加生词成功!", Toast.LENGTH_LONG) .show(); } }); →创建一个ContentValues对象 →values中存值

8.3 访问备忘录数据案例 程序清单:MementoResolver\src\iet\jxufe\cn\android\resolver\MainActivity.java show.setOnClickListener(new OnClickListener() { public void onClick(View v) { Cursor cursor = contentResolver.query( Mementos.Memento.MEMENTOS_CONTENT_URI, null, null, null, null); System.out.println(cursor); SimpleCursorAdapter resultAdapter = new SimpleCursorAdapter( MainActivity.this, R.layout.result, cursor, new String[] { Mementos.Memento._ID, Mementos.Memento.SUBJECT, Mementos.Memento.BODY, Mementos.Memento.DATE }, new int[] { R.id.memento_num, R.id.memento_subject, R.id.memento_body, R.id.memento_date }); result.setAdapter(resultAdapter); } }); →查询所有记录 →设置数据的显示方式

8.4 获取网路资源 由于手机的计算能力、存储能力都比较有限,它通常是作为移动终端来使用,具体的数据处理是交给网络服务器来进行的,而它主要的优势在于携带方便,因此,获取网络资源非常重要。 Android完全支持JDK本身的TCP、UDP网络通信,也支持JDK提供的URL、URLConnection等通信API。 除此之外,Android还内置了HttpClient,可方便地发送HTTP请求,并获取HTTP响应。

8.4 获取网路资源 如http:// iet.jxufe.cn/index.html。 URL(Uniform Resource Locator)对象代表统一资源定位器,用于指定网络上某一资源,该资源既可以是简单的文件或目录,也可以是对复杂对象的引用。通常URL由协议名、主机、端口和资源组成。格式为:protocol://host:port/resourceName, 如http:// iet.jxufe.cn/index.html。 URL类提供了获取协议、主机名、端口号、资源名等方法,详细描述可查看API,此外还提供了openStream()方法,可以读取该URL资源的InputStream,通过该方法可以非常方便地读取远程资源。

8.4 获取网路资源 下面通过一个简单的例子,示范如何通过URL类读取远程资源。该示例用于获取网络上的一张图片,并显示在ImageView中。

8.4 获取网络图片案例 程序清单:AccessURL\src\com\example\accessurl\MainActivity.java public class MainActivity extends Activity { private ImageView myImg; private Handler myHandler; private Bitmap bitmap; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); myImg = (ImageView) findViewById(R.id.myImg); myHandler=new Handler(){ public void handleMessage(Message msg) { if(msg.what==0x1122){ myImg.setImageBitmap(bitmap); } };

8.4 获取网络图片案例 程序清单:AccessURL\src\com\example\accessurl\MainActivity.java new Thread(){ public void run(){ try{ URL url = new URL("http://www.baidu.com/" + "img/baidu_sylogo1.gif"); InputStream is = url.openStream(); bitmap = BitmapFactory.decodeStream(is); is.close(); }catch(Exception ex){ ex.printStackTrace(); } myHandler.sendEmptyMessage(0x1122); }.start(); →获取百度首页图片

8.4 获取网路资源 要想获取网络资源,还必须添加访问网络的许可权限。 注意:Android2.3以后开始提供了一个新的类StrictMode,该类用于捕捉发生在应用程序主线程中耗时的磁盘、网络访问或函数调用,可以帮助开发者改进程序,使主线程处理UI和动画在磁盘读写和网络操作时变得更平滑,避免主线程被阻塞。而2.3以下版本则不支持该类的。如果直接在主程序中处理网络连接操作,在2.3以后版本中会抛出NetworkOnMainThreadException异常,而在之前的版本是则不会。因此,通常采用子线程来处理一些网络连接操作,这样所有版本都适用。 要想获取网络资源,还必须添加访问网络的许可权限。

8.4 获取网路资源 在Android中为我们提供了一个WebView控件,可解析html源代码。下面显示获取网页资源的程序运行结果

8.4 显示html网页案例 程序清单:AccessHtml\src\com\example\accessurl\MainActivity.java public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); show = (WebView) findViewById(R.id.show); result_show=(TextView)findViewById(R.id.result); //show.loadUrl("http://www.baidu.com/"); myHandler = new Handler() { public void handleMessage(Message msg) { if (msg.what == 0x1122) { //result_show.setText(result); show.loadDataWithBaseURL(null, result, "text/html", "utf-8",null); } }; →使用TextView显示结果

8.4 显示html网页案例 程序清单:AccessHtml\src\com\example\accessurl\MainActivity.java 程序清单: new Thread() { public void run() { try { URL httpUrl = new URL("http://www.baidu.com/"); HttpURLConnection conn = (HttpURLConnection) httpUrl .openConnection(); conn.setConnectTimeout(5 * 1000); conn.setRequestMethod("GET"); if (conn.getResponseCode() != 200) throw new RuntimeException("请求url失败"); InputStream iStream = conn.getInputStream(); result = readData(iStream, "utf-8"); conn.disconnect(); myHandler.sendEmptyMessage(0x1122); } catch (Exception ex) { ex.printStackTrace(); } } }.start(); } →设置连接超时 →以get方式发起请求,GET大写 →得到网络返回的输入流

8.4 显示html网页案例 注意: show.loadUrl("http://www.baidu.com"); 上述程序主要是为了演示WebView可以解析HTML代码,实际上要实现上述功能可直接加载URL,而不用先获取源码,然后再将源码转换成对应的页,代码如下。 show.loadUrl("http://www.baidu.com"); 注意: 将字节数组转换成字符串时,需指定编码格式,如果网页中包含中文,而编码格式不正确则会出现中文乱码。编码格式可通过查看网页中的编码方式来指定,本程序中,百度首页采用的是UTF-8的编码格式。

8.4 获取网路资源 WebView控件提供了一个loadDataWithBaseURL(String baseUrl, String data, String mimeType, String encoding, String historyUrl):加载指定的数据到WebView中,可以将源代码字符串转换成相应的网页形式。 注意:将字节数组转换成字符串时,需指定编码格式,如果网页中包含中文,而编码格式不正确则会出现中文乱码。编码格式可通过查看网页中编码方式来指定,本程序中,百度首页采用的是UTF-8的编码格式。 WebView控件提供了一个loadUrl(String url)方法,直接加载指定的网页内容。