我需要在不同的手机上获得呼叫提供商的内部结构(这主要是因为三星设备会导致问题,即基础数据库架构)。 这是我的代码:
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
............................
dumpProvider();
}
private void dumpProvider() {
Cursor cursor = getCallsCursor();
try {
BufferedWriter writer = getWriter();
dumpColumnNames(cursor, writer);
cursor.moveToFirst();
do {
dumpRecord(cursor, writer);
} while (cursor.moveToNext());
writer.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
cursor.close();
}
}
private void dumpRecord(Cursor cursor, BufferedWriter writer) throws IOException {
String recordStr = "";
int columnCount = cursor.getColumnCount();
for (int columnIndex = 0; columnIndex < columnCount; columnIndex++) {
recordStr += cursor.getString(columnIndex) + " ";
}
writer.append(recordStr);
writer.newLine();
}
private void dumpColumnNames(Cursor cursor, BufferedWriter writer) throws IOException {
String[] columnNames = cursor.getColumnNames();
String columnNamesStr = "";
for (String columnStr : columnNames) {
columnNamesStr += columnStr + " ";
}
writer.append(columnNamesStr);
writer.newLine();
}
private Cursor getCallsCursor() {
ContentResolver cr = getContentResolver();
Cursor cursor = cr.query(CallLog.Calls.CONTENT_URI, null, null, null, null);
return cursor;
}
private BufferedWriter getWriter() throws IOException {
......................
}
}
在我的LG上运行井,但在三星S2上运行时,我得到异常:
08-20 09:16:15.860: E/AndroidRuntime(19565): FATAL EXCEPTION: main
08-20 09:16:15.860: E/AndroidRuntime(19565): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.databasestrucutecollector/com.example.databasestrucutecollector.MainActivity}: android.database.sqlite.SQLiteException: no such column: sdn_alpha_id: , while compiling: SELECT sns_receiver_count, numberlabel, service_type, matched_number, type, contactid, lookup_uri, mime_type, sdn_alpha_id, sp_type, messageid, fname, simnum, lname, sns_pkey, account_id, formatted_number, call_out_duration, number, geocoded_location, account_name, is_read, raw_contact_id, source_data, cdnip_number, state, m_subject, date, real_phone_number, source_package, _id, sns_tid, name, normalized_number, name_reversed, _data, photo_id, logtype, reject_flag, has_content, m_content, country_code, frequent, cityid, bname, countryiso, numbertype, new, duration, cnap_name, address, e164_number, voicemail_uri FROM logs WHERE (logs.logtype=100 OR logs.logtype=110 OR logs.logtype=500 OR logs.logtype=800 OR logs.logtype=900 OR logs.logtype=1000 OR (logs.logtype=200 AND number NOT IN (SELECT number FROM logs WHERE number LIKE '%@%')) OR logs.logtype=300) AND ((((type != '4')))) ORDER BY date DESC
08-20 09:16:15.860: E/AndroidRuntime(19565): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1967)
08-20 09:16:15.860: E/AndroidRuntime(19565): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1992)
08-20 09:16:15.860: E/AndroidRuntime(19565): at android.app.ActivityThread.access$600(ActivityThread.java:127)
08-20 09:16:15.860: E/AndroidRuntime(19565): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1158)
08-20 09:16:15.860: E/AndroidRuntime(19565): at android.os.Handler.dispatchMessage(Handler.java:99)
08-20 09:16:15.860: E/AndroidRuntime(19565): at android.os.Looper.loop(Looper.java:137)
08-20 09:16:15.860: E/AndroidRuntime(19565): at android.app.ActivityThread.main(ActivityThread.java:4511)
08-20 09:16:15.860: E/AndroidRuntime(19565): at java.lang.reflect.Method.invokeNative(Native Method)
08-20 09:16:15.860: E/AndroidRuntime(19565): at java.lang.reflect.Method.invoke(Method.java:511)
08-20 09:16:15.860: E/AndroidRuntime(19565): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:980)
08-20 09:16:15.860: E/AndroidRuntime(19565): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:747)
08-20 09:16:15.860: E/AndroidRuntime(19565): at dalvik.system.NativeStart.main(Native Method)
08-20 09:16:15.860: E/AndroidRuntime(19565): Caused by: android.database.sqlite.SQLiteException: no such column: sdn_alpha_id: , while compiling: SELECT sns_receiver_count, numberlabel, service_type, matched_number, type, contactid, lookup_uri, mime_type, sdn_alpha_id, sp_type, messageid, fname, simnum, lname, sns_pkey, account_id, formatted_number, call_out_duration, number, geocoded_location, account_name, is_read, raw_contact_id, source_data, cdnip_number, state, m_subject, date, real_phone_number, source_package, _id, sns_tid, name, normalized_number, name_reversed, _data, photo_id, logtype, reject_flag, has_content, m_content, country_code, frequent, cityid, bname, countryiso, numbertype, new, duration, cnap_name, address, e164_number, voicemail_uri FROM logs WHERE (logs.logtype=100 OR logs.logtype=110 OR logs.logtype=500 OR logs.logtype=800 OR logs.logtype=900 OR logs.logtype=1000 OR (logs.logtype=200 AND number NOT IN (SELECT number FROM logs WHERE number LIKE '%@%')) OR logs.logtype=300) AND ((((type != '4')))) ORDER BY date DESC
08-20 09:16:15.860: E/AndroidRuntime(19565): at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:180)
08-20 09:16:15.860: E/AndroidRuntime(19565): at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:136)
08-20 09:16:15.860: E/AndroidRuntime(19565): at android.content.ContentProviderProxy.query(ContentProviderNative.java:358)
08-20 09:16:15.860: E/AndroidRuntime(19565): at android.content.ContentResolver.query(ContentResolver.java:317)
08-20 09:16:15.860: E/AndroidRuntime(19565): at com.example.databasestrucutecollector.MainActivity.getContactsCursor(MainActivity.java:71)
08-20 09:16:15.860: E/AndroidRuntime(19565): at com.example.databasestrucutecollector.MainActivity.dumpProvider(MainActivity.java:31)
08-20 09:16:15.860: E/AndroidRuntime(19565): at com.example.databasestrucutecollector.MainActivity.onCreate(MainActivity.java:26)
08-20 09:16:15.860: E/AndroidRuntime(19565): at android.app.Activity.performCreate(Activity.java:4470)
08-20 09:16:15.860: E/AndroidRuntime(19565): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1052)
08-20 09:16:15.860: E/AndroidRuntime(19565): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1931)
任何提示?
答案 0 :(得分:1)
正如this answer中已经提出的那样,如果您知道需要查询的列,则可以指定选择:
String[] projection = new String[] {CallLog.Calls._ID, CallLog.Calls.CACHED_NAME, CallLog.Calls.DATE, CallLog.Calls.DURATION, CallLog.Calls.NUMBER, CallLog.Calls.TYPE };
Cursor cursor = context.getContentResolver().query( android.provider.CallLog.Calls.CONTENT_URI, projection, null, null, null );
但是,我仍然在寻找一种无需选择即可查询所有列的解决方案......
这似乎是S2设备上的一个错误?有没有人在其他设备上体验过它?
答案 1 :(得分:0)
我不确定为什么你的代码崩溃了,对我来说似乎很好,
我写了一个方法来转储任何ContentProvider uri的所有数据,也许它对你有用:
cur = resolver.query(uri, null, null, null, sort);
if (cur != null) {
// BASIC STUFF
Log.v(TAG, "count = " + cur.getCount());
int columnCount = cur.getColumnCount();
Log.v(TAG, "cols = " + columnCount);
// PRINT ALL COLUMN NAMES
cur.moveToFirst();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < columnCount; i++) {
sb.append(i).append(": ").append(cur.getColumnName(i)).append(", ");
}
Log.v(TAG, "COLUMNS: " + sb.toString());
// PRINT ALL DATA
do {
sb = new StringBuilder();
for (int i = 0; i < columnCount; i++) {
String value = cur.getString(i);
String name = cur.getColumnName(i);
sb.append(i).append(": ").append(value).append(". \t");
}
Log.v(TAG, sb.toString());
} while (cur.moveToNext());
}