Android ContentResolver 内容解析者(解析器)----重新认识Android(11)

ContentResolver 内容解析者(解析器)
一、Content Provider (内容 提供者 )简介:
 
(一)、引入:
          数据库在Android当中是私有的 ,不能将数据库设为WORLD_READABLE, 每个数据库都只能创建它的包访问 。这意味着 只有创建这个数据库的应用程序才可访问它 。也就是说不能跨越进程和包,直接访问别的应用程序的数据库。那么如何在应用程序间交换数据呢?可以使用ContentProvider(内容提供者)来实现。这样就更加安全可靠(想从我家借东西,你不能直接进来拿,要我拿给你).
为什么要暴露数据呢?系统中的电话簿,短信,媒体库等数据,其他app希望访问.
 
(二)、ContentProvider的功能和意义:
        为了在应用程序之间交换数据,Android提供了 ContentProvider ,它是不同应用程序之间进行数据交换的标准API。
当一个应用程序需要把自己的数据暴露给其他应用程序使用时,该应用程序可以通过提供ContentProvider来实现;
        而其他应用程序需要使用这些数据时,不管提供数据的应用程序是否启动,可以通过 ContentResolver 来操作ContentProvider暴露的数据。包括增加数据insert()、删除数据delete()、修改数据update()、查询数据query()等。
        虽然大部分使用ContentProvider操作的数据都来自于数据库,但是也可以来自于文件、SharedPreferences、XML或网络等其他存储方式。
 
(三)、核心类:
1、 ContentProvider 内容提供者 :(需要暴露数据的A应用程序--类似于服务器端)
可以通过继承一个 ContentProvider 抽象类 将自己的数据暴露出去;
A应用通过Uri向外暴露数据。只要将A应用安装到手机上。无论是否运行,其他应用都可以从A应用获取数据。
外界不知道,也无需知道A应用暴露的数据在A应用当中是如何存储的,(是用数据库存储还是用文件存储,还是通过网上获得),外界可以通过一套标准的接口 读取或修改A应用里的数据.
   
2、 ContentResolver  内容解析者 :(访问操作A应用所暴露的数据--类似于客户端)
外界的程序通过 ContentResolver 可以访问 ContentProvider 提供的数据;
 
3、 Uri统一资源标识符: Uri是ContentResolver和ContentProvider进行数据交换的标识。
例如一个Uri是  content://com.qf.day16_contentprovider_t/user/5
Uri  的标准前缀 (协议protocal) :以“ content:// ”作为前缀,表示该数据由   ContentProvider  管理。
Uri  的 authority 部分(授权,权限):" com.qf.day16_contentprovider_t "该部分是暴露数据的app的包名。(要求小写)。
Uri  的 path 部分(路径):  " user " 用于判断请求的路径(哪些数据被请求)。
被请求的特定记录的 id 值[可选的]: "5" 如果请求不仅限于某个单条数据,该部分及其前面的斜线应该删除。
将一个字符串转换成Uri的方式:   Uri uri = Uri.parse("..............")
【备注:】URI、URL的区别:
首先,URI,是 uniform resource identifier ,统一资源标识符,用来唯一的标识一个资源。
URL是 uniform resource locator ,统一资源定位器, 它是一种具体的URI ,即URL可以用来标识一个资源,而且还指明了如何 定位 这个资源。
        也就是说,URI是以一种抽象的,高层次概念定义统一资源标识,而URL则是具体的资源标识的方式。可以认为 URL是一种具体的URI ,它不仅唯一标识资源,而且还提供了定位该资源的信息。URI是一种语义上的抽象概念,可以是绝对的,也可以是相对的,
而URL则必须提供足够的信息来定位,所以,是绝对的。


二、使用 ContentResolver  管理通话记录:
查询手机通话记录,可以利用上下文菜单删除通话记录
整个通话记录列表lv
上下文菜单中的删除项:action_delete
通话记录编号tv_id
对方电话号码tv_number
通话开始时间tv_date
通话类型(呼出/呼入/未接)tv_type
注意需要申请权限,否则运行会出现异常:WRITE_CALL_LOG,READ_CALL_LOG
/**
 * ContentProvider内容提供者 1.主要用于不同的应用程序之间,共享数据的。
A:ContentProvider:向外提供数据的
 * 用于通过Uri向外暴露数据。只要将应用安装到手机上。无论是否运行,都可以获取数据。
B:ContentResolver:获取并解析数据
 * 用于解析通过ContentProvider暴露 出来的数据。 A应用暴露出的是Uri,B应用使用该Uri就可以访问A应用暴露出来的数据了。
 * =====================================================
 * 本例用于实现通过ContentResovler来获取手机中通话记录
 * 通话记录存储在内部存储的系统应用目录中:data/data/com.android.providers.contacts/contacts2.db
 * 对外暴露的Uri:"content://call_log/calls"
 * step1:通过 getContentResolver ()获取ContentResovler对象
 * step2:获取通话记录的Uri:"content://call_log/calls"
 * step3:执行查询:ContentResovler对象.query(uri,查询的字段, 条件,条件的参数,排序依据);
 * step4:添加权限: READ_CALL_LOG  读取通话记录, WRITE_CALL_LOG  写通话记录 通话记录表的核心字段" _id ",
 * " number "电话号码, " date "时间(毫秒值), " type ": 1:呼入 2:呼出 3:未接
 */
public class Main3Activity extends AppCompatActivity {

    // step2:提供要解析数据对应的Uri,就是电话记录的uri
    private Uri uri_callLog = CallLog.Calls.CONTENT_URI;// 系统提供的常量,表示通话记录对外暴露的Uri
    // 上面常量的值就是 Uri.parse("content://call_log/calls")得到的结果.
    private ContentResolver contentResolver;
    private ListView lv_listview;
    private MyCursorAdapter adapter;// 自定义的适配器类对象

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main3);
        lv_listview = (ListView) findViewById(R.id.lv_listview);
        // step1:获取ContentResolver
        contentResolver = getContentResolver();
        queryCallLog();// 调用自定义的方法,用于查询并显示通话记录
        // 注册 上下文菜单:可以删除某个通话记录
        registerForContextMenu(lv_listview);
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
        super.onCreateContextMenu(menu, v, menuInfo);
        getMenuInflater().inflate(R.menu.call_menu, menu);// 上下文菜单,只有一个"删除"选项
    }

    // 上下文菜单点击时间处理
    @Override
    public boolean onContextItemSelected(MenuItem item) {
        AdapterView.AdapterContextMenuInfo menuInfo = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
        int position = menuInfo.position;// 获得弹出上下文菜单时所选中的条目的位置
        Cursor cursor = adapter.getCursor();// 调用CursorAdapter的获取cursor对象的方法
        cursor.moveToPosition(position);// 把cursor作为数据源,移动到指定位置
        int id = cursor.getInt(cursor.getColumnIndex("_id"));// 通话记录表calls中的字段
        switch (item.getItemId()) {
            case R.id.action_delete:
                // 删除一条记录
                int count = deleteCallLog(id);// 调用自定义的删除通话记录的方法
                if (count > 0) {
                    Toast.makeText(Main3Activity.this, "删除成功", Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(Main3Activity.this, "删除失败", Toast.LENGTH_SHORT).show();
                }
                break;
            default:
                break;
        }
        queryCallLog();// 调用自定义的重新查询的方法
        return super.onContextItemSelected(item);
    }

    /**
     * 删除一条指定的通话记录
     *
     * @param id
     * @return
     */
    public int deleteCallLog(int id) {
        int count = contentResolver.delete(uri_callLog, "_id=?", new String[]{id + ""});// 也可以第二个参数传"_id="+id,第三参数传null
        return count;
    }

    /**
     * 通过contentResolver,查询uri所指向的通话记录数据
     * 第一个参数:要操作的应用暴露出的uri。指向通话记录的数据
     * 第二个参数:要查询的字段
     * 第三个参数:查询的条件
     * 第四个参数:条件的参数值
     * 第五个参数:排序
     */
    // 查询数据
    public void queryCallLog() {
        // step3:通过contentResolver获取数据
        //Uri uri,String[] projection列名数组,String selection查询条件,String[] selectionArgs替换占位符的数组,String sortOrder
                Cursor cursor = contentResolver.query(uri_callLog, new String[]{"_id", "number", "date", "type"}, null, null, "date desc");
        // SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
        // R.layout.item_listview, cursor, new String[] { "_id", "number",
        // "date", "type" }, new int[] { R.id.tv_id,
        // R.id.tv_number, R.id.tv_date, R.id.tv_type },
        // CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);//这样填进去日期就只能显示成毫秒数了,不美观

        // 因此可以使用继承CursorAdapter的自定义适配器来适配Cursor数据
        // 父类CursorAdapter没有无参的构造方法,必须如此传参:
        adapter = new MyCursorAdapter(this, cursor, CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER); // 最后一个参数表示,如果数据源发生变化则在后面学习的Loader中可以动态更新.
        lv_listview.setAdapter(adapter);
    }

    // 自定义的继承抽象类CursorAdapter的适配器
    class MyCursorAdapter extends CursorAdapter {
        // 继承抽象类,重写两个抽象方法
        public MyCursorAdapter(Context context, Cursor c, int flags) {
            super(context, c, flags);// 父类没有无参的构造方法,必须如此传参
        }

        @Override
        public View newView(Context context, Cursor cursor, ViewGroup parent) {
            // 指定布局文件,生成一个条目的View对象,注意,在内部类中,上下文是MainActivity.this
            return LayoutInflater.from(Main3Activity.this).inflate(R.layout.item_listview, null);
        }

        @Override
        public void bindView(View view, Context context, Cursor cursor) {
            // 填充数据到每个条目的内部组件上,类似于继承BaseAdapter中重写getView()方法
            TextView tv_id = (TextView) view.findViewById(R.id.tv_id);
            TextView tv_number = (TextView) view.findViewById(R.id.tv_number);
            TextView tv_date = (TextView) view.findViewById(R.id.tv_date);
            TextView tv_type = (TextView) view.findViewById(R.id.tv_type);
            // 从cursor获取数据,显示到textview上
            tv_id.setText("" + cursor.getInt(cursor.getColumnIndex("_id")));
            tv_number.setText(cursor.getString(cursor.getColumnIndex("number")));
            long dateNum = cursor.getLong(cursor.getColumnIndex("date"));// 获取以毫秒表示的date数据
            Date date = new Date(dateNum);// 利用毫秒数构建Date对象
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            tv_date.setText(sdf.format(date));
            int typeNum = cursor.getInt(cursor.getColumnIndex("type"));
            if (typeNum == 1) {
                tv_type.setText("呼入");
            } else if (typeNum == 2) {
                tv_type.setText("呼出");
            } else {
                tv_type.setText("未接");
            }
        }
    }
}

/**
 * 短信息的程序的数据库文件:/data/data/com.android.providers.telephony/mmssms.db
 * Uri:content://sms
 * step1:获取contentResolver对象
 * step2:获取短信息的Uri
 * step3:查询,插入
 * step4:添加权限: READ_SMS , WRITE_SMS
 * @author  Administrator
 * 核心字段: _id , address 电话号码, body 信息文本, type 类型(1.接收;2.发送), date 时间(毫秒)
 */
四、使用 ContentResolver  查询 联系人
(一)、 [总结]使用ContentResolver 操作数据的步骤:
1、调用Context的 getContentResolver ()方法获得ContentResolver 对象;
2、调用ContentResolver 的 query() 方法查询数据。
· Cursor  query (Uri  uri , String[]  projection , String where, String[] whereArgs, String sortOrder)
参数解释:
String[]    projection :表示select语句中需要查询的所有的字段组成的字符串数组。
String   where:表示带有 占位符 的where子句组成的字符串;
String[]   whereArgs:表示 替换 where参数中 占位符 的数据组成的字符串数组;
String   sortOrder:表示select语句中的order by子句组成的字符串;
 
(二)、  联系人中 管理ContentProvider的几个Uri: 
1、联系人的Uri==>      content://com.android.contacts/ raw_contacts  
2、电话/邮件地址等数据的Uri==>  content://com.android.contacts/ data
 
数据库位置 :/data/data/com.android.providers.contacts/databases/contacts2.db
用可视化工具打开(例如SQLite Expert)
核心表:
1.raw_contacts原始联系人表
"_id":联系人的id
"display_name":联系人的姓名 
2.data数据表
"raw_contact_id":作为外键参照raw_contacts表的_id字段
"data1":具体数据,例如手机号,email,姓名等
"mimetype_id":数据的大类型,例如
1:email; 5:电话; 7:姓名; 在mimetypes表中对应于_id字段
3.mimetypes表
"_id":类型id
"mimetype":具体类型,例如_id为7的mimetype是 vnd.android.cursor.item/name
1 电子邮件
2 即时通讯
3 昵称
4 组织,单位
5 电话号码
6 邮编
7 名字
8 地址
9 身份证识别号
10 头像
11 组群
/**
 * 操作手机的联系人: 应用程序数据所在的位置:/data/data/com.android.providers/contacts/contacts2.db
 * step1:获取ContentResolver对象
 * step2:提供Uri 1、联系人的Uri==>
 * content://com.android.contacts/raw_contacts
 * 2、电话/邮件地址等数据的Uri==> content://com.android.contacts/data
 * step3:执行查询
 * step4: 添加权限 : READ_CONTACTS
 *
 * @author  Administrator
 */
public class MainActivity extends Activity implements OnClickListener {
private Uri uri_raw_contact = Uri.parse("content://com.android.contacts/raw_contacts");// raw_contacts表
private Uri uri_data = Uri.parse("content://com.android.contacts/data");
private ContentResolver contentResolver;
private ListView lv_listview;
private Button btn_queryData; 
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
contentResolver = getContentResolver();
initView();// 自定义的获取组件引用和注册监听器的方法
queryContacts();// 自定义的查询联系人的方法
}
 
public void initView() {
lv_listview = (ListView) findViewById(R.id.lv_listview);
btn_queryData = (Button) findViewById(R.id.btn_queryData);
btn_queryData.setOnClickListener(this);
}
 
/**
 * 获取联系人的信息,并且显示到listview上。 用SimpleAdapter进行适配
 */
public void queryContacts() {
List<Map<String, String>> list = getDataContacts();// 自定义的方法,获取联系人的信息List
// 仅用于展示信息,可以直接使用SimpleAdapter
SimpleAdapter adapter = new SimpleAdapter(this, list, R.layout.item_listview,
new String[] { "_id", "display_name", "phone", "email" },
new int[] { R.id.tv_id, R.id.tv_display_name, R.id.tv_phone, R.id.tv_email });
lv_listview.setAdapter(adapter);
}
 
// 自定义的用于查询联系人的方法
public List<Map<String, String>> getDataContacts() {
List<Map<String, String>> list = new ArrayList<Map<String, String>>();//初始化结果集
// A:查询raw_contact表,为了得到_id,display_name.
Cursor cursor = contentResolver.query(uri_raw_contact, new String[] { "_id", "display_name" }, null, null,null);
while (cursor.moveToNext()) {
Map<String, String> map = new HashMap<String, String>();
String _id = cursor.getString(cursor.getColumnIndex("_id"));
String display_name = cursor.getString(cursor.getColumnIndex("display_name"));
map.put("_id", _id);
map.put("display_name", display_name);
// B:根据查询到_id,查询data表,获取到data1, mimetype字段:
// select data1,mimetype from data where raw_contact_id = _id:
Cursor cursor2 = contentResolver.query(uri_data, new String[] { "data1", "mimetype" }, "raw_contact_id=?",new String[] { _id }, null);
// 存储的是_id对应的联系人的信息:
String email = "";
String phone = "";
String address = "";
 
while (cursor2.moveToNext()) {
String data = cursor2.getString(cursor2.getColumnIndex("data1"));
String mimetype = cursor2.getString(cursor2.getColumnIndex("mimetype"));// 虽然data表没有这个字段,只有mimetype_id字段,但此处必须这样获取,且获取回来的是一个类似于"vnd.android.cursor.item/email_v2"的字符串
if ("vnd.android.cursor.item/email_v2".equals(mimetype)) {
email = email + "|" + data;// 如果mimetype的值为email,表示此处的data中的数据是电子邮箱
} else if ("vnd.android.cursor.item/phone_v2".equals(mimetype)) {// 电话(有可能有手机的,座机的,家庭的,单位的...)
phone = phone + "|" + data;
} else if ("vnd.android.cursor.item/postal-address_v2".equals(mimetype)) {// 地址
address = address + "|" + data;
}
}
map.put("phone", phone);
map.put("email", email);
map.put("address", address);
 
list.add(map);//把一个联系人的所有信息存入map后,再将map存入list
}
return list;
}
// 点击按钮,实现查询功能
@Override
public void onClick(View v) {
queryContacts();//调用自定义的方法
}
}
一、自定义ContentProvider:
  (一)、操作步骤:
1、自己编写一个类,必须继承自 ContentProvider 类;
2、实现ContentProvider类中所有的抽象方法;
    需要实现: onCreate () 、 getType()  、 query () 、 insert () 、 update ()、 delete () 等方法。
【备注:】
ContentProvider暴露出来的数据和方法是给其他应用程序来调用。
其他应用程序通过ContentResolver对象调用 query () 、 insert () 、 update ()、 delete () 等。
3、定义ContentProvider的Uri。这个Uri是ContentResolver对象执行CRUD操作时重要的参数;
4、使用UriMatcher对象映射Uri返回代码 ;【超纲】
5、在AndroidMainfest.xml文件中使用<provider>标签注册ContentProvider。
 
(二)、ContentProvider类中的六个抽象方法:
1、boolean  onCreate ()  初始化provider
  注意没有ContentResolver试图访问你的Provider之前,它不会创建出来.
2、Uri  insert (Uri uri, ContentValues values)  插入新数据到ContentProvider
3、int  delete (Uri uri, String selection, String[] selectionArgs) 从ContentProvider中删除数据
4、int  update (Uri uri, ContentValues values, String selection, String[] selectionArgs) 更新ContentProvider已经存在的数据
5、Cursor  query (Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)  返回数据给调用者
6、String  getType (Uri uri)  返回ContentProvider数据的MIME类型
(三)、在清单文件中声明注册ContentProvider:
<provider android:name=".WordsContentProvider"  
android:authorities ="com.qf.wordscontentprovider"  
android:exported ="true"  
 />
 
// android:name 属性的值:ContentProvider类的子类的完整路径;
// android:authorities 属性的值:对应于content:URI中的authority部分。
// android:exported 属性是否允许其他应用调用。如果是false,则该ContentProvider不允许其他应用调用。
 
【备注:】
        ContentProvider是 单例模式 的,当多个应用程序通过使用ContentResolver 来操作使用ContentProvider 提供的数据时,ContentResolver 调用的数据操作会委托给同一个ContentProvider 来处理。这样就能保证数据的一致性。
数据库工具类DBHelper.java
import  android.content.Context;
import  android.database.sqlite.SQLiteDatabase;
import  android.database.sqlite.SQLiteOpenHelper;
public   class  DBHelper extends   SQLiteOpenHelper {
 
public  DBHelper(Context context , int   versionCode ){
super ( context , "users.db" , null , versionCode );
}
@Override
public   void  onCreate(SQLiteDatabase db ) {
// TODO  初始化创建表
db . execSQL ( "create table t_user(_id integer primary key ,uname,upass,money)" );
db . execSQL ( "create table t_order(_id integer primary key ,product_name,price,user_id)" );
//对于 sqlite 来说,只要是integer的主键,则是自动增长的,无需用 autoincrement 指定
db . execSQL ( "insert into t_user(uname,upass,money) values('disen','123',1000)" );
db . execSQL ( "insert into t_user(uname,upass,money) values('jack','234',10000)" );
}
 
@Override
public   void  onUpgrade(SQLiteDatabase db , int   oldVersion , int   newVersion ) {
// TODO   升级数据库(删除旧表,创建新表)
if ( newVersion > oldVersion ){
db .execSQL( "drop table if exists t_user" );
db .execSQL( "drop table if exists t_order" );
onCreate( db );
}
}
 
}
在AndroidManifest.xml中的<application>标签中:
<!-- 注册ContentProvider组件,
  android: authorities 属性声明当前组件的唯一标识,在Resolver中使用uri时,它作为中间部分,后面还要跟着path
   android:exported="true" 设置当前组件可以被外部应用访问 -->
   < provider   android:name = "com.user.contentprovider.UserContentProvider"
    android:authorities = "com.user.contentprovider.users"
    android:exported = "true" />
 
UserContentProvider.java
 
public   class   UserContentProvider   extends  ContentProvider {
 
// 声明当前ContentProvider组件的唯一标识(Authority),注:必须使用小写字母
private   static   final  String AUTHORITY  = "com. user .contentprovider.users" ;
 
// 声明访问当前应用下的数据库中哪些资源,给这些访问资源声明code标识
private   static   final   int   CODE_USER  = 0;
private   static   final   int   CODE_ORDER  = 6;
 
// 声明完整的资源访问 Uri 的匹配器--UriMatcher,实例化它并增加资源访问的 Uri
private   static  UriMatcher uriMatcher ;
static  {
uriMatcher  = new  UriMatcher(UriMatcher. NO_MATCH ); // 值是-1
//UriMatcher. addURI (String authority, String path, int code)
// 用Resolver访问时的 Uri
// content://com.qf.contentprovider.users/users
uriMatcher .addURI( AUTHORITY , "users" , CODE_USER );
 
// content://com.qf.contentprovider.users/orders
uriMatcher .addURI( AUTHORITY , "orders" , CODE_ORDER ); //假设是订单表
}
  /**
 * 自定义的数据库工具类
 */
private  DBHelper dbHelper ;
 
@Override
public   boolean  onCreate() {
// TODO  初始化ConentProvider组件,实例化数据库操作工具类
dbHelper  = new  DBHelper( getContext (), 1);//第二个参数是版本号
return   true ; // 成功返回true
}
 
@Override
public  Cursor query(Uri uri , String[] projection , String selection , String[] selectionArgs , String sortOrder ) {
// TODO  查询数据表
SQLiteDatabase db  = dbHelper .getReadableDatabase(); // 先以读写方式打开数据库,一旦磁盘空间满了,
// 会继续尝试以只读方式打开数据库。
Cursor cursor  = null ; // 查询的结果
// 通过 Uri 匹配器,判断当前请求的 Uri 是访问哪一资源的code
switch  ( uriMatcher .match( uri )) {
case   CODE_USER : // 查询t_users用户表的数据:
cursor  = db .query( "t_user" , projection , selection , selectionArgs , null , null , sortOrder );
break ;
//case CODE_ORDER:.....
}
return   cursor ;
}
 
@Override
public  Uri insert(Uri uri , ContentValues values ) {
// TODO  向数据表中插入数据
SQLiteDatabase db  = dbHelper .getReadableDatabase(); // 先以读写方式打开数据库,一旦磁盘空间满了,
// 会继续尝试以只读方式打开数据库。
if  ( uriMatcher .match( uri ) == CODE_USER ) {//如果是插入t_user表
long   id  = db .insert( "t_user" , null , values );
db .close();
return   ContentUris. withAppendedId ( uri , id ); // 将给定的id追加到路径末尾返回
}
//else if()....
return   null ;
}
 
@Override
public   int  delete(Uri uri , String selection , String[] selectionArgs ) {
// TODO  删除数据表中数据
SQLiteDatabase db  = dbHelper .getReadableDatabase();
if  ( uriMatcher .match( uri ) == CODE_USER ) {
int   cnt  = db .delete( "t_user" , selection , selectionArgs );
db .close();
return   cnt ;//返回收到影响的行数
}
return  0;
}
 
@Override
public   int  update(Uri uri , ContentValues values , String selection , String[] selectionArgs ) {
// TODO  更新数据表中的数据
SQLiteDatabase db  = dbHelper .getReadableDatabase();
if  ( uriMatcher .match( uri ) == CODE_USER ) {
int   cnt  = db .update( "t_user" , values , selection , selectionArgs );
db .close();
return   cnt ;//返回收到影响的行数
}
return  0;
}
@Override
public  String getType(Uri uri ) {
// TODO  Auto-generated method stub
return   null ;
}
}
在另外一个app中利用ContentResolver来使用自定义的ContentProvider暴露出来的数据:
public class MainActivity extends Activity{
         private TextView tv_info;
         private ContentResolver resolver;
         private Uri uri = Uri.parse("content://com.user.contentprovider.users/users");
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          // TODO Auto-generated method stub
           super.onCreate(savedInstanceState);
           setContentView(R.layout.layout_main);
            tv_info = (TextView)findViewById(R.id.tv_info);
           resolver = getContentResolver();
      }
        public void click(View v){
             switch (v.getId()) {
             case R.id.bt_query:
              //建表时的语句:create table t_user(_id integer primary key,uname,upass,money)
              query();//调用自定义的查询所有数据的方法
              break;
            case R.id.bt_insert:
              insert();//调用自定义的插入数据的方法
              break;
            case R.id.bt_update:
            //请自行实现
             break;
          default:
            break;
        }
     }
     private void insert() {
       //调用自定义的插入数据的方法(硬编码)
        ContentValues values = new ContentValues();
          values.put("uname", "zhang");
        values.put("upass", "321");
          values.put("money", "99");
        Uri nUri = resolver.insert(uri, values);//sqlite会自动指定主键id
       long newId = ContentUris.parseId(nUri);//获取新插入的id
      Toast.makeText(this, ""+newId, 0).show();
   }
   private void query() {
    //自定义的查询所有数据的方法
     Cursor c = resolver.query(uri , new String[]{"_id","uname","upass","money"}, null, null,null);
    String text = "";
    while(c.moveToNext()){
          text +=c.getString(0)+","+c.getString(1)+","+c.getString(2)+","+c.getString(3)+"\n";
    }
     tv_info.setText(text);
   }
}





  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Google Android SDK开发范例大全(完整版)共4个分卷 目录 第1章 了解.深入.动手做. 1.1 红透半边天的Android 1.2 本书目的及涵盖范例范围 1.3 如何阅读本书 1.4 使用本书范例 1.5 参考网站 第2章 Android初体验 2.1 安装AndroidSDK与ADTplug-in 2.2 建立第一个Android项目(HelloAndroid!) 2.3 Android应用程序架构——从此开始 2.4 可视化的界面开发工具 2.5 部署应用程序到Android手机 第3章 用户人机界面 3.1 更改与显示文字标签——TextView标签的使用 3.2 更改手机窗口画面底色——drawable定义颜色常数的方法 3.3 更改TextView文字颜色——引用Drawable颜色常数及背景色 3.4 置换TextView文字——CharSequence数据类型与ResourceID应用 3.5 取得手机屏幕大小——DisplayMetrics取得画面宽高的方法 3.6 样式化的定型对象——Style样式的定义 3.7 简易的按钮事件——Button事件处理 3.8 手机页面的转换——setContentView的应用 3.9 调用另一个Activity——Intent对象的使用 3.10 不同Activity之间的数据传递——Bundle对象的实现 3.11 返回数据到前一个Activity——startActivityForResult方法 3.12 具有交互功能的对话框——AlertDialog窗口 3.13 置换文字颜色的机关——Button与TextView的交互 3.14 控制不同的文字字体——Typeface对象使用 3.15 如iPhone拖动相片特效——Gallery画廊 3.16 自制计算器——多按钮的整合应用 3.17 关于(About)程序信息——Menu功能菜单程序设计 3.18 程序加载中,请稍后——ProgressDialog与线程整合应用 3.19 全屏幕以按钮覆盖——动态产生按钮并最大化 3.20 今晚到哪儿打牙祭?——具选择功能的对话框 3.21 Android变脸——主题(Theme)实现 第4章 史上超豪华的手机控件 4.1 EditText与TextView共舞——setOnKeyListener事件 4.2 设计具有背景图的按钮——ImageButton的焦点及事件处理 4.3 给耶诞老人的信息——Toast对象的使用 4.4 我同意条款——CheckBox的isChecked属性 4.5 消费券采购列表——多选项CheckBox的应用 4.6 向左或向右——RadioGroup组与onCheckedChanged事件 4.7 专业相框设计——ImageView的堆栈应用 4.8 自定义下拉菜单模式——Spinner与setDropDownViewResource 4.9 动态添加/删除的Spinner菜单——ArrayList与Widget的依赖性 4.10 心爱小宝贝相片集——Gallery与衍生BaseAdapter容器 4.11 快速的搜索手机文件引擎——JavaI/O的应用 4.12 按钮也能随点击变换——ImageButton选择特效 4.13 具自动提示功能的菜单——AutoCompleteTextView与数组 4.14 数字及模拟小时钟设计——AnalogClock与DigitalClock的原理 4.15 动态输入日期与时间——DatePicker与TimePicker应用 4.16 猜猜红心A在那儿——ImageView点击事件与透明度处理 4.17 后台程序运行进度提示——ProgressBar与Handler的整合应用 4.18 动态文字排版——GridView与ArrayAdapter设计 4.19 在Activity里显示列表列表——ListView的布局 4.20 以动态列表配置选项——ListActivity与Menu整合技巧 4.21 查找程序根目录下所有文件——JavaI/O与ListActivity的结合.. 4.22 加载手机磁盘里的图文件——使用decodeFile方法 4.23 动态放大缩小ImageView里的图片——运用Matrix对象来缩放图文件 4.24 动态旋转图片——Bitmap与Matrix旋转ImageView 4.25 猜猜我在想什么——RadioButtonID 4.26 离开与关闭程序的弹出窗口——对话窗口上的ICON图标 第5章 交互式通信服务与手机控制 5.1 具有正则表达式的TextView——Linkify规则 5.2 ACTION!CALL!拨打电话——Intent.ACTION.CALL的使用 5.3 自制发送短信程序——SmsManager与PendingIntent对象 5.4 自制发送Email程序——Intent在Email上的使用 5.5 自制日历手机数据库——实现SQLiteOpenHelper 5.6 手机震动的节奏——Vibrator对象及周期运用 5.7 图文可视化提醒——Toast与LinearLayoutView 5.8 状态栏的图标与文字提醒——NotificationManager与Notification对象的应用 5.9 搜索手机通讯录自动完成——使用ContentResolver 5.10 取得联系人资料——Provider.Contact的使用 5.11 制作有图标的文件资源管理器——自定义Adapter对象 5.12 还原手机默认桌面——重写clearWallpaper方法 5.13 置换手机背景图——Gallery与setWallpaper整合实现 5.14 撷取手机现存桌面——getWallpaper与setImageDrawable 5.15 文件资源管理器再进化——JavaI/O修改文件名及删除 5.16 取得目前File与Cache的路径——getCacheDir与getFilesDir 5.17 打开/关闭WiFi服务——WifiManager状态判断 5.18 取得SIM卡内的信息——TelephonyManager的应用 5.19 调用拨号按钮——打电话CALL_BUTTON 5.20 DPAD按键处理——onKeyDown事件与Layout坐标交互 5.21 任务管理器正在运行的程序——RunningTaskInfo 5.22 动态更改屏幕方向——LANDSCAPE与PORTRAIT 5.23 系统设置更改事件——onConfigurationChanged信息处理 5.24 取得电信网络与手机相关信息——TelephonyManager与android.provider.Settings.System的应用 第6章 手机自动服务纪实 6.1 您有一条短信popup提醒——常驻BroadcastReceiver的应用 6.2 手机电池计量还剩多少——使用BroadcastReceiver捕捉Intent.ACTION_BATTERY_CHANGED 6.3 群发拜年短信给联系人——ACTION_PICK与Uri对象 6.4 开始与停止系统服务——Service与Runnable整合并用 6.5 通过短信发送email通知——BroadcastReceiver与Intent整合 6.6 手机拨接状态——PhoneStateListener之onCallStateChanged 6.7 有来电,发送邮件通知——PhoneStateListener与ACTION_SEND 6.8 存储卡剩余多少容量——Environment加StatFs 6.9 访问本机内存与存储卡——File的创建与删除 6.10 实现可定时响起的闹钟——PendingIntent与AlarmManager的运用 6.11 黑名单来电自动静音——PhoneStateListener与AudioManager 6.12 手机翻背面即静音震动——SensorListener及AudioManager整合应用 6.13 指定时间置换桌面背景——多AlarmManager事件处理 6.14 判断发送短信后的状态——BroadcastReceiver聆听PendingIntent 6.15 后台服务送出广播信息——sendBroadcast与BroadcastReceiver 6.16 开机程序设计——receiver与intent-filter协同作业 6.17 双向短信常驻服务——Service与receiver实例 第7章 娱乐多媒体 7.1 访问Drawable资源的宽高——ContextMenu与Bitmap的应用 7.2 绘制几何图形——使用android.graphics类 7.3 手机屏幕保护程序——FadeIn/FadeOut特效与运行线程 7.4 用手指移动画面里的照片——onTouchEvent事件判断 7.5 加载存储卡的Gallery相簿——FileArrayList 7.6 取得手机内置媒体里的图文件——ACTION_GET_CONTENT取回InputStream 7.7 相片导航向导与设置背景桌面——ImageSwitcher与Gallery 7.8 调整音量大小声——AudioManager控制音量 7.9 播放mp3资源文件——raw文件夹与MediaPlayer的使用 7.10 播放存储卡里的mp3音乐——MediaPlayer.setDataSource 7.11 自制录音/播放录音程序——MediaRecorder与AudioEncoder 7.12 通过收到短信开始秘密录音——MediaRecorder与BroadcastReceiver实例 7.13 内置影片播放器载入3gp电影——VideoViewWidget 7.14 自制3gp影片播放器——MediaPlayer与实现SurfaceView 7.15 相机预览及拍照临时文件——Camera及PictureCallback事件 第8章 当Android与Internet接轨 8.1 HTTPGET/POST传递参数——HTTP连接示范 8.2 在程序里浏览网页——WebView.loadUrl 8.3 嵌入HTML标记的程序——WebView.loadData 8.4 设计前往打开网页功能——Intent与Uri.parse 8.5 将网络图像网址放入Gallery中显示——URL.URLConnection.BaseAdapter 8.6 即时访问网络图文件展示——HttpURLConnection 8.7 手机气象局,实时卫星云图——HttpURLConnection与URLConnection和运行线程 8.8 通过网络播放MP3——Runnable存储FileOutputStream技巧 8.9 设置远程下载音乐为手机铃声——RingtoneManager与铃声存放路径 8.10 远程下载桌面背景图案——URLConnection与setWallpaper()搭配 8.11 将手机文件上传至网站服务器——模拟HTTPFORM的POSTACTION 8.12 移动博客发布器——以XML-RPC达成远程过程调用 8.13 移动RSS阅读器——利用SAXParser解析XML 8.14 远程下载安装Android程序——APKInstaller的应用 8.15 手机下载看3gp影片——Runnable混搭SurfaceView 8.16 访问网站LoginAPI——远程服务器验证程序运行权限 8.17 地震速报!——HttpURLConnection与Service侦测服务 第9章 Google服务与Android混搭 9.1 Google帐号验证Token——AuthSub 9.2 Google搜索——AutoCompleteTextView与GoogleSearchAPI 9.3 前端产生QRCode二维条形码——GoogleChartAPI 9.4 以经纬度查找目的地位置——GeoPoint与MapView的搭配运用 9.5 GPSGoogle地图——LocationListener与MapView实时更新 9.6 移动版GoogleMap——Geocoder反查Address对象 9.7 规划导航路径——DirectionsRoute 9.8 移动设备上的Picasa相册——GooglePicasaAPI 9.9 随身翻译机——GoogleTranslateAPI 第10章 创意Android程序设计 10.1 手机手电筒——PowerManager控制WakeLock并改变手机亮度 10.2 GPS轨迹记录器——利用LocationListener在地图上画图并换算距离 10.3 女性贴身看护——AlarmManager.DatePicker.TimePicker 10.4 手机QRCode二维条形码生成器——Canvas与SurfaceHolder绘图 10.5 AndroidQRCode二维条形码扫描仪——BitmapFactory.decodeByteArray 10.6 上班族今天中午要吃什么——热量骰子地图 10.7 掷杯筊——把手机放在空中甩事件处理...
Google Android SDK开发范例大全(完整版)共4个分卷 目录 第1章 了解.深入.动手做. 1.1 红透半边天的Android 1.2 本书目的及涵盖范例范围 1.3 如何阅读本书 1.4 使用本书范例 1.5 参考网站 第2章 Android初体验 2.1 安装AndroidSDK与ADTplug-in 2.2 建立第一个Android项目(HelloAndroid!) 2.3 Android应用程序架构——从此开始 2.4 可视化的界面开发工具 2.5 部署应用程序到Android手机 第3章 用户人机界面 3.1 更改与显示文字标签——TextView标签的使用 3.2 更改手机窗口画面底色——drawable定义颜色常数的方法 3.3 更改TextView文字颜色——引用Drawable颜色常数及背景色 3.4 置换TextView文字——CharSequence数据类型与ResourceID应用 3.5 取得手机屏幕大小——DisplayMetrics取得画面宽高的方法 3.6 样式化的定型对象——Style样式的定义 3.7 简易的按钮事件——Button事件处理 3.8 手机页面的转换——setContentView的应用 3.9 调用另一个Activity——Intent对象的使用 3.10 不同Activity之间的数据传递——Bundle对象的实现 3.11 返回数据到前一个Activity——startActivityForResult方法 3.12 具有交互功能的对话框——AlertDialog窗口 3.13 置换文字颜色的机关——Button与TextView的交互 3.14 控制不同的文字字体——Typeface对象使用 3.15 如iPhone拖动相片特效——Gallery画廊 3.16 自制计算器——多按钮的整合应用 3.17 关于(About)程序信息——Menu功能菜单程序设计 3.18 程序加载中,请稍后——ProgressDialog与线程整合应用 3.19 全屏幕以按钮覆盖——动态产生按钮并最大化 3.20 今晚到哪儿打牙祭?——具选择功能的对话框 3.21 Android变脸——主题(Theme)实现 第4章 史上超豪华的手机控件 4.1 EditText与TextView共舞——setOnKeyListener事件 4.2 设计具有背景图的按钮——ImageButton的焦点及事件处理 4.3 给耶诞老人的信息——Toast对象的使用 4.4 我同意条款——CheckBox的isChecked属性 4.5 消费券采购列表——多选项CheckBox的应用 4.6 向左或向右——RadioGroup组与onCheckedChanged事件 4.7 专业相框设计——ImageView的堆栈应用 4.8 自定义下拉菜单模式——Spinner与setDropDownViewResource 4.9 动态添加/删除的Spinner菜单——ArrayList与Widget的依赖性 4.10 心爱小宝贝相片集——Gallery与衍生BaseAdapter容器 4.11 快速的搜索手机文件引擎——JavaI/O的应用 4.12 按钮也能随点击变换——ImageButton选择特效 4.13 具自动提示功能的菜单——AutoCompleteTextView与数组 4.14 数字及模拟小时钟设计——AnalogClock与DigitalClock的原理 4.15 动态输入日期与时间——DatePicker与TimePicker应用 4.16 猜猜红心A在那儿——ImageView点击事件与透明度处理 4.17 后台程序运行进度提示——ProgressBar与Handler的整合应用 4.18 动态文字排版——GridView与ArrayAdapter设计 4.19 在Activity里显示列表列表——ListView的布局 4.20 以动态列表配置选项——ListActivity与Menu整合技巧 4.21 查找程序根目录下所有文件——JavaI/O与ListActivity的结合.. 4.22 加载手机磁盘里的图文件——使用decodeFile方法 4.23 动态放大缩小ImageView里的图片——运用Matrix对象来缩放图文件 4.24 动态旋转图片——Bitmap与Matrix旋转ImageView 4.25 猜猜我在想什么——RadioButtonID 4.26 离开与关闭程序的弹出窗口——对话窗口上的ICON图标 第5章 交互式通信服务与手机控制 5.1 具有正则表达式的TextView——Linkify规则 5.2 ACTION!CALL!拨打电话——Intent.ACTION.CALL的使用 5.3 自制发送短信程序——SmsManager与PendingIntent对象 5.4 自制发送Email程序——Intent在Email上的使用 5.5 自制日历手机数据库——实现SQLiteOpenHelper 5.6 手机震动的节奏——Vibrator对象及周期运用 5.7 图文可视化提醒——Toast与LinearLayoutView 5.8 状态栏的图标与文字提醒——NotificationManager与Notification对象的应用 5.9 搜索手机通讯录自动完成——使用ContentResolver 5.10 取得联系人资料——Provider.Contact的使用 5.11 制作有图标的文件资源管理器——自定义Adapter对象 5.12 还原手机默认桌面——重写clearWallpaper方法 5.13 置换手机背景图——Gallery与setWallpaper整合实现 5.14 撷取手机现存桌面——getWallpaper与setImageDrawable 5.15 文件资源管理器再进化——JavaI/O修改文件名及删除 5.16 取得目前File与Cache的路径——getCacheDir与getFilesDir 5.17 打开/关闭WiFi服务——WifiManager状态判断 5.18 取得SIM卡内的信息——TelephonyManager的应用 5.19 调用拨号按钮——打电话CALL_BUTTON 5.20 DPAD按键处理——onKeyDown事件与Layout坐标交互 5.21 任务管理器正在运行的程序——RunningTaskInfo 5.22 动态更改屏幕方向——LANDSCAPE与PORTRAIT 5.23 系统设置更改事件——onConfigurationChanged信息处理 5.24 取得电信网络与手机相关信息——TelephonyManager与android.provider.Settings.System的应用 第6章 手机自动服务纪实 6.1 您有一条短信popup提醒——常驻BroadcastReceiver的应用 6.2 手机电池计量还剩多少——使用BroadcastReceiver捕捉Intent.ACTION_BATTERY_CHANGED 6.3 群发拜年短信给联系人——ACTION_PICK与Uri对象 6.4 开始与停止系统服务——Service与Runnable整合并用 6.5 通过短信发送email通知——BroadcastReceiver与Intent整合 6.6 手机拨接状态——PhoneStateListener之onCallStateChanged 6.7 有来电,发送邮件通知——PhoneStateListener与ACTION_SEND 6.8 存储卡剩余多少容量——Environment加StatFs 6.9 访问本机内存与存储卡——File的创建与删除 6.10 实现可定时响起的闹钟——PendingIntent与AlarmManager的运用 6.11 黑名单来电自动静音——PhoneStateListener与AudioManager 6.12 手机翻背面即静音震动——SensorListener及AudioManager整合应用 6.13 指定时间置换桌面背景——多AlarmManager事件处理 6.14 判断发送短信后的状态——BroadcastReceiver聆听PendingIntent 6.15 后台服务送出广播信息——sendBroadcast与BroadcastReceiver 6.16 开机程序设计——receiver与intent-filter协同作业 6.17 双向短信常驻服务——Service与receiver实例 第7章 娱乐多媒体 7.1 访问Drawable资源的宽高——ContextMenu与Bitmap的应用 7.2 绘制几何图形——使用android.graphics类 7.3 手机屏幕保护程序——FadeIn/FadeOut特效与运行线程 7.4 用手指移动画面里的照片——onTouchEvent事件判断 7.5 加载存储卡的Gallery相簿——FileArrayList 7.6 取得手机内置媒体里的图文件——ACTION_GET_CONTENT取回InputStream 7.7 相片导航向导与设置背景桌面——ImageSwitcher与Gallery 7.8 调整音量大小声——AudioManager控制音量 7.9 播放mp3资源文件——raw文件夹与MediaPlayer的使用 7.10 播放存储卡里的mp3音乐——MediaPlayer.setDataSource 7.11 自制录音/播放录音程序——MediaRecorder与AudioEncoder 7.12 通过收到短信开始秘密录音——MediaRecorder与BroadcastReceiver实例 7.13 内置影片播放器载入3gp电影——VideoViewWidget 7.14 自制3gp影片播放器——MediaPlayer与实现SurfaceView 7.15 相机预览及拍照临时文件——Camera及PictureCallback事件 第8章 当Android与Internet接轨 8.1 HTTPGET/POST传递参数——HTTP连接示范 8.2 在程序里浏览网页——WebView.loadUrl 8.3 嵌入HTML标记的程序——WebView.loadData 8.4 设计前往打开网页功能——Intent与Uri.parse 8.5 将网络图像网址放入Gallery中显示——URL.URLConnection.BaseAdapter 8.6 即时访问网络图文件展示——HttpURLConnection 8.7 手机气象局,实时卫星云图——HttpURLConnection与URLConnection和运行线程 8.8 通过网络播放MP3——Runnable存储FileOutputStream技巧 8.9 设置远程下载音乐为手机铃声——RingtoneManager与铃声存放路径 8.10 远程下载桌面背景图案——URLConnection与setWallpaper()搭配 8.11 将手机文件上传至网站服务器——模拟HTTPFORM的POSTACTION 8.12 移动博客发布器——以XML-RPC达成远程过程调用 8.13 移动RSS阅读器——利用SAXParser解析XML 8.14 远程下载安装Android程序——APKInstaller的应用 8.15 手机下载看3gp影片——Runnable混搭SurfaceView 8.16 访问网站LoginAPI——远程服务器验证程序运行权限 8.17 地震速报!——HttpURLConnection与Service侦测服务 第9章 Google服务与Android混搭 9.1 Google帐号验证Token——AuthSub 9.2 Google搜索——AutoCompleteTextView与GoogleSearchAPI 9.3 前端产生QRCode二维条形码——GoogleChartAPI 9.4 以经纬度查找目的地位置——GeoPoint与MapView的搭配运用 9.5 GPSGoogle地图——LocationListener与MapView实时更新 9.6 移动版GoogleMap——Geocoder反查Address对象 9.7 规划导航路径——DirectionsRoute 9.8 移动设备上的Picasa相册——GooglePicasaAPI 9.9 随身翻译机——GoogleTranslateAPI 第10章 创意Android程序设计 10.1 手机手电筒——PowerManager控制WakeLock并改变手机亮度 10.2 GPS轨迹记录器——利用LocationListener在地图上画图并换算距离 10.3 女性贴身看护——AlarmManager.DatePicker.TimePicker 10.4 手机QRCode二维条形码生成器——Canvas与SurfaceHolder绘图 10.5 AndroidQRCode二维条形码扫描仪——BitmapFactory.decodeByteArray 10.6 上班族今天中午要吃什么——热量骰子地图 10.7 掷杯筊——把手机放在空中甩事件处理...
Google Android SDK开发范例大全(完整版)共4个分卷 目录 第1章 了解.深入.动手做. 1.1 红透半边天的Android 1.2 本书目的及涵盖范例范围 1.3 如何阅读本书 1.4 使用本书范例 1.5 参考网站 第2章 Android初体验 2.1 安装AndroidSDK与ADTplug-in 2.2 建立第一个Android项目(HelloAndroid!) 2.3 Android应用程序架构——从此开始 2.4 可视化的界面开发工具 2.5 部署应用程序到Android手机 第3章 用户人机界面 3.1 更改与显示文字标签——TextView标签的使用 3.2 更改手机窗口画面底色——drawable定义颜色常数的方法 3.3 更改TextView文字颜色——引用Drawable颜色常数及背景色 3.4 置换TextView文字——CharSequence数据类型与ResourceID应用 3.5 取得手机屏幕大小——DisplayMetrics取得画面宽高的方法 3.6 样式化的定型对象——Style样式的定义 3.7 简易的按钮事件——Button事件处理 3.8 手机页面的转换——setContentView的应用 3.9 调用另一个Activity——Intent对象的使用 3.10 不同Activity之间的数据传递——Bundle对象的实现 3.11 返回数据到前一个Activity——startActivityForResult方法 3.12 具有交互功能的对话框——AlertDialog窗口 3.13 置换文字颜色的机关——Button与TextView的交互 3.14 控制不同的文字字体——Typeface对象使用 3.15 如iPhone拖动相片特效——Gallery画廊 3.16 自制计算器——多按钮的整合应用 3.17 关于(About)程序信息——Menu功能菜单程序设计 3.18 程序加载中,请稍后——ProgressDialog与线程整合应用 3.19 全屏幕以按钮覆盖——动态产生按钮并最大化 3.20 今晚到哪儿打牙祭?——具选择功能的对话框 3.21 Android变脸——主题(Theme)实现 第4章 史上超豪华的手机控件 4.1 EditText与TextView共舞——setOnKeyListener事件 4.2 设计具有背景图的按钮——ImageButton的焦点及事件处理 4.3 给耶诞老人的信息——Toast对象的使用 4.4 我同意条款——CheckBox的isChecked属性 4.5 消费券采购列表——多选项CheckBox的应用 4.6 向左或向右——RadioGroup组与onCheckedChanged事件 4.7 专业相框设计——ImageView的堆栈应用 4.8 自定义下拉菜单模式——Spinner与setDropDownViewResource 4.9 动态添加/删除的Spinner菜单——ArrayList与Widget的依赖性 4.10 心爱小宝贝相片集——Gallery与衍生BaseAdapter容器 4.11 快速的搜索手机文件引擎——JavaI/O的应用 4.12 按钮也能随点击变换——ImageButton选择特效 4.13 具自动提示功能的菜单——AutoCompleteTextView与数组 4.14 数字及模拟小时钟设计——AnalogClock与DigitalClock的原理 4.15 动态输入日期与时间——DatePicker与TimePicker应用 4.16 猜猜红心A在那儿——ImageView点击事件与透明度处理 4.17 后台程序运行进度提示——ProgressBar与Handler的整合应用 4.18 动态文字排版——GridView与ArrayAdapter设计 4.19 在Activity里显示列表列表——ListView的布局 4.20 以动态列表配置选项——ListActivity与Menu整合技巧 4.21 查找程序根目录下所有文件——JavaI/O与ListActivity的结合.. 4.22 加载手机磁盘里的图文件——使用decodeFile方法 4.23 动态放大缩小ImageView里的图片——运用Matrix对象来缩放图文件 4.24 动态旋转图片——Bitmap与Matrix旋转ImageView 4.25 猜猜我在想什么——RadioButtonID 4.26 离开与关闭程序的弹出窗口——对话窗口上的ICON图标 第5章 交互式通信服务与手机控制 5.1 具有正则表达式的TextView——Linkify规则 5.2 ACTION!CALL!拨打电话——Intent

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值