一.ListView
1.三种Adapter构建ListView
ListView添加条目的时候, 可以使用setAdapter(ListAdapter)方法, 常用的ListAdapter有三种
BaseAdapter: 定义一个类继承BaseAdapter, 重写4个抽象方法, ListView的条目是由getView()方法构建出来的
SimpleAdapter: 创建SimpleAdapter对象时, 传入数据(List<Map<String, ?>>), 并指定数据的绑定关系
SimpleCursorAdapter: 创建SimpleCursorAdapter对象时, 传入一个Cursor, 指定数据的绑定关系

练习一:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.shellway.sqlite.MainActivity"
android:background="@color/abc_search_url_text_normal"> <ListView
android:id="@+id/id_LV"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/> </RelativeLayout>

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:padding="10dp"
> <TextView
android:id="@+id/idTV"
android:textSize="20sp"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="1"
/>
<TextView
android:id="@+id/nameTV"
android:textSize="20sp"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:gravity="center"
android:text="张三"
/>
<TextView
android:id="@+id/balanceTV"
android:textSize="20sp"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:gravity="center"
android:text="10000"
/> </LinearLayout>

item.xml

package com.shellway.sqlite;

import java.util.List;

import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView; public class MainActivity extends ActionBarActivity { private ListView lv;
private List<Person> persons; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lv = (ListView) findViewById(R.id.id_LV); //获取ListView
PersonDAO dao = new PersonDAO(this);
persons = dao.findAll();
//给ListView添加Adapter,按照Adapter中的方法对ListView添加条目
lv.setAdapter(new myAdapter()); }
//定义Adapter,把每个Person对象生成一个条目,将所有条目装入ListView
private class myAdapter extends BaseAdapter{ @Override
public int getCount() { //返回ListView中要装入的条目的数量
return persons.size();
} @Override
public Object getItem(int position) {//点哪个条目就返回哪个条目的对象
return persons.get(position);
} @Override
public long getItemId(int position) {//返回条目的ID
return position;
} @Override
//返回指定位置上的View,会被添加到ListView中(即一个Person构建成一个View,然后挂到ListView)
public View getView(int position, View convertView, ViewGroup parent) {
Person p = persons.get(position);
//构建成一个条目(View),第三个参数是要挂到谁身上,这里写null它会自动返回到LListView中
View item = View.inflate(getApplicationContext(), R.layout.item, null);
TextView idTV = (TextView) item.findViewById(R.id.idTV);
TextView nameTV = (TextView) item.findViewById(R.id.nameTV);
TextView balanceTV = (TextView) item.findViewById(R.id.balanceTV);
idTV.setText(p.getId()+"");
nameTV.setText(p.getName());
balanceTV.setText(p.getBalance()+"");
return item;
}
}
}

MainActivity

SimpleAdapter:

注意:若要修改成SimpleAdapter,不要忘记了修改AndroidManifest.xml中下面加粗位置部分。

        <activity
android:name=".SimpleAdapterActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
package com.shellway.sqlite;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map; import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView; public class SimpleAdapterActivity extends ActionBarActivity { private ListView lv;
private List<Person> persons; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lv = (ListView) findViewById(R.id.id_LV); //获取ListView
PersonDAO dao = new PersonDAO(this);
persons = dao.findAll();
List<Map<String, Object>> data = new ArrayList<Map<String,Object>>();
for (Person p : persons) {
Map<String, Object> map = new HashMap<String, Object>();
map.put("id", p.getId());
map.put("name", p.getName());
map.put("balance", p.getBalance());
data.add(map);
}
lv.setAdapter(new SimpleAdapter(this, data , R.layout.item,
new String[]{"id","name","balance"},
new int[]{R.id.idTV,R.id.nameTV,R.id.balanceTV}));
/**SimpleAdapter
* 参数1:上下文环境
* 参数2:数据,List<Map<String, Object>>每个Person装入一个Map,再将Map装入List
* 参数3:布局文件的资源id
* 参数4:Map中的Key,和参数5中的id对应,将指定key的value放入View中指定id对应和组件上
* 参数5:View中的id
*/
}
}

SimpleAdapter

SimpleCusorAdapter:

注意:使用SimpleCusorAdapter,在查询结果中要包含有“_id”这一列,这里我把id取别名为_id的方法解决。

    public Cursor queryAllCusor(){
SQLiteDatabase db = helper.getReadableDatabase();
//Cursor c = db.rawQuery("select id,name,balance from people", null);
Cursor c = db.query("people", new String[]{"id as _id","name","balance"}, null, null, null, null, null, null);
return c;
}
package com.shellway.sqlite;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map; import android.support.v4.widget.SimpleCursorAdapter;
import android.support.v7.app.ActionBarActivity;
import android.database.Cursor;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView; public class SimpleCusorAdapterActivity extends ActionBarActivity { private ListView lv; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lv = (ListView) findViewById(R.id.id_LV); //获取ListView
PersonDAO dao = new PersonDAO(this);
Cursor c = dao.queryAllCusor();
lv.setAdapter(new SimpleCursorAdapter(this, R.layout.item, c,
new String[]{"_id","name","balance"},
new int[]{R.id.idTV,R.id.nameTV,R.id.balanceTV}));
/**SimpleAdapter
* 参数1:上下文环境
* 参数2:布局文件的资源id
* 参数3:包含数据的游标
* 参数4:游标中的列名
* 参数5:条目中的组件的ID,游标中的数据就会放在对应的这些组件上
*/
}
}

SimpleCusorAdapterActivity

运行结果:

2.监听ListView的点击
调用ListView.setOnItemClickListener(OnItemClickListener)方法注册一个监听器
在监听器的onItemClick()方法中使用 parent.getItemAtPosition(position) 方法可以获取指定条目上的数据
BaseAdapter: 返回的就是自定义的getItem()方法中返回的数据
SimpleAdapter: 返回的是一个Map, 就是创建SimpleAdapter时List中的一个Map
SimpleCursorAdapter: 返回的是一个Cursor, 这个Cursor就是创建时传入的Cursor, 但是已经通过moveToPosition()方法指定到点击的索引了

练习2:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.shellway.sqlite.SimpleAdapterActivity"
android:background="@color/abc_search_url_text_normal"> <LinearLayout
android:id="@+id/ll"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
> <TextView
android:textSize="20sp"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="序号"
/>
<TextView
android:textSize="20sp"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:gravity="center"
android:text="姓名"
/>
<TextView
android:textSize="20sp"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:gravity="center"
android:text="余额"
/>
</LinearLayout> <ListView
android:id="@+id/id_LV"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_below="@id/ll"
/> </RelativeLayout>

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:padding="10dp"
> <TextView
android:id="@+id/idTV"
android:textSize="20sp"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="1"
/>
<TextView
android:id="@+id/nameTV"
android:textSize="20sp"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:gravity="center"
android:text="张三"
/>
<TextView
android:id="@+id/balanceTV"
android:textSize="20sp"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:gravity="center"
android:text="10000"
/> </LinearLayout>

item.xml

package com.shellway.sqlite;

import java.util.List;

import android.support.v4.widget.SearchViewCompat.OnCloseListenerCompat;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast; public class BaseAdapterActivity extends ActionBarActivity { private ListView lv;
private List<Person> persons; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lv = (ListView) findViewById(R.id.id_LV); //获取ListView
PersonDAO dao = new PersonDAO(this);
persons = dao.findAll();
//给ListView添加Adapter,按照Adapter中的方法对ListView添加条目
lv.setAdapter(new myAdapter());
//给ListView添加条目点击监听器
lv.setOnItemClickListener(new myOnClickListener()); } private class myOnClickListener implements OnItemClickListener{
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
//获取点击的条目上的数据,其内部实际上是调用:myAdapter.getItem()
Person p = (Person) parent.getItemAtPosition(position);
Toast.makeText(getApplicationContext(), p.getBalance()+"", Toast.LENGTH_SHORT).show();
}
} //定义Adapter,把每个Person对象生成一个条目,将所有条目装入ListView
private class myAdapter extends BaseAdapter{ @Override
public int getCount() { //返回ListView中要装入的条目的数量
return persons.size();
} @Override
public Object getItem(int position) {//点哪个条目就返回哪个条目的对象
return persons.get(position);
} @Override
public long getItemId(int position) {//返回条目的ID
return position;
} @Override
//返回指定位置上的View,会被添加到ListView中(即一个Person构建成一个View,然后挂到ListView)
public View getView(int position, View convertView, ViewGroup parent) {
Person p = persons.get(position);
//构建成一个条目(View),第三个参数是要挂到谁身上,这里写null它会自动返回到LListView中
View item = View.inflate(getApplicationContext(), R.layout.item, null);
TextView idTV = (TextView) item.findViewById(R.id.idTV);
TextView nameTV = (TextView) item.findViewById(R.id.nameTV);
TextView balanceTV = (TextView) item.findViewById(R.id.balanceTV);
idTV.setText(p.getId()+"");
nameTV.setText(p.getName());
balanceTV.setText(p.getBalance()+"");
return item;
}
}
}

BaseAdapterActivity添加ListView中条目点击监听事件

package com.shellway.sqlite;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map; import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener; public class SimpleAdapterActivity extends ActionBarActivity { private ListView lv;
private List<Person> persons; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lv = (ListView) findViewById(R.id.id_LV); //获取ListView
PersonDAO dao = new PersonDAO(this);
persons = dao.findAll();
List<Map<String, Object>> data = new ArrayList<Map<String,Object>>();
for (Person p : persons) {
Map<String, Object> map = new HashMap<String, Object>();
map.put("id", p.getId());
map.put("name", p.getName());
map.put("balance", p.getBalance());
data.add(map);
}
lv.setAdapter(new SimpleAdapter(this, data , R.layout.item,
new String[]{"id","name","balance"},
new int[]{R.id.idTV,R.id.nameTV,R.id.balanceTV}));
/**SimpleAdapter
* 参数1:上下文环境
* 参数2:数据,List<Map<String, Object>>每个Person装入一个Map,再将Map装入List
* 参数3:布局文件的资源id
* 参数4:Map中的Key,和参数5中的id对应,将指定key的value放入View中指定id对应和组件上
* 参数5:View中的id
*/
lv.setOnItemClickListener(new myOnClickListener());
}
private class myOnClickListener implements OnItemClickListener{
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
//SimpleAdapter返回的是一个map
Map<String,Object> map = (Map<String, Object>) parent.getItemAtPosition(position);
Toast.makeText(getApplicationContext(), map.get("name").toString(), Toast.LENGTH_SHORT).show();
}
}
}

SimpleAdapterActivity添加ListView中条目点击监听事件

package com.shellway.sqlite;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map; import android.support.v4.widget.SimpleCursorAdapter;
import android.support.v7.app.ActionBarActivity;
import android.database.Cursor;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener; public class SimpleCusorAdapterActivity extends ActionBarActivity { private ListView lv; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lv = (ListView) findViewById(R.id.id_LV); //获取ListView
PersonDAO dao = new PersonDAO(this);
Cursor c = dao.queryAllCusor();
lv.setAdapter(new SimpleCursorAdapter(this, R.layout.item, c,
new String[]{"_id","name","balance"},
new int[]{R.id.idTV,R.id.nameTV,R.id.balanceTV}));
/**SimpleAdapter
* 参数1:上下文环境
* 参数2:布局文件的资源id
* 参数3:包含数据的游标
* 参数4:游标中的列名
* 参数5:条目中的组件的ID,游标中的数据就会放在对应的这些组件上
*/
lv.setOnItemClickListener(new myOnClickListener());
} private class myOnClickListener implements OnItemClickListener{
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
//SimpleCursorAdapter返回的是一个Cursor
Cursor c = (Cursor) parent.getItemAtPosition(position);
Toast.makeText(getApplicationContext(), c.getString(0), Toast.LENGTH_SHORT).show();
}
}
}

SimpleCusorAdapterActivity添加ListView中条目点击监听事件

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.shellway.sqlite"
android:versionCode="1"
android:versionName="1.0" > <uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="21" />
<instrumentation
android:targetPackage="com.shellway.sqlite"
android:name="android.test.InstrumentationTestRunner" /> <application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<uses-library android:name="android.test.runner" />
<activity
android:name=".BaseAdapterActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application> </manifest>

AndroidManifest.xml

辅助类:

package com.shellway.sqlite;

public class Person {

    private Integer id;
private String name;
private Integer balance;
public Person() {
super();
}
public Person(String name, Integer balance) {
super();
this.name = name;
this.balance = balance;
}
public Person(Integer id, String name, Integer balance) {
super();
this.id = id;
this.name = name;
this.balance = balance;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getBalance() {
return balance;
}
public void setBalance(Integer balance) {
this.balance = balance;
}
@Override
public String toString() {
return "person [id=" + id + ", name=" + name + ", balance=" + balance
+ "]";
}
}

Person.java

package com.shellway.sqlite;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper; public class DBSQLiteHelper extends SQLiteOpenHelper {
public DBSQLiteHelper(Context context){
super(context,"data.db" , null, 4);
/**
* 由于弗雷没有无参的构造函数,必须显式调用有参的构造函数
* 参数1:上下文环境,用来确定数据库文件存储的目录
* 参数2:数据库文件的名字
* 参数3:生成游标的工厂,填null就是使用默认的
* 参数4:数据库的版本,从1开始
*/
} @Override
public void onCreate(SQLiteDatabase db) {
System.out.println("onCreate");
db.execSQL("CREATE TABLE people(id INTEGER PRIMARY KEY AUTOINCREMENT,name VACHAR(20))");
} @Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
System.out.println("onUpgrade");
db.execSQL("ALTER TABLE people ADD balance INTEGER");
}
}

DBSQLiteHelper.java

package com.shellway.sqlite;

import java.util.ArrayList;
import java.util.List; import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase; public class PersonDAO {
private DBSQLiteHelper helper; public PersonDAO(Context context) {
helper = new DBSQLiteHelper(context);
} public long insert(Person p){
SQLiteDatabase db = helper.getWritableDatabase();//获取数据库链接(可写的)
//db.execSQL("INSERT INTO people(name,balance) VALUES(?,?)", new Object[]{p.getName(),p.getBalance()} );
ContentValues values = new ContentValues();
values.put("name", p.getName());
values.put("balance", p.getBalance());
/**
* 这里的第二个参数 可以随便填表里的任意一个字段名,是为了防止插入的字段名为空时会出错,
* 当你确定插入的值不会出错时候可以null
* 返回值表示最新插入的记录的ID
*/
long rows = db.insert("people", null, values);
db.close();
return rows;
}
public void delete(Integer id){
SQLiteDatabase db = helper.getWritableDatabase();
//db.execSQL("DELETE FROM people WHERE id = ?", new Object[]{id});
db.delete("people", "id=?", new String[]{id+""});
db.close();
}
public void update(Person p){
SQLiteDatabase db = helper.getWritableDatabase();
//db.execSQL("update people set name=?,balance=? where id=? ", new Object[]{p.getName(),p.getBalance(),p.getId()});
ContentValues values = new ContentValues();
values.put("name", p.getName());
values.put("balance", p.getBalance());
db.update("people", values, "id=?", new String[]{p.getId()+""});
db.close();
}
//根据id查询某条记录
public Person query(Integer id){
/**
* 查询时候应该优先使用getReadableDatabase()而不是getWritableDatabase(),
* 其实getReadableDatabase是先获取getWritableDatabase,若获取失败则采用getReadableDatabase
*/
SQLiteDatabase db = helper.getReadableDatabase();
//Cursor c = db.rawQuery("select name,balance from people where id=?",new String[]{id+""});
Cursor c = db.query("people", new String[]{"id","name","balance"}, "id=?", new String[]{id+""}, null, null, null, null);
Person p = null ;
if (c.moveToNext()) {
String name = c.getString(c.getColumnIndex("name"));
int balance = c.getInt(2);//若直接用下标方式,则注意该字段的索引,游标的索引是从0开始的
p = new Person(id,name,balance);
}
c.close();
db.close();
return p;
}
//查询全部记录
public List<Person> findAll(){
SQLiteDatabase db = helper.getReadableDatabase();
//Cursor c = db.rawQuery("select id,name,balance from people", null);
Cursor c = db.query("people", null, null, null, null, null, null, null);
List<Person> persons = new ArrayList<Person>();
while (c.moveToNext()) {
Person p = new Person(c.getInt(0),c.getString(1),c.getInt(2));
persons.add(p);
}
c.close();
db.close();
return persons;
}
public Cursor queryAllCusor(){
SQLiteDatabase db = helper.getReadableDatabase();
//Cursor c = db.rawQuery("select id,name,balance from people", null);
Cursor c = db.query("people", new String[]{"id as _id","name","balance"}, null, null, null, null, null, null);
return c;
}
//查询记录总条数
public int queryCount(){
SQLiteDatabase db = helper.getReadableDatabase();
//Cursor c = db.rawQuery("select count(*) from people", null);
Cursor c = db.query("people", new String[]{"count(*)"}, null, null, null, null, null);
c.moveToNext();
int i = c.getInt(0);
c.close();
db.close();
return i;
}
//分页查询
public List<Person> queryPage(int pageNum,int capacity){
String offset = (pageNum-1) * capacity +""; //偏移量,即是第几页的页数
String len = capacity + ""; //一页中显示的个数
SQLiteDatabase db = helper.getReadableDatabase();
//Cursor c = db.rawQuery("select id,name,balance from people limit ?,?", new String[]{offset,len});
Cursor c = db.query("people", new String[]{"id","name","balance"}, null, null, null, null, null, offset+","+len);
List<Person> persons = new ArrayList<Person>();
while (c.moveToNext()) {
Person p = new Person(c.getInt(0),c.getString(1),c.getInt(2));
persons.add(p);
}
c.close();
db.close();
return persons;
}
}

PersonDAO.java

package com.shellway.sqlite;

import java.util.ArrayList;
import java.util.List;
import java.util.Random; import android.database.sqlite.SQLiteDatabase;
import android.provider.SyncStateContract.Helpers;
import android.test.AndroidTestCase; public class TestSQLite extends AndroidTestCase {
public void test1(){
DBSQLiteHelper helper = new DBSQLiteHelper(getContext());
SQLiteDatabase sql = helper.getWritableDatabase();
/**
* 获取可写的数据库连接
* 数据库文件不存在时,会创建数据库文件,并且执行onCreate()方法
* 数据库文件存在,且版本没有改变时,不执行任何方法
* 数据库文件存在,版本提升,执行onUpdate方法
*/
}
public void testInsert(){
PersonDAO personDAO = new PersonDAO(getContext());
long rows = personDAO.insert(new Person("KKK",20000));
System.out.println(rows);
}
public void testDelete(){
PersonDAO personDAO = new PersonDAO(getContext());
personDAO.delete(104);
}
public void testUpdate(){
PersonDAO personDAO = new PersonDAO(getContext());
personDAO.update(new Person(1,"www",30000));
}
public void testQuery(){
PersonDAO personDAO = new PersonDAO(getContext());
System.out.println(personDAO.query(5));
}
public void testFindAll(){
PersonDAO personDAO = new PersonDAO(getContext());
List<Person> persons = personDAO.findAll();
for (Person p : persons) {
System.out.println(p);
}
}
public void testQueryCount(){
PersonDAO personDAO = new PersonDAO(getContext());
int count = personDAO.queryCount();
System.out.println(count);
}
public void testQueryPage(){
PersonDAO personDAO = new PersonDAO(getContext());
List<Person> persons = personDAO.queryPage(3, 20);
for (Person p : persons) {
System.out.println(p);
}
} }

TestSQLite.java测试类

运行结果:

二.内容提供者(ContentProvider)
1.什么是ContentProvider
ContentProvider可以用来把程序中的数据对外进行共享, 提供增删改查的方法
ContentProvider中可以注册观察者, 监听数据的变化
* 2.怎么创建?

步骤1:在清单文件AndroidManifest.xml中注册

步骤2:定义类继承ContentProvider

package com.shellway.sqlite.provider;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri; public class SQLiteProvider extends ContentProvider { @Override
public boolean onCreate() {
return false;
} @Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
System.out.println("query");
return null;
} @Override
public Uri insert(Uri uri, ContentValues values) {
System.out.println("insert");
return null;
} @Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
System.out.println("delete");
return 0;
} @Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
System.out.println("update");
return 0;
} @Override
public String getType(Uri uri) {
return null;
}
}

定义类SQLiteProvider继承ContentProvider

步骤3:另创建一个工程访问内容提供者

package com.shellway.other;

import android.support.v7.app.ActionBarActivity;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem; public class MainActivity extends ActionBarActivity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//获取解析器对象
ContentResolver resolver = getContentResolver();
//访问内容提供者
ContentValues values = new ContentValues();
Uri uri = Uri.parse("content://com.shellway.sqlite.provider");
resolver.insert(uri, values);
resolver.delete(uri, null, null);
resolver.update(uri, values, null, null);
resolver.query(uri, null, null, null, null);
}
}

MainActivity

3.在手机上注册
将应用安装到手机上即可, 不用运行程序
* 4.怎么访问
获取解析器ContentResolver, 指定Uri
通过ContentResolver.insert(), delete(), update(), query()方法访问Uri关联的ContentProvider
5.Uri的处理
使用UriMatcher可以检查传入的Uri是否和指定的匹配
如果Uri带了id, 可以使用ContentUris获取id, 插入方法可以使用ContentUris给Uri加上id

练习:

package com.shellway.sqlite.provider;

import com.shellway.sqlite.dao.DBSQLiteHelper;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri; public class SQLiteProvider extends ContentProvider {
private UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
private DBSQLiteHelper helper;
private static final int PERSON = 1;
private static final int PERSON_ID = 2;
@Override
public boolean onCreate() {
helper = new DBSQLiteHelper(getContext());
//设置一个Uri,如果匹配到person,则返回PERSON
matcher.addURI("com.shellway.sqlite.provider", "person", PERSON);
matcher.addURI("com.shellway.sqlite.provider", "person/#", PERSON_ID);
return true;
} @Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
SQLiteDatabase db = helper.getReadableDatabase();
switch (matcher.match(uri)) {
case PERSON_ID:
long id = ContentUris.parseId(uri);
selection = selection==null ? "id=" + id : selection + " AND id =" + id ;
case PERSON:
return db.query("people", projection, selection, selectionArgs, null, null, sortOrder);
default:
throw new RuntimeException("Uri不能试看识别。。。 ");
}
} @Override
public Uri insert(Uri uri, ContentValues values) {
SQLiteDatabase db = helper.getWritableDatabase();
switch (matcher.match(uri)) {
case PERSON:
long id = db.insert("people", "id", values);
return ContentUris.withAppendedId(uri, id);
default:
throw new RuntimeException("Uri不能试看识别。。。 ");
}
} @Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
SQLiteDatabase db = helper.getWritableDatabase();
switch (matcher.match(uri)) {
case PERSON_ID:
long id = ContentUris.parseId(uri);
selection = selection==null ? "id=" + id : selection + " AND id =" + id ;
case PERSON:
return db.delete("people", selection, selectionArgs);
default:
throw new RuntimeException("Uri不能试看识别。。。 ");
}
} @Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
SQLiteDatabase db = helper.getWritableDatabase();
switch (matcher.match(uri)) {
case PERSON_ID:
long id = ContentUris.parseId(uri);
selection = selection==null ? "id=" + id : selection + " AND id =" + id ;
case PERSON:
return db.update("people", values, selection, selectionArgs);
default:
throw new RuntimeException("Uri不能试看识别。。。 ");
}
} @Override
public String getType(Uri uri) {
return null;
}
}

02.SQLlite工程中的内容提供者SQLiteProvider

package com.shellway.other;

import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.test.AndroidTestCase; public class ProviderTest extends AndroidTestCase {
public void test1(){
//获取解析器对象
ContentResolver resolver = getContext().getContentResolver();
//访问内容提供者
ContentValues values = new ContentValues();
Uri uri = Uri.parse("content://com.shellway.sqlite.provider"); resolver.insert(uri, values);
resolver.delete(uri, null, null);
resolver.update(uri, values, null, null);
resolver.query(uri, null, null, null, null);
} public void testQuery(){
ContentResolver resolver = getContext().getContentResolver();
Uri uri = Uri.parse("content://com.shellway.sqlite.provider/person");
Cursor c = resolver.query(uri, null, "balance>?", new String[]{8000+""}, "balance ASC");
while (c.moveToNext()) {
Person p = new Person(c.getInt(0),c.getString(1),c.getInt(2));
System.out.println(p);
}
}
public void testQuery2(){
ContentResolver resolver = getContext().getContentResolver();
Uri uri = Uri.parse("content://com.shellway.sqlite.provider/person/10");
Cursor c = resolver.query(uri, null, "balance>?", new String[]{8000+""}, "balance ASC");
while (c.moveToNext()) {
Person p = new Person(c.getInt(0),c.getString(1),c.getInt(2));
System.out.println(p);
}
}
public void testInsert(){
ContentResolver resolver = getContext().getContentResolver();
ContentValues values = new ContentValues();
values.put("name", "Insert");
values.put("balance", "54321");
Uri uri = Uri.parse("content://com.shellway.sqlite.provider/person");
Uri count = resolver.insert(uri, values);
System.out.println(count);
}
public void testUpdate(){
ContentResolver resolver = getContext().getContentResolver();
ContentValues values = new ContentValues();
values.put("name", "Update");
values.put("balance", "12345");
Uri uri = Uri.parse("content://com.shellway.sqlite.provider/person/106");
int i = resolver.update(uri, values, null, null);
System.out.println(i);
}
public void testDelete(){
ContentResolver resolver = getContext().getContentResolver();
Uri uri = Uri.parse("content://com.shellway.sqlite.provider/person/107");
int i = resolver.delete(uri, null, null);
System.out.println(i);
}
}

03.Other测试工程中的测试内容提供者的类ProviderTest

细节补充:

    @Override
public String getType(Uri uri) {
switch (matcher.match(uri)) {
case PERSON_ID:
//一般返回的类型是:minetype? image/jpg html/text css/text
return "vnd.android.cursor.item/person"; //这里表示返回的是单条的person数据
case PERSON:
return "vnd.android.cursor.dir/person";//这里表示返回的是多条的person数据
default:
throw new RuntimeException("Uri不能试看识别。。。 ");
}
}

SQLiteProvider中的getType

   public void testType(){
ContentResolver resolver = getContext().getContentResolver();
String s1 = resolver.getType(Uri.parse("content://com.shellway.sqlite.provider/person/106"));
String s2 = resolver.getType(Uri.parse("content://com.shellway.sqlite.provider/person"));
System.out.println(s1);
System.out.println(s2);
}

ProviderTest中的测试getType方法:testType

注意1:ProviderTest类中的ContentResolver resolver = getContext().getContentResolver();这一行不能放到类的成员变量里边,因为:.class ->.dex ->.app ->安装 ->开启进程(开启主线程)->创建ProviderTest对象 ->setContext ->测试方法 ->getConTest。否则会出现空指针异常,因为还没有setContext就getContext.

注意2:SQLiteProvider中的onCreate() 方法是在第一次启动时执行,然后会长期驻留在后台,除非是被杀死,否则不会再执行。

6.注册观察者
在应用程序中可以对ContentProvider注册一个观察者(ContentObserver)
定义类继承ContentObserver, 重写onChange()方法
使用ContentResolver.registerContentObserver(Uri, boolean, ContentObServer)方法可以注册, 传入指定Uri, 是否监听子级路径, 和一个观察者对象
在收到数据改变通知之后, 会自动执行onChange()方法
7.通知观察者
注册观察者之后, 需要在ContentProvider中进行通知, 观察者才能收到, 使用ContentResolver.notifyChange()方法可以通知数据的改变

练习:

package com.shellway.sqlite.ui;

import java.util.List;

import com.shellway.sqlite.R;
import com.shellway.sqlite.dao.PersonDAO;
import com.shellway.sqlite.domain.Person; import android.support.v4.widget.SearchViewCompat.OnCloseListenerCompat;
import android.support.v7.app.ActionBarActivity;
import android.content.ContentProvider;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast; public class BaseAdapterActivity extends ActionBarActivity { private ListView lv;
private List<Person> persons;
private PersonDAO dao; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lv = (ListView) findViewById(R.id.id_LV); //获取ListView
dao = new PersonDAO(this);
persons = dao.findAll();
//给ListView添加Adapter,按照Adapter中的方法对ListView添加条目
lv.setAdapter(new myAdapter());
//给ListView添加条目点击监听器
lv.setOnItemClickListener(new myOnClickListener());
//注册一个内容观察者
Uri uri = Uri.parse("content://com.shellway.sqlite.provider");
//第二个参数表示监听上面uri子路径下所有的变化,若改为false则只监听uri本身的变化
getContentResolver().registerContentObserver(uri , true, new MyContentObserver());
}
private class MyContentObserver extends ContentObserver{
public MyContentObserver() {
super(new Handler());//Handler()是一个处理器,目前没有用到
}
@Override
public void onChange(boolean selfChange) {
persons = dao.findAll();
lv.setAdapter(new myAdapter());
}
} private class myOnClickListener implements OnItemClickListener{
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
//获取点击的条目上的数据,其内部实际上是调用:myAdapter.getItem()
Person p = (Person) parent.getItemAtPosition(position);
Toast.makeText(getApplicationContext(), p.getBalance()+"", Toast.LENGTH_SHORT).show();
}
} //定义Adapter,把每个Person对象生成一个条目,将所有条目装入ListView
private class myAdapter extends BaseAdapter{ @Override
public int getCount() { //返回ListView中要装入的条目的数量
return persons.size();
} @Override
public Object getItem(int position) {//点哪个条目就返回哪个条目的对象
return persons.get(position);
} @Override
public long getItemId(int position) {//返回条目的ID
return position;
} @Override
//返回指定位置上的View,会被添加到ListView中(即一个Person构建成一个View,然后挂到ListView)
public View getView(int position, View convertView, ViewGroup parent) {
Person p = persons.get(position);
//构建成一个条目(View),第三个参数是要挂到谁身上,这里写null它会自动返回到LListView中
View item = View.inflate(getApplicationContext(), R.layout.item, null);
TextView idTV = (TextView) item.findViewById(R.id.idTV);
TextView nameTV = (TextView) item.findViewById(R.id.nameTV);
TextView balanceTV = (TextView) item.findViewById(R.id.balanceTV);
idTV.setText(p.getId()+"");
nameTV.setText(p.getName());
balanceTV.setText(p.getBalance()+"");
return item;
}
}
}

02.SQLite工程中在BaseAdapterActivity里注册观察者观察一个Uri

package com.shellway.sqlite.provider;

import com.shellway.sqlite.dao.DBSQLiteHelper;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri; public class SQLiteProvider extends ContentProvider {
private UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
private DBSQLiteHelper helper;
private static final int PERSON = 1;
private static final int PERSON_ID = 2;
@Override
public boolean onCreate() {
helper = new DBSQLiteHelper(getContext());
//设置一个Uri,如果匹配到person,则返回PERSON
matcher.addURI("com.shellway.sqlite.provider", "person", PERSON);
matcher.addURI("com.shellway.sqlite.provider", "person/#", PERSON_ID);
return true;
} @Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
SQLiteDatabase db = helper.getReadableDatabase();
switch (matcher.match(uri)) {
case PERSON_ID:
long id = ContentUris.parseId(uri);
selection = selection==null ? "id=" + id : selection + " AND id =" + id ;
case PERSON:
return db.query("people", projection, selection, selectionArgs, null, null, sortOrder);
default:
throw new RuntimeException("Uri不能试看识别。。。 ");
}
} @Override
public Uri insert(Uri uri, ContentValues values) {
SQLiteDatabase db = helper.getWritableDatabase();
switch (matcher.match(uri)) {
case PERSON:
long id = db.insert("people", "id", values);
getContext().getContentResolver().notifyChange(uri, null);
return ContentUris.withAppendedId(uri, id);
default:
throw new RuntimeException("Uri不能试看识别。。。 ");
}
} @Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
SQLiteDatabase db = helper.getWritableDatabase();
switch (matcher.match(uri)) {
case PERSON_ID:
long id = ContentUris.parseId(uri);
selection = selection==null ? "id=" + id : selection + " AND id =" + id ;
case PERSON:
int count = db.delete("people", selection, selectionArgs);
getContext().getContentResolver().notifyChange(uri, null);
return count;
default:
throw new RuntimeException("Uri不能试看识别。。。 ");
}
} @Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
SQLiteDatabase db = helper.getWritableDatabase();
switch (matcher.match(uri)) {
case PERSON_ID:
long id = ContentUris.parseId(uri);
selection = selection==null ? "id=" + id : selection + " AND id =" + id ;
case PERSON:
int count = db.update("people", values, selection, selectionArgs);
getContext().getContentResolver().notifyChange(uri, null);
return count;
default:
throw new RuntimeException("Uri不能试看识别。。。 ");
}
} @Override
public String getType(Uri uri) {
switch (matcher.match(uri)) {
case PERSON_ID:
//一般返回的类型是:minetype? image/jpg html/text css/text
return "vnd.android.cursor.item/person"; //这里表示返回的是单条的person数据
case PERSON:
return "vnd.android.cursor.dir/person";//这里表示返回的是多条的person数据
default:
throw new RuntimeException("Uri不能试看识别。。。 ");
}
}
}

02.SQLite工程中在SQLiteProvider内容提供者里编写内容变更通知语句

package com.shellway.other;

import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.test.AndroidTestCase; public class ProviderTest extends AndroidTestCase {
public void test1(){
//获取解析器对象
ContentResolver resolver = getContext().getContentResolver();
//访问内容提供者
ContentValues values = new ContentValues();
Uri uri = Uri.parse("content://com.shellway.sqlite.provider"); resolver.insert(uri, values);
resolver.delete(uri, null, null);
resolver.update(uri, values, null, null);
resolver.query(uri, null, null, null, null);
} public void testQuery(){
ContentResolver resolver = getContext().getContentResolver();
Uri uri = Uri.parse("content://com.shellway.sqlite.provider/person");
Cursor c = resolver.query(uri, null, "balance>?", new String[]{8000+""}, "balance ASC");
while (c.moveToNext()) {
Person p = new Person(c.getInt(0),c.getString(1),c.getInt(2));
System.out.println(p);
}
}
public void testQuery2(){
ContentResolver resolver = getContext().getContentResolver();
Uri uri = Uri.parse("content://com.shellway.sqlite.provider/person/10");
Cursor c = resolver.query(uri, null, "balance>?", new String[]{8000+""}, "balance ASC");
while (c.moveToNext()) {
Person p = new Person(c.getInt(0),c.getString(1),c.getInt(2));
System.out.println(p);
}
}
public void testInsert(){
ContentResolver resolver = getContext().getContentResolver();
ContentValues values = new ContentValues();
values.put("name", "Test5");
values.put("balance", "12345");
Uri uri = Uri.parse("content://com.shellway.sqlite.provider/person");
Uri count = resolver.insert(uri, values);
}
public void testUpdate(){
ContentResolver resolver = getContext().getContentResolver();
ContentValues values = new ContentValues();
values.put("name", "shellway");
values.put("balance", "10000");
Uri uri = Uri.parse("content://com.shellway.sqlite.provider/person/116");
int i = resolver.update(uri, values, null, null);
}
public void testDelete(){
ContentResolver resolver = getContext().getContentResolver();
Uri uri = Uri.parse("content://com.shellway.sqlite.provider/person/122");
int i = resolver.delete(uri, null, null);
}
public void testType(){
ContentResolver resolver = getContext().getContentResolver();
String s1 = resolver.getType(Uri.parse("content://com.shellway.sqlite.provider/person/106"));
String s2 = resolver.getType(Uri.parse("content://com.shellway.sqlite.provider/person"));
System.out.println(s1);
System.out.println(s2);
}
}

在A应用(03.Other)中使用内容提供者,使得数据发生改变

package com.shellway.contentobserver;

import android.support.v7.app.ActionBarActivity;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast; public class MainActivity extends ActionBarActivity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Uri uri = Uri.parse("content://com.shellway.sqlite.provider");
getContentResolver().registerContentObserver(uri , true, new MyContentOberver());
}
private class MyContentOberver extends ContentObserver{
public MyContentOberver() {
super(new Handler());
}
@Override
public void onChange(boolean selfChange) {
Uri uri = Uri.parse("content://com.shellway.sqlite.provider/person");
Cursor c = getContentResolver().query(uri, null, null, null, "id desc limit 1");
while (c.moveToNext()) {
Toast.makeText(getApplicationContext(), c.getString(1), Toast.LENGTH_SHORT).show();
}
}
}
}

在B应用(04.ContentObserver)中也注册一个观察者观察相同的Uri,若该Uri上的数据发生改变,我会收到通知然后执行我的onChange方法

结果:一旦在A应用中通过内容提供者改变数据,则注册在该Uri上的观察者都会收到数据发生改变的通知,因为事先在内容提供者里都已经放了一个“通知者”,这里的通知者即是:getContext().getContentResolver().notifyChange(uri, null);所以,SQLite工程和B应用中的观察者都会接收到通知,从而执行自己的onChange()方法。

四.监听短信
1.获取源码
安装GIT工具:
在网站上下载com.android.providers.telephony源码:https://github.com/android
通过清单文件可以查找到Uri
2.监听改变
对指定Uri添加ContentOberver
在onChange方法中查询最新的记录, 收发短信时都会收到修改通知, 这样就能获取刚刚收发的短信了

package com.shellway.smsobserver;

import java.text.SimpleDateFormat;
import java.util.Date; import android.support.v7.app.ActionBarActivity;
import android.content.ContentResolver;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler; public class MainActivity extends ActionBarActivity { private Uri uri;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//注册短信观察者
uri = Uri.parse("content://sms");
getContentResolver().registerContentObserver(uri , true, new MyObserver());
}
private class MyObserver extends ContentObserver{ private long flag;
public MyObserver() {
super(new Handler());
}
@Override
public void onChange(boolean selfChange) {
ContentResolver resolver = getContentResolver();
//查询最新的一条短信信息,因为收发短信,信息都会先往数据库存然后才显示在手机屏幕
Cursor c = resolver.query(uri, null, null, null, "_id desc limit 1");
while(c.moveToNext()){
String addr = c.getString(c.getColumnIndex("address"));
String body = c.getString(c.getColumnIndex("body"));
int type = c.getInt(c.getColumnIndex("type"));
Long date = c.getLong(c.getColumnIndex("date"));
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
Date d = new Date(date);
String dd = sdf.format(d);
if(flag!=date){ //因为回短信时会打印出三条重复的信息,这里利用时间来控制打印结果只为一条信息
System.out.println(dd +" " + (type == 1 ? "收":"发") + addr +" "+ body);
flag = date;
}
}
}
}
}

监听短信信息变化:MainActivity.java

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.shellway.smsobserver"
android:versionCode="1"
android:versionName="1.0" > <uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="21" />
<uses-permission android:name="android.permission.READ_SMS"/>
<uses-permission android:name="android.permission.WRITE_SMS"/> <application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application> </manifest>

AndroidManifest.xml

结果:

五.读写联系人
1.获取原码
和监听短信相同, 获取com.android.providers.contacts源码
2.读取联系人
先读raw_contacts表中的id, 在根据id查找data表
3.写出联系人
先向raw_contacts表中写出一个id(自动生成)
在向data表写出3条对应数据, raw_contact_id一列使用刚刚插入的id

 练习:(读联系人)

1.新建一个工程:

2.分析:

3.编写程序:

package com.shellway.contacts;

import android.content.ContentResolver;
import android.database.Cursor;
import android.net.Uri;
import android.test.AndroidTestCase; public class ContactsTest extends AndroidTestCase { public void testContexts(){
Uri idUri = Uri.parse("content://com.android.contacts/raw_contacts");
Uri dataUri = Uri.parse("content://com.android.contacts/data");
ContentResolver resolver = getContext().getContentResolver();
Cursor c = resolver.query(idUri, new String[]{"_id"}, null, null, null);
/* String[] arr = c.getColumnNames();//打印raw_contacts表中的所有列名
for (String s : arr) {
System.out.println(s);
}*/
while(c.moveToNext()){
int idRaw = c.getInt(0);
Cursor datac = resolver.query(dataUri, new String[]{"mimetype","data1","data2","data3"}
, "raw_contact_id=?"
, new String[]{idRaw+""}
, null);
while(datac.moveToNext()){
if(datac.getString(0).equals("vnd.android.cursor.item/name")){
System.out.println("姓名: "+ datac.getString(datac.getColumnIndex("data1")));
}else if(datac.getString(0).equals("vnd.android.cursor.item/phone_v2")){
System.out.println("电话: "+ datac.getString(datac.getColumnIndex("data1")));
}else if(datac.getString(0).equals("vnd.android.cursor.item/email_v2")){
System.out.println("邮箱: "+ datac.getString(datac.getColumnIndex("data1")));
}
}
}
/* Cursor datac = resolver.query(dataUri, null, null, null, null);//打印data表中的所有列名
String[] s = datac.getColumnNames();
for (String st : s) {
System.out.println(st);
}*/ }
}

ContactsTest.java

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.shellway.contacts"
android:versionCode="1"
android:versionName="1.0" > <uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="21" />
<instrumentation
android:targetPackage="com.shellway.contacts"
android:name="android.test.InstrumentationTestRunner" />
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.WRITE_CONTACTS"/>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<uses-library android:name="android.test.runner" />
</application> </manifest>

AndroidManifest.xml

结果:

java攻城狮之路(Android篇)--ListView与ContentProvider的更多相关文章

  1. java攻城狮之路(Android篇)--BroadcastReceiver&Service

    四大组件:activity 显示. contentProvider 对外暴露自己的数据给其他的应用程序.BroadcastReceiver 广播接收者,必须指定要接收的广播类型.必须明确的指定acti ...

  2. java攻城狮之路(Android篇)--widget_webview_metadata_popupwindow_tabhost_分页加载数据_菜单

    一.widget:桌面小控件1 写一个类extends AppWidgetProvider 2 在清单文件件中注册: <receiver android:name=".ExampleA ...

  3. java攻城狮之路(Android篇)--MP3 MP4、拍照、国际化、样式主题、图片移动和缩放

    一.MP3播放器 查看Android API文档可以看到MediaPlayer状态转换图: 练习: package com.shellway.mp3player; import java.io.Fil ...

  4. java攻城狮之路(Android篇)--Activity生命

    一:Activity的激活 1.写一个类 extends Activity Activity是android的四大组件之一.Activity的激活分为显式意图激活和隐式意图激活.如果一个activit ...

  5. java攻城狮之路(Android篇)--与服务器交互

    一.图片查看器和网页源码查看器 在输入地址的是不能输入127.0.0.1 或者是 localhost.ScrollView :可以看成一个滚轴 可以去包裹很多的控件在里面 练习1(图片查看器): pa ...

  6. java攻城狮之路(Android篇)--SQLite

    一.Junit    1.怎么使用        在AndroidManifest.xml文件中进行配置, 在manifest借点下配置instrumentation, 在application借点下 ...

  7. java攻城师之路(Android篇)--搭建开发环境、拨打电话、发送短信、布局例子

    一.搭建开发环境 1.所需资源 JDK6以上 Eclipse3.6以上 SDK17, 2.3.3 ADT17 2.安装注意事项 不要使用中文路径 如果模拟器默认路径包含中文, 可以设置android_ ...

  8. java攻城狮之路--复习xml&dom_pull编程续

    本章节我们要学习XML三种解析方式: 1.JAXP DOM 解析2.JAXP SAX 解析3.XML PULL 进行 STAX 解析 XML 技术主要企业应用1.存储和传输数据 2.作为框架的配置文件 ...

  9. java攻城狮之路--复习xml&dom_pull编程

    xml&dom_pull编程: 1.去掉欢迎弹窗界面:在window项的preferences选项中输入“configuration center” 找到这一项然后     把复选框勾去即可. ...

随机推荐

  1. python mysql desc

    #!/usr/bin/python import MySQLdb try: conn=MySQLdb.connect(host='localhost',user='root',passwd='your ...

  2. Python快速上手JSON指南

    什么是JSON? 网上对JSON有很多教程,有各种各样的解释.一言以蔽之,JSON本质上是一种语法,这种语法的作用是把数据以字符串的形式存储.传递,多用于Web编程. JSON的典型示例 '{ &qu ...

  3. 详解Bootstrap媒体对象

    在web页面中,图片居左,内容居右排列,是非常常见的效果,它也就是媒体对象,它是一种抽象的样式,可以用来构建不同类型的组件,在bootstrap框架中其对应的版本文件如下: LESS: media.l ...

  4. DataGridViewComboBoxColumn值无效

    值无效,可能是你下拉框选项,没有这样的值,而你却设置这个值. dataGridView1.Rows[i].Cells[].Value = "选项一"; 解决方法就是在窗体的构造函数 ...

  5. openCV_java 图像二值化

    较为常用的图像二值化方法有:1)全局固定阈值:2)局部自适应阈值:3)OTSU等. 局部自适应阈值则是根据像素的邻域块的像素值分布来确定该像素位置上的二值化阈值.这样做的好处在于每个像素位置处的二值化 ...

  6. 三步解决EntityFramework Code First中的MissingMethodException错误

    在数据库初始化时运行OnModelCreating的方法中,有时会抛出MissingMethodException异常. 以下三步可解决大部份的出错场景: 在程序包管理器控制台中运行:Uninstal ...

  7. NGUI 减少drawcall规则

    前置说明一: Unity中的drawcall定义: 每次引擎准备数据并通知GPU的过程称为一次Draw Call. Unity(或者说基本所有图形引擎)生成一帧画面的处理过程大致可以这样简化描述:引擎 ...

  8. [转] 配置Log4j

    Log4J的配置文件(Configuration File)就是用来设置记录器的级别.存放器和布局的,它可接key=value格式的设置或xml格式的设置信息.通过配置,可以创建出Log4J的运行环境 ...

  9. Hadoop学习-生态体系(ecosystem)概览

    0. 大背景 全球No.1搜索引擎公司谷歌(Google)面临每天海量搜索引擎数据的问题,经过长时间的实践积累, 谷歌形成了自己的大数据框架,但是并没有开源,而是发表了一篇论文,阐述了自己的思想,在论 ...

  10. Unix Pipes to Javascript Pipes

    Unix Pipes Unix管道扫描稿 简单样例: $ netstat -apn | grep 8080 相信这个大家经常使用,这里就不细说了. 那么管道基本思想是什么呢? 让每个程序只完成一件事, ...