我需要使用SQL加入标准的android表(如联系人和调用日志)。可以使用SQLiteDatabase类的rawQuery或查询方法。但是为了使方法正常工作,我需要知道我可以在原始SQL查询中提供的表名。
实施例。我想执行这样的查询:
SELECT * FROM Contacts as c INNER JOIN Call_Log as l ON c.number = l.number
我知道如何获取字段名称(如CallLog.Calls.NUMBER),但我不知道如何获取每个android所具有的标准表的名称。可以对名称进行硬编码,但使用CallLog.TABLE_NAME之类的方式看起来更可靠。那么,我在哪里可以找到CallLog.TABLE_NAME的类似物?
答案 0 :(得分:0)
您要求提供大量信息,但这是如何访问联系人表以及如何创建自己的SQL表并使用从其他表获取的信息更新它的很好的总结。
要对联系人提供程序进行任何类型的搜索,您的应用必须具有READ_CONTACTS权限。要请求此项,请将此元素作为子元素添加到清单文件中:
<uses-permission android:name="android.permission.READ_CONTACTS" />
要对“呼叫记录”进行任何类型的搜索,您的应用必须具有READ_CALL_LOG权限。要请求此项,请将此元素作为子元素添加到清单文件中:
<uses-permission android:name="android.permission.READ_CALL_LOG" />
以下有关如何访问电话记录历史的代码
Uri allCalls = Uri.parse("content://call_log/calls");
Cursor c = managedQuery(allCalls, null, null, null, null);
String num= c.getString(c.getColumnIndex(CallLog.Calls.NUMBER));// for number
String name= c.getString(c.getColumnIndex(CallLog.Calls.CACHED_NAME));// for name
String duration = c.getString(c.getColumnIndex(CallLog.Calls.DURATION));// for duration
int type = Integer.parseInt(c.getString(c.getColumnIndex(CallLog.Calls.TYPE)));// for call type, Incoming or out going.
此技术尝试将搜索字符串与Contact Provider的ContactsContract.Contacts表中的联系人或联系人的姓名进行匹配。您通常希望在ListView中显示结果,以允许用户在匹配的联系人中进行选择。
将数据保存到数据库非常适合重复或结构化数据,例如联系信息。本课程假定您通常熟悉SQL数据库,并帮助您开始使用Android上的SQLite数据库。您在Android上使用数据库所需的API可以在android.database.sqlite包中找到。
SQL数据库的主要原则之一是模式:数据库组织方式的正式声明。架构反映在用于创建数据库的SQL语句中。您可能会发现创建一个称为契约类的伴随类很有帮助,它以系统和自我记录的方式明确指定了模式的布局。
契约类是定义URI,表和列名称的常量的容器。契约类允许您在同一个包中的所有其他类中使用相同的常量。这使您可以在一个位置更改列名,并让它在整个代码中传播。
组织合同类的一种好方法是将整个数据库的全局定义放在类的根级别。然后为每个枚举其列的表创建一个内部类。
public final class FeedReaderContract {
// To prevent someone from accidentally instantiating the contract class,
// make the constructor private.
private FeedReaderContract() {}
/* Inner class that defines the table contents */
public static class FeedEntry implements BaseColumns {
public static final String TABLE_NAME = "entry";
public static final String COLUMN_NAME_TITLE = "title";
public static final String COLUMN_NAME_SUBTITLE = "subtitle";
}
}
一旦定义了数据库的外观,就应该实现创建和维护数据库和表的方法。以下是一些创建和删除表的典型语句:
private static final String TEXT_TYPE = " TEXT";
private static final String COMMA_SEP = ",";
private static final String SQL_CREATE_ENTRIES =
"CREATE TABLE " + FeedEntry.TABLE_NAME + " (" +
FeedEntry._ID + " INTEGER PRIMARY KEY," +
FeedEntry.COLUMN_NAME_TITLE + TEXT_TYPE + COMMA_SEP +
FeedEntry.COLUMN_NAME_SUBTITLE + TEXT_TYPE + " )";
private static final String SQL_DELETE_ENTRIES =
"DROP TABLE IF EXISTS " + FeedEntry.TABLE_NAME;
就像您在设备的内部存储中保存的文件一样,Android会将您的数据库存储在与相关应用程序相关的私有磁盘空间中。您的数据是安全的,因为默认情况下,其他应用程序无法访问此区域。
SQLiteOpenHelper类中提供了一组有用的API。当您使用此类获取对数据库的引用时,系统仅在需要时执行可能长时间运行的创建和更新数据库的操作,而不是在应用程序启动期间执行。您需要做的就是调用getWritableDatabase()或getReadableDatabase()。
要使用SQLiteOpenHelper,请创建一个覆盖onCreate(),onUpgrade()和onOpen()回调方法的子类。您可能还想实现onDowngrade(),但这不是必需的。
例如,这是SQLiteOpenHelper的一个实现,它使用了上面显示的一些命令:
public class FeedReaderDbHelper extends SQLiteOpenHelper {
//如果更改数据库架构,则必须增加数据库版本。 public static final int DATABASE_VERSION = 1; public static final String DATABASE_NAME =&#34; FeedReader.db&#34;;
public FeedReaderDbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
public void onCreate(SQLiteDatabase db) {
db.execSQL(SQL_CREATE_ENTRIES);
}
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// This database is only a cache for online data, so its upgrade policy is
// to simply to discard the data and start over
db.execSQL(SQL_DELETE_ENTRIES);
onCreate(db);
}
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
onUpgrade(db, oldVersion, newVersion);
}
}
要访问您的数据库,请实例化SQLiteOpenHelper的子类:
FeedReaderDbHelper mDbHelper = new FeedReaderDbHelper(getContext()); 将信息放入数据库
通过将ContentValues对象传递给insert()方法将数据插入数据库:
// Gets the data repository in write mode
SQLiteDatabase db = mDbHelper.getWritableDatabase();
// Create a new map of values, where column names are the keys
ContentValues values = new ContentValues();
values.put(FeedEntry.COLUMN_NAME_TITLE, title);
values.put(FeedEntry.COLUMN_NAME_SUBTITLE, subtitle);
// Insert the new row, returning the primary key value of the new row
long newRowId = db.insert(FeedEntry.TABLE_NAME, null, values);
The first argument for insert() is simply the table name.
第二个参数告诉框架在ContentValues为空的情况下要做什么(即,你没有放任何值)。如果指定列的名称,框架将插入一行并将该列的值设置为null。如果指定null,就像在此代码示例中一样,当没有值时,框架不会插入行。
要从数据库中读取,请使用query()方法,将选择条件和所需列传递给它。该方法结合了insert()和update()的元素,但列列表定义了要获取的数据,而不是要插入的数据。查询结果将在Cursor对象中返回给您。
SQLiteDatabase db = mDbHelper.getReadableDatabase();
// Define a projection that specifies which columns from the database
// you will actually use after this query.
String[] projection = {
FeedEntry._ID,
FeedEntry.COLUMN_NAME_TITLE,
FeedEntry.COLUMN_NAME_SUBTITLE
};
// Filter results WHERE "title" = 'My Title'
String selection = FeedEntry.COLUMN_NAME_TITLE + " = ?";
String[] selectionArgs = { "My Title" };
// How you want the results sorted in the resulting Cursor
String sortOrder =
FeedEntry.COLUMN_NAME_SUBTITLE + " DESC";
Cursor c = db.query(
FeedEntry.TABLE_NAME, // The table to query
projection, // The columns to return
selection, // The columns for the WHERE clause
selectionArgs, // The values for the WHERE clause
null, // don't group the rows
null, // don't filter by row groups
sortOrder // The sort order
);
要查看光标中的一行,请使用Cursor移动方法之一,在开始读取值之前必须始终调用它们。通常,您应该首先调用moveToFirst(),这将放置&#34;读取位置&#34;在结果的第一个条目。对于每一行,您可以通过调用其中一个Cursor get方法(例如getString()或getLong())来读取列的值。对于每个get方法,必须传递所需列的索引位置,可以通过调用getColumnIndex()或getColumnIndexOrThrow()来获取。例如:
cursor.moveToFirst();
long itemId = cursor.getLong(
cursor.getColumnIndexOrThrow(FeedEntry._ID)
);