当前位置:文档之家› android四大组件--ContentProvider详解

android四大组件--ContentProvider详解

android四大组件--ContentProvider详解
android四大组件--ContentProvider详解

android四大组件--ContentProvider详解

一、相关ContentProvider概念解析:

1、ContentProvider简介

在Android官方指出的Android的数据存储方式总共有五种,分别是:Shared Preferences、网络存储、文件存储、外储存储、SQLite。但是我们知道一般这些存储都只是在单独的一个应用程序之中达到一个数据的共享,有时候我们需要操作其他应用程序的一些数据,例如我们需要操作系统里的媒体库、通讯录等,这时我们就可能通过ContentProvider来满足我们的需求了。

2、为什么要选择ContentProvider?

ContentProvider向我们提供了我们在应用程序之前共享数据的一种机制,而我们知道每一个应用程序都是运行在不同的应用程序的,数据和文件在不同应用程序之间达到数据的共享不是没有可能,而是显得比较复杂,而正好Android中的ContentProvider则达到了这一需求,比如有时候我们需要操作手机里的联系人,手机里的多媒体等一些信息,我们都可以用到这个ContentProvider来达到我们所需。

1)、ContentProvider为存储和获取数据提供了统一的接口。ContentProvide 对数据进行封装,不用关心数据存储的细节。使用表的形式来组织数据。

2)、使用ContentProvider可以在不同的应用程序之间共享数据。

3)、Android为常见的一些数据提供了默认的ContentProvider(包括音频、视频、图片和通讯录等)。

总的来说使用ContentProvider对外共享数据的好处是统一了数据的访问方式。

3、Uri介绍

为系统的每一个资源给其一个名字,比方说通话记录。

1)、每一个ContentProvider都拥有一个公共的URI,这个URI用于表示这个ContentProvider所提供的数据。

2)、Android所提供的ContentProvider都存放在android.provider包中。将其分为A,B,C,D 4个部分:

A:标准前缀,用来说明一个Content Provider控制这些数据,无法改变的;

"content://"

B:URI 的标识,用于唯一标识这个ContentProvider,外部调用者可以根据这个标识来找到它。它定义了是哪个Content Provider提供这些数据。对于第三方应用程序,为了保证URI标识的唯一性,它必须是一个完整的、小写的类名。这个标识在元素的 authorities属性中说明:一般是定义该ContentProvider的包.类的名称

C:路径(path),通俗的讲就是你要操作的数据库中表的名字,或者你也可以自己定义,记得在使用的时候保持一致就可以了;

"content://com.bing.provider.myprovider/tablename"

D:如果URI中包含表示需要获取的记录的ID;则就返回该id对应的数据,如果没有ID,就表示返回全部;

"content://com.bing.provider.myprovider/tablename/#" #表示数据id。

PS:

路径(path)可以用来表示我们要操作的数据,路径的构建应根据业务而定,如下:

1、要操作person表中id为10的记录,可以构建这样的路径:/person/10

2、要操作person表中id为10的记录的name字段, person/10/name

3、要操作person表中的所有记录,可以构建这样的路径:/person

4、要操作xxx表中的记录,可以构建这样的路径:/xxx

5、当然要操作的数据不一定来自数据库,也可以是文件、xml或网络等其他存储方

式,如下:

要操作xml文件中person节点下的name节点,可以构建这样的路径:/person/name

6、如果要把一个字符串转换成Uri,可以使用Uri类中的parse()方法,如下:Uri

uri = Uri.parse("content://com.bing.provider.personprovider/person")

4、UriMatcher类使用介绍

因为Uri代表了要操作的数据,所以我们经常需要解析Uri,并从Uri中获取数据。Android系统提供了两个用于操作Uri的工具类,分别为UriMatcher和

ContentUris 。掌握它们的使用,会便于我们的开发工作。

UriMatcher类用于匹配Uri,它的用法如下:

首先第一步把你需要匹配Uri路径全部给注册上,如下:

//常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码

UriMatcher sMatcher = new UriMatcher(UriMatcher.NO_MATCH);

//如果match()方法匹配content://com.bing.procvide.personprovider/person路径,返回匹配码为1

sMatcher.addURI("com.bing.procvide.personprovider", "person", 1);//添加需要匹配uri,如果匹配就会返回匹配码

//如果match()方法匹配content://com.bing.provider.personprovider/person/230路径,返回匹配码为2

sMatcher.addURI("com.bing.provider.personprovider", "person/#", 2);//#号为通配符

switch (sMatcher.match(Uri.parse("content://com.ljq.provider.personprovider/person/10"))) { case 1

break;

case 2

break;

default://不匹配

break;

}

注册完需要匹配的Uri后,就可以使用sMatcher.match(uri)方法对输入的Uri进行匹配,如果匹配就返回匹配码,匹配码是调用addURI()方法传入的第三个参数,假设匹配content://com.ljq.provider.personprovider/person路径,返回的匹配码为1

5、ContentUris类使用介绍

ContentUris类用于操作Uri路径后面的ID部分,它有两个比较实用的方法:withAppendedId(uri, id)用于为路径加上ID部分:

Uri uri = Uri.parse("content://com.bing.provider.personprovider/person") Uri resultUri = ContentUris.withAppendedId(uri, 10);

//生成后的Uri为:content://com.bing.provider.personprovider/person/10

parseId(uri)方法用于从路径中获取ID部分:

Uri uri = Uri.parse("content://com.ljq.provider.personprovider/person/10") long personid = ContentUris.parseId(uri);//获取的结果为:10

6、使用ContentProvider共享数据

1)ContentProvider类主要方法的作用:

public boolean onCreate():该方法在ContentProvider创建后就会被调用,

Android开机后,ContentProvider在其它应用第一次访问它时才会被创建。

public Uri insert(Uri uri, ContentValues values):该方法用于供外部应用往

ContentProvider添加数据。

public int delete(Uri uri, String selection, String[] selectionArgs):该

方法用于供外部应用从ContentProvider删除数据。

public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs):该方法用于供外部应用更新ContentProvider中的数据。

public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder):该方法用于供外部应用从ContentProvider 中获取数据。

public String getType(Uri uri):该方法用于返回当前Url所代表数据的MIME

类型。

2)如果操作的数据属于集合类型,那么MIME类型字符串应该以

vnd.android.cursor.dir/开头,

例如:要得到所有person记录的Uri为

content://com.bing.provider.personprovider/person,那么返回的MIME类型字符串应该为:"vnd.android.cursor.dir/person"。

3)如果要操作的数据属于非集合类型数据,那么MIME类型字符串应该以

vnd.android.cursor.item/开头,

例如:得到id为10的person记录,Uri为

content://com.bing.provider.personprovider/person/10,那么返回的MIME类型字符串为:"vnd.android.cursor.item/person"。

7、ContentResolver操作ContentProvider中的数据

1)当外部应用需要对ContentProvider中的数据进行添加、删除、修改和查询操作时,可以使用ContentResolver 类来完成,要获取ContentResolver 对象,可以使用Activity提供的getContentResolver()方法。

2)ContentResolver 类提供了与ContentProvider类相同签名的四个方法:public Uri insert(Uri uri, ContentValues values):该方法用于往ContentProvider添加数据。

public int delete(Uri uri, String selection, String[] selectionArgs):该方法用于从ContentProvider删除数据。

public int update(Uri uri, ContentValues values, String selection, String[]

selectionArgs):该方法用于更新ContentProvider中的数据。

public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder):该方法用于从ContentProvider中获取数据。

这些方法的第一个参数为Uri,代表要操作的ContentProvider和对其中的什么数据进行操作,

其实和contentprovider里面的方法是一样的.他们所对应的数据,最终是会被传到我们在之前程序里面定义的那个contentprovider类的方法,

假设给定的是:

Uri.parse("content://com.bing.providers.personprovider/person/10"),那么将会对主机名为com.bing.providers.personprovider的ContentProvider进行操作,操作的数据为person表中id为10的记录。

使用ContentResolver对ContentProvider中的数据进行添加、删除、修改和查询操作:

ContentResolver resolver = getContentResolver();

Uri uri = Uri.parse("content://com.bing.provider.personprovider/person");

//添加一条记录

ContentValues values = new ContentValues();

values.put("name", "bingxin");

values.put("age", 25);

resolver.insert(uri, values);

//获取person表中所有记录

Cursor cursor = resolver.query(uri, null, null, null, "personid desc");

while(cursor.moveToNext()){

Log.i("ContentTest", "personid="+ cursor.getInt(0)+ ",name="+ cursor.getString(1));

}

//把id为1的记录的name字段值更改新为zhangsan

ContentValues updateValues = new ContentValues();

updateValues.put("name", "zhangsan");

Uri updateIdUri = ContentUris.withAppendedId(uri, 2);

resolver.update(updateIdUri, updateValues, null, null);

//删除id为2的记录

Uri deleteIdUri = ContentUris.withAppendedId(uri, 2);

resolver.delete(deleteIdUri, null, null);

8、监听ContentProvider中数据的变化

如果ContentProvider的访问者需要知道ContentProvider中的数据发生变化,可以在

ContentProvider发生数据变化时调用getContentResolver().notifyChange(uri, null)来通知注册在此URI上的访问者,例子如下:

public class PersonContentProvider extends ContentProvider {

public Uri insert(Uri uri, ContentValues values) {

db.insert("person", "personid", values);

getContext().getContentResolver().notifyChange(uri, null);

}

}

如果ContentProvider的访问者需要得到数据变化通知,必须使用ContentObserver对数据(数据采用uri描述)进行监听,当监听到数据变化通知时,系统就会调用ContentObserver的onChange()方法:

getContentResolver().registerContentObserver(Uri.parse("content://com.ljq.providers.per sonprovider/person"),

true, new PersonObserver(new Handler()));

public class PersonObserver extends ContentObserver{

public PersonObserver(Handler handler) {

super(handler);

}

public void onChange(boolean selfChange) {

//此处可以进行相应的业务处理

}

}

二、ContentProvider的实现过程

1、定义一个CONTENT_URI常量,提供了访问ContentProvider的标识符。

public static final Uri CONTENT_URI =

Uri.parse("content://com.example.codelab.transportationprovider");

其中:content是协议

Com.exmaple.codelab.transportationprovider是类名,包含完整的包名。

Uri.parse将一个字符串转换成Uri类型。

如果Provider包含子表,同样定义包含字表的CONTENT_URI。

content://com.example.codelab.transportationprovider/train

content://com.example.codelab.transportationprovider/air/domestic

content://com.example.codelab.transportationprovider/air/international

然后定义列,确保里面包含一个_id的列。

2、定义一个类,继承ContentProvider。

public class FirstContentProvider extends ContentProvider

先介绍一下ContentProvider用到的UriMatcher。UriMatcher的一个重要的函数是

match(Uri uri)。这个函数可以匹配Uri,根据传入的不同Uri返回不同的自定义整形值,以表明Uri访问的不同资源的类型。

例如:public static final UriMatcher uriMatcher;

static {

uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);

uriMatcher.addURI(Book.AUTHORITY, "item", Book.ITEM);

uriMatcher.addURI(Book.AUTHORITY, "item/#", Book.ITEM_ID);

}

这里UriMatcher类型的静态字段是用来匹配传入到ContentProvider中的Uri的类。其构造方法传入的匹配码是使用match()方法匹配根路径时返回的值,这个匹配码

可以为一个大于零的数表示匹配根路径或传入-1,即常量UriMatcher.NO_MATCH表示不匹配根路径。

addURI()方法是用来增加其他URI匹配路径的,

第一个参数传入标识ContentProvider的AUTHORITY字符串。

第二个参数传入需要匹配的路径,这里的#号为通配符,代表匹配任意数字,

另外还可以用*来匹配任意文本。

第三个参数必须传入一个大于零的匹配码,用于match()方法对相匹配的URI

返回相对应的匹配码。例如:

sMatcher.addURI(“com.test.provider.personprovider”, “person”, 1);如果match()方法匹配content://com.test.provider.personprovider/person路径,返回匹配码为1。

3、实现query,insert,update,delete,getType和onCreate方法。

4、在AndroidManifest.xml当中进行声明。

android:name="com.bj.FirstContentProvider" />

三、实例

1、常量类

/**

* 提供ContentProvider对外的各种常量,当外部数据需要访问的时候,就可以参考这些常量操作数据。

* @author HB

*

*/

public class ContentData {

public static final String AUTHORITY = "hb.android.contentProvider";

public static final String DATABASE_NAME = "teacher.db";

//创建数据库的时候,都必须加上版本信息;并且必须大于4

public static final int DATABASE_VERSION = 4;

public static final String USERS_TABLE_NAME = "teacher";

public static final class UserTableData implements BaseColumns {

public static final String TABLE_NAME = "teacher";

//Uri,外部程序需要访问就是通过这个Uri访问的,这个Uri必须的唯一的。

public static final Uri CONTENT_URI = Uri.parse("content://"+ AUTHORITY + "/teacher");

// 数据集的MIME类型字符串则应该以vnd.android.cursor.dir/开头

public static final String CONTENT_TYPE =

"vnd.android.cursor.dir/hb.android.teachers";

// 单一数据的MIME类型字符串应该以vnd.android.cursor.item/开头

public static final String CONTENT_TYPE_ITME =

"vnd.android.cursor.item/hb.android.teacher";

/* 自定义匹配码*/

public static final int TEACHERS = 1;

/* 自定义匹配码*/

public static final int TEACHER = 2;

public static final String TITLE = "title";

public static final String NAME = "name";

public static final String DATE_ADDED = "date_added";

public static final String SEX = "SEX";

public static final String DEFAULT_SORT_ORDER = "_id desc";

public static final UriMatcher uriMatcher;

static {

// 常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码

uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);

// 如果match()方法匹配content://hb.android.teacherProvider/teachern 路径,返回匹配码为TEACHERS

uriMatcher.addURI(ContentData.AUTHORITY, "teacher", TEACHERS);

// 如果match()方法匹配

content://hb.android.teacherProvider/teacher/230,路径,返回匹配码为TEACHER uriMatcher.addURI(ContentData.AUTHORITY, "teacher/#", TEACHER);

}

}

}

PS:

在创建UriMatcher对象uriMatcher时,我们传给构造函数的参数为UriMatcher.NO_MATCH,它表示当uriMatcher不能匹配指定的URI时,就返回代码UriMatcher.NO_MATCH。接下来增加了三个匹配规则,分别是uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); uriMatcher.addURI(ContentData.AUTHORITY, "teacher", TEACHERS); uriMatcher.addURI(ContentData.AUTHORITY,

"teacher/#", TEACHER);

它们的匹配码分别是teacher.ITEM、teacher.ITEM_ID和teacher.ITEM_POS,其中,符号#表示匹配任何数字。

2、SQLite操作类DBOpenHelper

/**

* 这个类继承SQLiteOpenHelper抽象类,用于创建数据库和表。创建数据库是调用它的父类构造方法创建。

* @author HB

*/

public class DBOpenHelper extends SQLiteOpenHelper {

// 在SQLiteOepnHelper的子类当中,必须有该构造函数,用来创建一个数据库;

public DBOpenHelper(Context context, String name, CursorFactory factory,

int version) {

// 必须通过super调用父类当中的构造函数

super(context, name, factory, version);

// TODO Auto-generated constructor stub

}

// public DBOpenHelper(Context context, String name) {

// this(context, name, VERSION);

// }

public DBOpenHelper(Context context, String name, int version) {

this(context, name, null, version);

}

/**

* 只有当数据库执行创建的时候,才会执行这个方法。如果更改表名,也不会创建,只有当创建数据库的时候,才会创建改表名之后的数据表

*/

@Override

public void onCreate(SQLiteDatabase db) {

System.out.println("create table");

db.execSQL("create table " + https://www.doczj.com/doc/5012654578.html,erTableData.TABLE_NAME

+ "(" + https://www.doczj.com/doc/5012654578.html,erTableData._ID

+ " INTEGER PRIMARY KEY autoincrement,"

+ https://www.doczj.com/doc/5012654578.html, + " varchar(20),"

+ https://www.doczj.com/doc/5012654578.html,erTableData.TITLE + " varchar(20),"

+ https://www.doczj.com/doc/5012654578.html,erTableData.DATE_ADDED + " long,"

+ https://www.doczj.com/doc/5012654578.html,erTableData.SEX + " boolean)" + ";");

}

@Override

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

}

}

3、内容提供者代码

/**

* 这个类给外部程序提供访问内部数据的一个接口

* @author HB

*

*/

public class TeacherContentProvider extends ContentProvider {

private DBOpenHelper dbOpenHelper = null;

// UriMatcher类用来匹配Uri,使用match()方法匹配路径时返回匹配码

/**

* 是一个回调函数,在ContentProvider创建的时候,就会运行,第二个参数为指定数据库名称,如果不指定,就会找不到数据库;

* 如果数据库存在的情况下是不会再创建一个数据库的。(当然首次调用在这里也不会生成数据库必须调用SQLiteDatabase的

getWritableDatabase,getReadableDatabase两个方法中的一个才会创建数据库)*/

@Override

public boolean onCreate() {

//这里会调用DBOpenHelper的构造函数创建一个数据库;

dbOpenHelper = new DBOpenHelper(this.getContext(),

ContentData.DATABASE_NAME, ContentData.DATABASE_VERSION);

return true;

}

/**

* 当执行这个方法的时候,如果没有数据库,他会创建,同时也会创建表,但

是如果没有表,下面在执行insert的时候就会出错

* 这里的插入数据也完全可以用sql语句书写,然后调用db.execSQL(sql)执行。

*/

@Override

public Uri insert(Uri uri, ContentValues values){

//获得一个可写的数据库引用,如果数据库不存在,则根据onCreate的方法里创建;

SQLiteDatabase db = dbOpenHelper.getWritableDatabase();

long id = 0;

switch (uriMatcher.match(uri)) {

case TEACHERS:

id = db.insert("teacher", null, values); // 返回的是记录的行号,主键为int,实际上就是主键值

return ContentUris.withAppendedId(uri, id);

case TEACHER:

id = db.insert("teacher", null, values);

String path = uri.toString();

return Uri.parse(path.substring(0, https://www.doczj.com/doc/5012654578.html,stIndexOf("/"))+id); // 替换掉id default:

throw new IllegalArgumentException("Unknown URI " + uri);

}

}

@Override

public int delete(Uri uri, String selection, String[] selectionArgs) {

SQLiteDatabase db = dbOpenHelper.getWritableDatabase();

int count = 0;

switch (uriMatcher.match(uri)) {

case TEACHERS:

count = db.delete("teacher", selection, selectionArgs);

break;

case TEACHER:

// 下面的方法用于从URI中解析出id,对这样的路径

content://hb.android.teacherProvider/teacher/10

// 进行解析,返回值为10

long personid = ContentUris.parseId(uri);

String where = "_ID=" + personid; // 删除指定id的记录

where += !TextUtils.isEmpty(selection) ? " and (" + selection + ")" : ""; // 把其它条件附加上

count = db.delete("teacher", where, selectionArgs);

break;

default:

throw new IllegalArgumentException("Unknown URI " + uri);

}

db.close();

return count;

}

@Override

public int update(Uri uri, ContentValues values, String selection,

String[] selectionArgs) {

SQLiteDatabase db = dbOpenHelper.getWritableDatabase();

int count = 0;

switch (uriMatcher.match(uri)) {

case TEACHERS:

count = db.update("teacher", values, selection, selectionArgs);

break;

case TEACHER:

// 下面的方法用于从URI中解析出id,对这样的路径

content://com.ljq.provider.personprovider/person/10

// 进行解析,返回值为10

long personid = ContentUris.parseId(uri);

String where = "_ID=" + personid;// 获取指定id的记录

where += !TextUtils.isEmpty(selection) ? " and (" + selection + ")" : "";// 把其它条件附加上

count = db.update("teacher", values, where, selectionArgs);

break;

default:

throw new IllegalArgumentException("Unknown URI " + uri);

}

db.close();

return count;

}

@Override

public String getType(Uri uri) {

switch (uriMatcher.match(uri)) {

case TEACHERS:

return CONTENT_TYPE;

case TEACHER:

return CONTENT_TYPE_ITME;

default:

throw new IllegalArgumentException("Unknown URI " + uri);

}

}

@Override

public Cursor query(Uri uri, String[] projection, String selection,

String[] selectionArgs, String sortOrder) {

SQLiteDatabase db = dbOpenHelper.getReadableDatabase();

switch (uriMatcher.match(uri)) {

case TEACHERS:

return db.query("teacher", projection, selection, selectionArgs, null, null, sortOrder);

case TEACHER:

// 进行解析,返回值为10

long personid = ContentUris.parseId(uri);

String where = "_ID=" + personid;// 获取指定id的记录

where += !TextUtils.isEmpty(selection) ? " and (" + selection + ")" : "";// 把其它条件附加上

return db.query("teacher", projection, where, selectionArgs, null, null, sortOrder);

default:

throw new IllegalArgumentException("Unknown URI " + uri);

}

}

}

PS:

1、这里我们在ArticlesProvider类的内部中定义了一个DBHelper类,它继承于SQLiteOpenHelper类,它用是用辅助我们操作数据库的。使用这个DBHelper 类来辅助操作数据库的好处是只有当我们第一次对数据库时行操作时,系统才会执行打开数据库文件的操作。拿我们这个例子来说,只有第三方应用程序第一次调用query、insert、update或者delete函数来操作数据库时,我们才会真正去打开相应的数据库文件。这样在onCreate函数里,就不用执行打开数据库的操作,因为这是一个耗时的操作,而在onCreate函数中,要避免执行这些耗时的操作。

2、我们在实现自己的Content Provider时,必须继承于ContentProvider类,并且实现以下六个函数:

-- onCreate(),用来执行一些初始化的工作。

-- query(Uri, String[], String, String[], String),用来返回数据给调用者。

-- insert(Uri, ContentValues),用来插入新的数据。

-- update(Uri, ContentValues, String, String[]),用来更新已有的数据。

-- delete(Uri, String, String[]),用来删除数据。

-- getType(Uri),用来返回数据的MIME类型。

4、manifest

package="hb.android.contentProvider"

xmlns:android="https://www.doczj.com/doc/5012654578.html,/apk/res/android">

android:name=".TeacherContentProvider" android:multiprocess="false" />

PS:

在配置Content Provider的时候,最重要的就是要指定它的authorities属性了,只有配置了这个属性,第三方应用程序才能通过它来找到这个Content Provider。这要需要注意的,这里配置的authorities属性的值是和我们前面在Articles.java文件中定义的AUTHORITY常量的值是一致的。另外一个属性multiprocess是一个布尔值,它表示这个Content Provider是否可以在每个客户进程中创建一个实例,这样做的目的是为了减少进程间通信的开销。这里我们为了减少不必要的内存开销,把属性multiprocess的值设置为false,使得系统只能有一个Content Provider实例存在,它运行在自己的进程中。在这个配置文件里面,我们还可以设置这个Content Provider的访问权限,这里我们为了简单起见,就不设置权限了。

6、布局文件

android:orientation="vertical" android:layout_width="fill_parent"

android:layout_height="fill_parent">

7、activity

package hb.android.contentProvider;

import java.util.Date;

import android.app.Activity;

import android.content.ContentResolver;

import android.content.ContentValues;

import android.database.Cursor;

import https://www.doczj.com/doc/5012654578.html,.Uri;

import android.os.Bundle;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

/**

* 这个类用来测试ContentProvider是否可用。通过给定的uri访问,数据库;*

* @author HB

*

*/

public class TeacherActivity extends Activity {

Button insert;

Button query;

Button update;

Button delete;

Button querys;

Uri uri = Uri.parse("content://hb.android.contentProvider/teacher");

/** Called when the activity is first created. */

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(https://www.doczj.com/doc/5012654578.html,yout.main);

insert = (Button) findViewById(R.id.insert);

query = (Button) findViewById(R.id.query);

update = (Button) findViewById(R.id.update);

delete = (Button) findViewById(R.id.delete);

querys = (Button) findViewById(R.id.querys);

// 绑定监听器的两种方法一;

insert.setOnClickListener(new InsertListener());

query.setOnClickListener(new QueryListener());

// 方法二

update.setOnClickListener(new OnClickListener() {

public void onClick(View v) {

// TODO Auto-generated method stub

ContentResolver cr = getContentResolver();

ContentValues cv = new ContentValues();

cv.put("name", "huangbiao");

cv.put("date_added", (new Date()).toString());

int uri2 = cr.update(uri, cv, "_ID=?", new String[]{"3"}); System.out.println("updated"+":"+uri2);

}

});

delete.setOnClickListener(new OnClickListener() {

public void onClick(View v) {

ContentResolver cr = getContentResolver();

cr.delete(uri, "_ID=?", new String[]{"2"});

}

});

querys.setOnClickListener(new OnClickListener() {

public void onClick(View v) {

// TODO Auto-generated method stub

ContentResolver cr = getContentResolver();

// 查找id为1的数据

Cursor c = cr.query(uri, null, null,null, null);

System.out.println(c.getCount());

c.close();

}

});

}

class InsertListener implements OnClickListener {

public void onClick(View v) {

// TODO Auto-generated method stub

ContentResolver cr = getContentResolver();

ContentValues cv = new ContentValues();

cv.put("title", "jiaoshou");

cv.put("name", "jiaoshi");

cv.put("sex", true);

Uri uri2 = cr.insert(uri, cv);

System.out.println(uri2.toString());

}

}

class QueryListener implements OnClickListener {

public void onClick(View v) {

// TODO Auto-generated method stub

ContentResolver cr = getContentResolver();

// 查找id为1的数据

Cursor c = cr.query(uri, null, "_ID=?", new String[] { "1" }, null);

//这里必须要调用c.moveToFirst将游标移动到第一条数据,不然会出现index -1 requested , with a size of 1错误;cr.query返回的是一个结果集。

if (c.moveToFirst() == false) {

// 为空的Cursor

return;

}

int name = c.getColumnIndex("name");

System.out.println(c.getString(name));

c.close();

}

}

}

最终的效果如下:

组件Content Provider中的数据更新通知机制和Android系统中的广播(Broadcast)通知机制的实现思路是相似的。

在Android的广播机制中,首先是接收者对自己感兴趣的广播进行注册,接着当发送者发出这些广播时,接收者就会得到通知了。更多关于Android系统的广播机制的知识,可以参考前面Android四大组件--Broadcast Receiver详解这一文章。

然而,Content Provider中的数据监控机制与Android系统中的广播机制又有三个主要的区别,

一是前者是通过URI来把通知的发送者和接收者关联在一起的,而后者是通过Intent来关联的,

二是前者的通知注册中心是由ContentService服务来扮演的,而后者是由ActivityManagerService服务来扮演的,

三是前者负责接收数据更新通知的类必须要继承ContentObserver类,而后者要继承BroadcastReceiver类。

之所以会有这些区别,是由于Content Proivder组件的数据共享功能本身就是建立在URI的基础之上的,因此专门针对URI来设计另外一套通知机制会更实用和方便,而Android系统的广播机制是一种更加通用的事件通知机制,它的适用范围会更广泛一些。

Android四大组件

Android四大组件 Android开发平台是开放的平台,而位于四层框架顶端的应用开发,必然涉及到Android组件。本文将为大家详细介绍Android组件。 组件(Component),在谈及所谓架构和重用的时候,是一个重要的事情。很多时候都会说基于组件的软件架构,指的是期望把程序做乐高似的,有一堆接口标准封装完整的组件放在哪里,想用的时候取上几个一搭配,整个程序就构建完成了。 在开篇的时候就在说,Android是一个为组件化而搭建的平台,它引入所谓Mash-Up的概念,这使得你在应用的最上层,想做的不组件化都是很困难的一件事情(底层逻辑,好吧,管不了...)。具体说来,Android有四大组件四喜丸子:Activity、Service、Broadcast Receiver、Content Provider。 Activity 做一个完整的Android程序,不想用到Activity,真的是比较困难的一件事情,除非是想做绿叶想疯了。因为Activity是Android程序与用户交互的窗口,在我看来,从这个层面的视角来看,Android的Activity特像网站的页面。 首先,一个网站,如果一张页面都没有,那...,真是一颗奇葩。而一张页面往往都有个独立的主题和功能点,比如登录页面,注册页面,管理页面,如是。 在每个页面里面,会放一些链接,已实现功能点的串联,有的链接点了,刷,跑到同一站点的另一个页面去了;有的链接点了,啾,可能跳到其他网站的页面去;还有的链接点了,恩...,这次没跑,但当前页面的样子可能有所变化了。这些模式,和Activity给人的感觉很像,只不过实现策略不同罢了,毕竟Android这套架构的核心思想,本身就来自源于Web的Mash-Up概念,视为页面的客户端化,也未尝不可。 Activity,在四大组件中,无疑是最复杂的,这年头,一样东西和界面挂上了勾,都简化不了,想一想,独立做一个应用有多少时间沦落在了界面上,就能琢磨清楚了。从视觉效果来看,一个Activity占据当前的窗口,响应所有窗口事件,具备有控件,菜单等界面元素。从内部逻辑来看,Activity需要为了保持各个界面状态,需要做很多持久化的事情,还需要妥善管理生命周期,和一些转跳逻辑。对于开发者而言,就需要派生一个Activity的子类,然后埋头苦干上述事情。对于Activity的更多细节,先可以参见:reference/android/app/Activity.html。后续,会献上更为详尽的剖析。 Service 服务,从最直白的视角来看,就是剥离了界面的Activity,它们在很多Android的概念方面比较接近,都是封装有一个完整的功能逻辑实现,只不过Service不抛头露脸,只是默默无声的做坚实的后盾。 但其实,换个角度来看,Android中的服务,和我们通常说的Windows服务,Web的后台服务又有一些相近,它们通常都是后台长时间运行,接受上层指令,完成相关事务的模块。

Android程序设计教程教学大纲

《Android 程序设计课程》课程教学大纲 一、课程基本信息 二、理论教学内容及基本要求

1 Android 操作系统 本章主要对Android 的发展、特点、环境搭建和体系结构进行简要介绍。并且讲解了JDK、Eclipse、Android SDK 软件的下载及安装的基本知识。对Android 应用程序进行解析,提高读者对程序的创建、目录的结构、资源的管理以及对程序权限的理解。最后讲解如何调试Android 程序。 2 Android 生命周期与组件通信 本章主要讲述了Android 生命周期和组件之间的通信。生命周期主要讲述了Android四大组件之一的Activity 生命周期, 包括生命周期函数、栈结构和基本状态三方面。组件的通信靠Intent 实现, 以及Intent 基本构成。 3 Android 用户界面设计 本章主要从Android 用户界面开发出发, 讲述了开发过程中经常使用到的控件, 包括菜单、常用基础控件、对话框与消息框。界面中控件的结构及位置等需要通过有效的界面布局控制, Android 中提供了5 种界面布局格式, 即线性布局、相对布局、表格布局、绝对布局和框架布局。界面中还有一种必要的操作处理———外部操作的响应, 通过有效的事件机制完成。 4 Android 数据存储与交互 本章主要讲述了Android 数据存储与交互方面的内容, 系统中数据交互主要通过五种方式实现, 共享优先数据机制、SQLite 数据库、File 文件机制、内容提供器控件和网络存储。其中在应用程序中最常用也是最有效的数据交互方式是使用SQLite 数据库。 5 Android 后台服务与事件广播 本章主要讲述了Android 后台服务、事件广播和常驻程序。后台服务由系统提供的Service 组件实现, 可分为本地服务和远程服务。事件广播机制主要依靠BroadCast Reciver 组件实现。常驻程序AppWidget又称为窗口小部件, 是在HomeScreen上显示的小部件, 开发时常用AppWidgetProvider 和AppWidgetProviderInfo 类实现。 6 媒介与网络 本章介绍了Android 平台下通过程序实现音频、视频播放等操作。分别介绍了从源文件播放、文件系统播放和流媒体播放等方式。并且介绍了Android 图形绘制与特效, 包括图形的平移、旋转及缩放等操作, 保存指定格式图形文件。编写专业的绘图或控制图形动画的应用程序。以及如何使用Android 手机中内置的高性能WebKit 内核浏览器浏览网页, 使用HTTP 和URL 获得网络资源等内容。 7 Android NDK 本章介绍了Android NDK 的相关知识, 从NDK 的简单介绍到开发环境的

(带答案)Android复习资料

选择题 1. 下面不是Android四大组件之一的(B ) A. Activity B.Intent C. Service D. ContentProvider 2. 下面关于广播叙述错误的是(A) A. 广播是Android四大组件之一 B. BroadcastReceiver有两种注册方式,静态注册和动态注册 C. 静态注册需要在Mainfest.xml中配置 D. 动态注册需要在应用退出时候接触广播的注册。 3. 下面关于BroadcastReceiver错误的是(B): A. BroadcastReceiver有两种注册方式,静态注册和动态注册。 B. BroadcastReceiver必须在AndroidMainfest文件中声明 C. BroadcastReceiver的使用,一定有一方发送广播,有一方监听注册广播,onReceive方法才会被调用。 D. 广播发送的Intent都是隐式启动。 4. 下面关于谁先接收广播顺序错误的是(B) A. 有序广播,优先级高的先接收 B. 有序广播,同优先级的动静态广播接收器,静态优先于动态。 C. 有序广播,同优先级的动态广播接收器,先注册的大于后注册的。 D. 普通广播时,无视优先级,动态广播接收器优先于静态广播接收器 5. 下面关于广播说法错误的是(B) A. 广播分为有序广播和无序广播 B. 使用abortBroadcast方法可以中断所有广播的传递。 C. 广播注册方式分为动态和静态

D. sendOrderBroadcast用来向系统广播有序事件,sendBroadcast()是用来广播无序事件。 6. 下列关于Intent启动组件说法错误的是(C) A.startActivity( ) B. startService( ) C. startBroadcastReceiver() D.startActivityForResult() 7. 对于广播的发送,Intent的启动方式是(B) A.显式启动 B. 隐式启动 C. A和B都可以 D. 以上说法都不正确。 8. 下面关于Notification的说法正确的是(D): A. NotificationManager man = new NotificationManager(); B. PendingIntent contentIntent= new PendingIntent(); C. RemoteViews contentView = new RemoteViews(); D. Notification notification = new Notification(); 9. 关于ContenValues类说法正确的是( A ) A、他和Hashtable比较类似,也是负责存储一些名值对,但是他存储的名值对当中的 名是String类型,而值都是基本类型 B、他和Hashtable比较类似,也是负责存储一些名值对,但是他存储的名值对当中的 名是任意类型,而值都是基本类型 C、他和Hashtable比较类似,也是负责存储一些名值对,但是他存储的名值对当中的 名,可以为空,而值都是String类型 D、他和Hashtable比较类似,也是负责存储一些名值对,但是他存储的名值对当中的名是String类型,而值也是String类型 10.在手机开发中常用的数据库是(A) A,SQLite3 B,Oracle C,Sql Server D,Db23

Android基础应用课程标准

《Android基础》课程标准 一、课程定位 本课程是计算机专业基于Java方向的Android应用层程序开发的一门专业核心课程。作为Java程序设计、数据库原理与应用等课程的后续课程,主要在于培养学生应用Android技术进行Android应用程序开发的能力,并培养其良好的编程规范和职业习惯。 二、课程目标 通过案例驱动的学习和综合训练,熟练掌握Android应用程序开发的基本知识和技能,并能结合Android中的常用控件和四大系统组件进行Android应用程序的开发,并为后续Android高级知识的学习做下铺垫。在课程的学习中,培养诚实、守信、坚韧不拔的性格,培养善于沟通表达、善于自我学习、具备团队协作的能力。并养成规范的编码、按时交付软件等良好的工作态度。 (一)知识目标 1.掌握Android开发环境的搭建;熟悉Android应用的基本框架,了解Activity、layout的关系; 2.指导学生进行需求分析报告的拟定以及实训报告的编写; 3.熟练掌握Android常用的UI组件的用法,熟练使用Android的UI组件来搭建用户界面;掌握Android 中用户事件处理的基本方法; 4.掌握APP系统分层架构的搭建; 5.熟练掌握AdapterView相关UI组件以及Adapter模式、常见Adapter的定义; 6.熟悉Activity、Service和BroadcastReceiver的生命周期方法,熟练掌握它们的用法 7.熟悉Intent的用法,熟练使用Intent的诸多属性用途及用法; 8.熟练掌握Service与广播机制的使用和工作原理,为应用开发打下基础; 9.掌握SQLite的语法,熟练掌握Android SQLite 数据库的使用。能够用多种方式实现数据存储和数据 共享; 10.掌握Android的异步加载机制; 11.了解自定义控件的实现原理并掌握自定义技巧。 12.了解Android应用程序的屏幕适配、国际化方式及APP上架流程和盈利方式。 (二)职业能力目标

Android复习练习题

一、单选题 退出activity对一些资源以及状态的操作保存,可以在生命周期 的哪个函数中进行( A ) A、onPause() B、onCreate() C、onResume() D、onStart() Android项目工程下面的assets目录的作用是什么( B ) A、放置应用到的图片资源。Res/drawable B、主要放置一些文件资源,这些文件会被原封不动打包到apk里面 C、放置字符串,颜色,数组等常量数据res/values D、放置一些与UI相应的布局文件,都是xml文件res/layout 下列不属于android布局的是( C ) A、FrameLayout B、LinearLayout C、BorderLayout D、TableLayout E、RelativeLayout Intent的作用的是( A ) A、intent是连接四大组件的纽带,可以实现界面间切换,可以包含动作和动作数据; B、是一段长的生命周期,没有用户界面的程序,可以保持应用在后台运行,而不会因为切换页面而消失service C、实现应用程序间的数据共享contentprovider D、处理一个应用程序整体性的工作 下列哪个是AbsoluteLayout中特有的属性( B ) A、android:layout_height B、android:layout_x C、android:layout_above D、android:layout_toRightOf RatingBar组件中不能用属性直接设置的是( D) A、五角星个数 B、当前分数 C、分数的增量 D、五角星的色彩 在手机开发中常用的数据库是( A ) A、,sqlLite B、Oracle C、SqlServer D、Db23 关于BroadcastReceiver的说法不正确的是( B ) A)是用来接收广播Intent的 B),一个广播Intent只能被一个订阅了此广播的BroadcastReceiver所接收 C)对有序广播,系统会根据接收者声明的优先级别按顺序逐个执行接收者 D)接收者声明的优先级别在的android:priority属性中声明,数值越大优先级别越高 使用MediaPlayer播放保存在sdcard上的mp3文件时( C ) A)需要使用方法创建MediaPlayer B)直接newMediaPlayer即可 C)需要调用setDataSource方法设置文件源D)直接调用start方法,无需设置文件源在android中使用RadioButton时,要想实现互斥的选择需要用的组件是(D ) A)ButtonGroup B)RadioButtons C)CheckBox D)RadioGroup 在多个应用中读取共享存储数据时,需要用到的query方法,是哪个对象的方法( A ) A)ContentResolver B)ContentProvider C)Cursor D)SQLiteHelper DDMS中Log信息分为几个级别( C ) A)3 B)4 C)5D)6 能够自动完成输入内容的组件是( D )

Android复习练习题

一、单选题 退出 activity 对一些资源以及状态的操作保存,可以在生命周期 的哪个函数中进行( A ) A、onPause() B、onCreate() C、onResume() D、onStart() Android 项目工程下面的 assets 目录的作用是什么 ( B ) A、放置应用到的图片资源。 Res/drawable B、主要放置一些文件资源,这些文件会被原封不动打包到 apk 里面 C、放置字符串,颜色,数组等常量数据 res/values D、放置一些与 UI 相应的布局文件,都是 xml 文件 res/layout 下列不属于android布局的是( C ) A、FrameLayout B、LinearLayout C、BorderLayout D、TableLayout E、RelativeLayout Intent 的作用的是 ( A ) A、intent是连接四大组件的纽带,可以实现界面间切换,可以包含动作和动作数据; B、是一段长的生命周期,没有用户界面的程序,可以保持应用在后台运行,而不会因为切换页面而消失 service C、实现应用程序间的数据共享 contentprovider D、处理一个应用程序整体性的工作 下列哪个是AbsoluteLayout中特有的属性 ( B ) A、android:layout_height B、android:layout_x C、android:layout_above D、android:layout_toRightOf RatingBar组件中不能用属性直接设置的是( D) A、五角星个数 B、当前分数 C、分数的增量 D、五角星的色彩 在手机开发中常用的数据库是( A ) A、,sqlLite B、Oracle C、Sql Server D、Db23 关于BroadcastReceiver的说法不正确的是( B ) A)是用来接收广播Intent的 B),一个广播Intent只能被一个订阅了此广播的BroadcastReceiver所接收 C)对有序广播,系统会根据接收者声明的优先级别按顺序逐个执行接收者 D)接收者声明的优先级别在的android:priority属性中声明,数值越大优先级别越高 使用MediaPlayer播放保存在sdcard上的mp3文件时( C ) A)需要使用MediaPlayer.create方法创建MediaPlayer B)直接newMediaPlayer即可C)需要调用setDataSource方法设置文件源D)直接调用start方法,无需设置文件源在android中使用RadioButton时,要想实现互斥的选择需要用的组件是(D ) A)ButtonGroup B) RadioButtons C)CheckBox D)RadioGroup 在多个应用中读取共享存储数据时,需要用到的query方法,是哪个对象的方法?( A ) A)ContentResolver B)ContentProvider C)Cursor D)SQLiteHelper DDMS中Log信息分为几个级别( C ) A)3 B)4 C)5 D)6 能够自动完成输入内容的组件是( D )

Android应用开发经典面试题

Android应用开发经典面试题 1、Android的四大组件是哪些,它们的作用? 答:Activity:Activity是Android程序与用户交互的窗口,是Android构造块中最基本的一种,它需要为保持各界面的状态,做很多持久化的事情,妥善管理生命周期以及一些跳转逻辑 service:后台服务于Activity,封装有一个完整的功能逻辑实现,接受上层指令,完成相 关的食物,定义好需要接受的Intent提供同步和异步的接口 Content Provider:是Android提供的第三方应用数据的访问方案,可以派生Content Provider类,对外提供数据,可以像数据库一样进行选择排序,屏蔽内部数据的存储细节,向外提供统一的借口模型,大大简化上层应用,对数据的整合提供了更方便的途径 BroadCast Receiver:接受一种或者多种Intent作触发事件,接受相关消息,做一些简单 处理,转换成一条Notification,统一了Android的事件广播模型 2、请介绍下Android中常用的五种布局。 常用五种布局方式,分别是:FrameLayout(框架布局),LinearLayout(线性布局),AbsoluteLayout(绝对布局),RelativeLayout(相对布局),TableLayout(表格布局)。 一、FrameLayout:所有东西依次都放在左上角,会重叠,这个布局比较简单,也只能放 一点比较简单的东西。 二、LinearLayout:线性布局,每一个LinearLayout里面又可分为垂直布局 (android:orientation=”vertical”)和水平布局(android:orientation=”horizontal”)。当垂直布局时,每一行就只有一个元素,多个元素依次垂直往下;水平布局时,只有一行,每一个元素依次向右排列。 三、AbsoluteLayout:绝对布局用X,Y坐标来指定元素的位置,这种布局方式也比较简单,但是在屏幕旋转时,往往会出问题,而且多个元素的时候,计算比较麻烦。 四、RelativeLayout:相对布局可以理解为某一个元素为参照物,来定位的布局方式。主 要属性有:相对于某一个元素android:layout_below、android:layout_toLeftOf相对于父 元素的地方android:layout_alignParentLeft、android:layout_alignParentRigh;五、TableLayout:表格布局,每一个TableLayout里面有表格行TableRow,TableRow里面可以具体定义每一个元素。每一个布局都有自己适合的方式,这五个布局元素可以相互嵌套应用,做出美观的界面。

Android四大组件的详细讲解

Android应用程序由一些零散的有联系的组件组成,通过一个工程manifest绑定在一起。在manifest中,描述了每一个组件以及组件的作用,其中有6个组件,它们是Android 应用程序的基石: Activities(活动)应用程序的显示层。每一个画面对应于你的应用程序,将会是Activity类的扩展。Activity使用Views去构建UI来显示信息和响应用户的行为。就桌面开发而言,一个Activity相当于一张Form。你在这章中将会学习到更多关于Activities。 Services(服务)Android应用程序中不可见的“工人”。Service组件运行时不可见,但它负责更新的数据源和可见的Activity,以及触发通知。它们常用来执行一些需要持续运行的处理,当你的Activity已经不处于激活状态或不可见。你将在第8章学习怎样创建Service。 Content(内容)提供共享的数据存储。Content Provider(内容提供器)用来管理和共享应用程序的数据库。在应用程序间,Content Provider是共享数据的首选方式。这意味着,你可以配置自己的Content Provider去存取其他的应用程序或者通过其他应用程序暴露的Content Provider去存取它们的数据。Android设备本身包含了几个Content Provider来访问像联系人信息等有用的数据库。你将在第6章学习怎样创建和使用Content Provider。 Intents(意图)简单的消息传递框架。使用Intent,你可以在整个系统内广播消息或者给特定的Activity或者服务来执行你的行为意图。系统会决定那个(些)目标来执行适当的行为。 Broadcast Receivers(广播接收器)Intent广播的“消费者”。通过创建和注册一个Broadcast Receiver,应用程序可以监听符合特定条件的广播的Intent。Broadcast Receiver 会自动的启动你的Android应用程序去响应新来的Intent。Broadcast Receiver是事件驱动程序的理想手段。 Notifications(通知)用户通知的框架。Notification用来在不需要焦点或不中断它们当前Activity的情况下提示用户。它们是Service或Broadcast Receiver获得用户注意的首选方式。例如,当设备收到文本信息或外部来电时,它通过闪光,发声,显示图标或显示对话框信息来提醒你。在第8章里,你可以使用Notification来触发这些事件。 一、Activity详解 Activty的生命周期的也就是它所在进程的生命周期。

Android选择题集锦

下面关于Android dvm的进程和Linux的进程,应用程序的进程说法正确的是? 选择一项: a. DVM指dalivk的虚拟机.每一个Android应用程序都在它自己的进程中运行,不一定拥有一个独立的Dalvik虚拟机实例.而每一个DVM都是在Linux中的一个进程,所以说可以认为是同一个概念. b. DVM指dalivk的虚拟机.每一个Android应用程序都在它自己的进程中运行,不一定拥有一个独立的Dalvik虚拟机实例.而每一个DVM不一定都是在Linux 中的一个进程,所以说不是一个概念. c. DVM指dalivk的虚拟机.每一个Android应用程序都在它自己的进程中运行,都拥有一个独立的Dalvik 虚拟机实例.而每一个DVM 不一定都是在Linux 中的一个进程,所以说不是一个概念. d. DVM指dalivk的虚拟机.每一个Android应用程序都在它自己的进程中运行,都拥有一个独立的Dalvik虚拟机实例.而每一个DVM都是在Linux 中的一个进程,所以说可以认为是同一个概念. 题目2 下列选项哪个不是Activity启动的方法? a. goToActivity b. startActivity c. startActivityFromChild d. startActivityForResult 题目3 解析xml 的方式有() a. 字符器类型 b. 流方式 c. dom d. SAX 题目4 下列哪一个不属于Activity的生命周期方法? a. onInit( ) b. onStart( ) c. onStop( ) d. onPause( )

ANDROID应用开发试题

Android应用开发试题 一、选择题(每题2分,共30分) 1.下列不是手机操作系统的是?()D A.Android B.Window Mobile C.Apple IPhone IOS D.windows vista 2.Android的VM虚拟机是哪个?A A.Dalvik B.JVM C.KVM D.framework 3.AndroidVM虚拟机中运行的文件的后缀名为()C A.class B.apk C.dex D.xml 4.下列选项是Activity启动的方法有()ACD A.startActivity B.goToActivity C.startActivityForResult D.startActivityFromChild 5.下列哪个可做EditText编辑框的提示信息?()D A.android:inputType B.android:text C.android:digits D.android:hint 6.关于Activity的描述,下面哪个是错误的?AD A.一个Android程序中只能拥有一个Activity类 B.Activity类都必须在Androidmaniefest.xml中进行声明 C.系统完全控制Activity的整个生命周期 D.Activity类必须重载onCreate方法 7.关于widget(组件)属性的写法,下面哪个是正确的?ABC A.android:id=”@+id/tv_username” B.android:layout_width=”100px” C.android:src=”@drawable/icon” D.android:id="@id/tabhost" 8.下面哪个不是Android SDK中的ViewGroup(视图容器)?D A.LinearLayout B.ListView C.GridView D.Button 9.下列哪个不是Activity的生命周期方法之一?()B A.onCreate B.startActivity C.onStart D.onResume 10.MediaPlayer对象从停止状态到播放状态调用的方法是()AB A.prepare() B.start() C.reset() D.release() 11.下面说法错误的是()BC A.Android采用单线程模型 B.Android会默认会为线程创建一个关联的消息队列 C.Handler会与多个线程以及该线程的消息队列对应 D.程序组件首先通过Handler把消息传送给Looper,Looper把消息放入队列12.android中下列属于Intent的作用的是()C A实现应用程序间的数据共享 B是一段长的生命周期,没有用户界面的程序,可以保持应用在后台运行,而不会因为切换页面而消失 C可以实现界面间的切换,可以包含动作和动作数据,连接四大组件的纽带D处理一个应用程序整体性的工作 13.关于应用程序的生命周期,一个Activity从启动到运行状态需要执行3个方

android面试题目--答案

Android笔试题 一、选择题 1. 对一些资源以及状态的操作保存,最好是保存在生命周期的哪个函数中进行 (d) A、onPause() B、onCreate() C、 onResume() D、onStart() 2. android 中下列属于Intent的作用的是(c) A、实现应用程序间的数据共享 B、是一段长的生命周期,没有用户界面的程序,可以保持应用在后台运行,而不会因为切换页面而消失 C、可以实现界面间的切换,可以包含动作和动作数据,连接四大组件的纽带 D、处理一个应用程序整体性的工作 3. 下面的对自定style的方式正确的是(a) A、 B、 C、 fill_parent D、 4. android 关于service生命周期的onCreate()和onStart()说确的是(ad)(多选题) A、当第一次启动的时候先后调用onCreate()和onStart()方法 B、当第一次启动的时候只会调用onCreate()方法 C、如果service已经启动,将先后调用onCreate()和onStart()方法 D、如果service已经启动,只会执行onStart()方法,不在执行onCreate()方法 5. Android项目工程下面的assets目录的作用是什么b A、放置应用到的图片资源。 B、主要放置多媒体等数据文件 C、放置字符串,颜色,数组等常量数据 D、放置一些与UI相应的布局文件,都是xml文件

Android期末考试复习试卷(仅供参考)

一、选择题(20分,每小题2分) 1、下列不是手机操作系统的是( D )。 A Android B Window Mobile C Apple IPhone IOS D Windows Vista 2、下列选项哪个不是Activity 启动的方法(B ) A startActivity B goToActivity C startActivityForResult D startActivityFromChild 3、下列哪个不是Activity 的生命周期方法之一(B ) A onCreate B startActivity C onStart D onResume 4、下列哪个可做Android 数据存储(A ) A SQlite B M ySql C Oracle D DB2 5、下列哪个可做EditText编辑框的提示信息( D ) A android:inputType B android:text C android:digits D android:hint 6、Math.ceil(99.1) 的结果是(B ) A 99 B 100 C 99.1 D 99.0 7、android 中下列属于Intent的作用的是(C) A实现应用程序间的数据共享 B是一段长的生命周期,没有用户界面的程序,可以保持应用在后台运行,而不会因为切换页面而消失 C可以实现界面间的切换,可以包含动作和动作数据,连接四大组件的纽带 D处理一个应用程序整体性的工作 8、关于res/raw 目录说法正确的是A A这里的文件是原封不动的存储到设备上不会转换为二进制的格式 B这里的文件是原封不动的存储到设备上会转换为二进制的格式 C这里的文件最终以二进制的格式存储到指定的包中 D这里的文件最终不会以二进制的格式存储到指定的包中 9、Math.round(11.5)等于多少(). Math.round(-11.5)等于多少( C) A 11 ,-11 B 11 ,-12 C 12 ,-11 D 12 ,-12 10、我们都知道Hanlder是线程与Activity通信的桥梁,如果线程处理不当,你的机器就会变得越慢,那么线程销毁的方法是(A ) A onDestroy() B onClear() C onFinish() D onStop() 二、填空题(10 分,共10 题,每空1 分) 1、为了使android 适应不同分辨率机型,布局时字体单位应用( sp ),像素 单位应用( sp )和(dip ) 2、定义LinearLayout 水平方向布局时至少设置的三个属性:( android:orientation),(android:layout width)和(android:layout height) 3、layout 布局文件的命名不能出现字母(大写)

Android四大组件的ContentProvider实例——获取联系人

Android四大组件的ContentProvider实例——获取联系人 1.ContentProvider简述 ContenttProvider(以下简称CP)是为了获取不同应用之间的数据而诞生的组件,并且官方为常见的一些数据提供了默认的CP。例如,联系人、短信等。 CP的几点关键: Uri:是CP的标志符,是识别CP的唯一方式。 ContentResolver:对CP进行操作的类。 权限:有时候操作一些地方需要一些权限。 2.获取联系人实现思路

3.具体实现3.1 申请权限

android6.0不仅要在AndroidManifest.xml中静态申请,还需要在代码中进行动态申请。 静态申请 在AndroidManifest.xml中进行申请。 动态申请 动态申请的流程为:发起申请和申请结果。 发起申请: 主要使用requestPermissions(permission名字的数组,整型的自定义reques code)方法 注: 什么时候进行动态申请呢?版本大于等于6.0且当前页面没有这个权限。

request code 为自定义数值,例子中我定义了一个常量 int--PERMISSIONS_REQUEST_READ_CONTACTS,这个是为了在查看申请结果时判定用的。 private void showContacts() { //检验是否版本大于6.0,当前页面是否有这个权限 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) { //发起申请 requestPermissions(new String[]{Manifest.permission.READ_CONTACTS}, PERMISSIONS_REQUEST_READ_CONTACTS); } else { //低版本直接运行,跳过动态申请。 readContacts(); } } 申请结果 重写onRequsetPermissionResult(int requestCode,String[] permissions,int[] grantResults)方法。

A03_a_Android应用框架的四大组件

A03_a_Android應用框架的四大組件?4個嫡系基類: Activity Service BroadcastReceiver ContentProvider Android母框架裡提供了4個一等公民(或稱為嫡系)的基類,包括: ●Activity: 處理UI互動的事情 ●Service:幕後服務(如硬件及Driver的服務) ●BroadcastReceiver: 接收訊息及事件處理 ●ContentProvider: 儲存共用資料 如下圖所示: 圖1 Android 框架裡的4個嫡系基類 基於這些基類,地頭蛇就可以撰寫AP子類,如下圖:

圖2 平台與應用兩種知識的結合 這4種應用子類都是由Android框架來負責創建(Create or New)其對象(Object)的。不過有趣的是: ●平台框架基類寫在先 ●應用子類寫在後 那麼框架事先又如何知道應用開發者後來撰寫的應用子類的名稱呢? 如果不知道應用子類的名稱,又如何創建應用子類的對象呢? 答案是:依賴AndroidManifest.xml文檔。例如: // AndroidManifest.xml

Android四大组件——Service后台服务、前台服务、IntentService、跨进程服务、无障碍服务、系统服务

Android四大组件——Service后台服务、前台服务、IntentService、跨进程服务、无障碍服务、系统服务 Service简介 Service是Android中实现程序后台运行的解决方案,它非常适用于去执行那些不需要和用户交互而且还要求长期运行的任务。Service默认并不会运行在子线程中,它也不运行在一个独立的进程中,它同样执行在UI线程中,因此,不要在Service中执行耗时的操作,除非你在Service中创建了子线程来完成耗时操作 Service的运行不依赖于任何用户界面,即使程序被切换到后台或者用户打开另一个应用程序,Service仍然能够保持正常运行,这也正是Service的使用场景。当某个应用程序进程被杀掉时,所有依赖于该进程的Service也会停止运行 后台服务 后台服务可交互性主要是体现在不同的启动服务方式,startService()和bindService()。bindService()可以返回一个代理对象,可调用Service中的方法和获取返回结果等操作,而startService()不行 不可交互的后台服务 不可交互的后台服务即是普通的Service,Service的生命周期很简单,分别为onCreate、onStartCommand、onDestroy这三个。当我们startService()的时候,首次创建Service会回调onCreate()方法,然后回调onStartCommand()方法,再次startService()的时候,就只会执行一次onStartCommand()。服务一旦开启后,我们就需要通过stopService()方法或者stopSelf()方法,就能把服务关闭,这时就会回调onDestroy() 一、创建服务类 创建一个服务非常简单,只要继承Service,并实现onBind()方法 public class BackGroupService extends Service { /** * 綁定服务时调用 * * @param intent * @return */ @Nullable

AnjoyoAndroid07课后习题

AnjoyoAndroid07课后习题 一、选择题: 1.下面关于Service的描述有误的一项是()。 A、Service运行在主线程中,可以执行各种后台操作,比如数据计算、多媒体播放、下 载文件等等。 B、Service是不提供用户界面而在后台完成各种耗时操作的组件,译为“服务”。 C、Service与Activity一样,也是Android的四大组件之一,与Activity相同,也使用 Intent对象激活Service。 D、Service、Intent、Activity和ContentProvider被并称为Android的四大组件。 2.下面关于Service的说法不正确的一项是()。 A、Service是Android系统的后台服务组件,适用于开发无界面、长时间运行的应用功 能。 B、Activity比Service的优先级高,不会轻易被Android系统终止。 C、应用程序组件可以启动一个服务(Start a Service),即使用户切换到另一个应用程 序,它仍然会继续在后台运行。 D、一个组件还可以绑定到一个与它进行交互、甚至进行进程间通信(IPC)的服务(Bind a Service),比如处理网络交易、播放音乐、执行文件I / O操作的服务。 3.下列关于Service说法错误的一项是()。 A、Android中,Service有两种不同的使用方式,一种是以启动方式使用Service(Started Service),另一种是以绑定方式使用Service(Bound Service)。 B、需要在AndroidManifest.xml文件中注册,否则,Service根本无法启动。 C、以绑定方式使用Service,能够获取到Service对象,不仅能够正常启动Service,而 且能够调用正在运行中的Service实现的私有方法和属性。 D、为了使Service支持绑定,需要在Service类中重写onBind()方法,并在onBind()方 法中返回Service对象。 4.下列关于Service绑定说法有误的一项是()。 A、如果绑定成功,则会通过getService()获取Service对象,这样便可以调用Service中 的方法和属性。 B、如果绑定意外失败,会将Service对象设置为null,表示绑定意外失效,Service实 例不再可用。 C、绑定一个Service就可以开启并使一个Service处于运行状态。 D、以绑定方式使用Service时,调用者需要声明一个ServiceConnnection对象,但可以 不用重写它的onServiceConnected()和onServiceDisconnected()方法。 5.下面关于Service描述错误的一项是()。 A、取消绑定仅需要使用unbindService()方法,并将ServiceConnnection对象传递给 unbindService()方法即可。 B、以启动方式使用Service时,使用startService()方法的目的是回调onStart()方法。 C、以绑定方式使用Service时,使用bindService()方法的目的是回调onBind()方法,它 的作用是在Service和调用者之间建立一个桥梁。 D、一般会把要在应用程序被关闭后仍然需要执行的操作实现为一个绑定式的Service, 而将一些执行特定功能、执行周期短或在应用程序关闭后将要停止的操作实现为启动式

相关主题
相关文档 最新文档