SQLite 异常错误,使用 CursorLoader 和 ContactContracts

Posted

技术标签:

【中文标题】SQLite 异常错误,使用 CursorLoader 和 ContactContracts【英文标题】:SQLite Exception error, using CursorLoader & ContactContracts 【发布时间】:2015-02-24 04:46:50 【问题描述】:

我正在尝试将 ListView(即片段)填充到加载 android 手机联系人的活动中。而且由于我不熟悉 SQLite 样式的查询,我可能弄乱了语法,因为我收到了这个错误:

java.lang.RuntimeException: An error occurred while executing doInBackground()
Caused by: android.database.sqlite.SQLiteException: near "display_name": syntax error (code 1): , while compiling: SELECT _id, photo_thumb_uri, display_name, has_phone_number FROM view_contacts_restricted WHERE ((1)) AND ((photo_thumb_uri=?display_name=?has_phone_number=?)) ORDER BY display_nameASC

两个问题:

    下面是我的片段代码和我的 logcat。有什么看起来不对吗? (是什么导致了错误?)

    我没有使用片段 xml 布局(虽然我之前尝试过,所以注释掉的代码仍然存在),因为我读到 CursorLoader 创建自己的布局。这是一个正确的假设吗?

ContactsFragment.java

package org.azurespot.practiceapp.addressbook;

import android.app.ListFragment;
import android.app.LoaderManager.LoaderCallbacks;
import android.content.ContentUris;
import android.content.CursorLoader;
import android.content.Loader;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Contacts;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CursorAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;

import com.example.practiceapp.R;

/*
 * Partially from http://***.com/questions/18199359/how-to-display-contacts-in-a-listview-in-android-for-android-api-11
 */

public class ContactsFragment extends ListFragment implements 
                                LoaderCallbacks<Cursor>

    private CursorAdapter mAdapter;
    public ListView listView;
    public Cursor cursor;
    private android.content.Context context;
    public View view;
    public static Uri uri;

    public static final String[] FROM =  
            ContactsContract.Contacts.PHOTO_THUMBNAIL_URI,
            ContactsContract.Contacts.DISPLAY_NAME_PRIMARY,
            ContactsContract.Contacts.HAS_PHONE_NUMBER ;

    private static final int[] TO =  R.id.contact_thumbnail, 
        R.id.contact_name, R.id.contact_number ;

    // columns requested from the database
    private static final String[] PROJECTION = 
            Contacts._ID,
            ContactsContract.Contacts.PHOTO_THUMBNAIL_URI,
            ContactsContract.Contacts.DISPLAY_NAME_PRIMARY,
            ContactsContract.Contacts.HAS_PHONE_NUMBER,
    ;

    // this goes in the CursorLoader parameter list, it filters
    // out only those contacts who have a phone number
    private static final String FILTER = 
            ContactsContract.Contacts.PHOTO_THUMBNAIL_URI + "=?" +
            ContactsContract.Contacts.DISPLAY_NAME_PRIMARY + "=?" +
            ContactsContract.Contacts.HAS_PHONE_NUMBER + "=?";

    private static final String[] SELECTION_ARGS = 
            ContactsContract.Contacts.PHOTO_THUMBNAIL_URI,
            ContactsContract.Contacts.DISPLAY_NAME_PRIMARY,
            ContactsContract.Contacts.HAS_PHONE_NUMBER
    ;


    @Override
    public void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);

        // delete list if already there (old version)
        if (!(listView == null))
            listView.setAdapter(null);
        

        // create adapter once
        context = getActivity();
        int layout = android.R.layout.simple_list_item_1;
        Cursor c = null; // there is no cursor yet
        int flags = 0; // no auto-requery! Loader requeries.
        // put List in adapter
        mAdapter = new SimpleCursorAdapter(context, layout, c, FROM, TO, flags);


     // end onCreate


    // Empty public constructor, required by the system
    public ContactsFragment() 

    // A UI Fragment must inflate its View (all fragments must override onCreateView)
//    @Override
//    public View onCreateView(LayoutInflater inflater, ViewGroup container,
//            Bundle savedInstanceState) 
//        // Inflate the fragment layout
//        View view =  inflater.inflate(R.layout.fragment_list_view,
//            container, false);
//        listView = (ListView) view.findViewById(R.id.contact_list); 
//        
//        return view;
//    

    public void onActivityCreated(Bundle savedInstanceState) 
        super.onActivityCreated(savedInstanceState);

        // every time we start, use a list adapter
        setListAdapter(mAdapter);
//        // scroll faster
//        listView.setFastScrollEnabled(true);

        // and tell loader manager to start loading
        getLoaderManager().initLoader(0, null, this);

    

    // a CursorLoader does a query in the background
    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) 
        // load from the "Contacts table"
        Uri contentUri = Contacts.CONTENT_URI;

        // no sub-selection, no sort order, simply every row
        // projection says we want just the _id and the name column
        return new CursorLoader(getActivity(),
                contentUri,
                PROJECTION,
                FILTER,
                SELECTION_ARGS,
                ContactsContract.Contacts.DISPLAY_NAME + "ASC");
    

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor data) 
         // Once cursor is loaded, give it to adapter
        mAdapter.swapCursor(data);
    

    @Override
    public void onLoaderReset(Loader<Cursor> loader) 
        // Delete the reference to the existing Cursor,
        // so it can recycle it
        mAdapter.swapCursor(null);

    

Logcat

12-26 20:45:16.398: I/PersonaManager(18479): getPersonaService() name persona_policy
12-26 20:45:16.478: D/skia(18479): GFXPNG PNG bitmap created width:48 height:48 bitmap id is 270 
12-26 20:45:16.478: E/MoreInfoHPW_ViewGroup(18479): Parent view is not a TextView
12-26 20:45:16.488: D/skia(18479): GFXPNG PNG bitmap created width:72 height:72 bitmap id is 271 
12-26 20:45:16.498: D/skia(18479): GFXPNG PNG bitmap created width:144 height:144 bitmap id is 272 
12-26 20:45:16.508: D/skia(18479): GFXPNG PNG bitmap created width:144 height:144 bitmap id is 273 
12-26 20:45:16.558: I/Adreno-EGL(18479): <qeglDrvAPI_eglInitialize:410>: EGL 1.4 QUALCOMM build:  ()
12-26 20:45:16.558: I/Adreno-EGL(18479): OpenGL ES Shader Compiler Version: E031.24.00.08+13
12-26 20:45:16.558: I/Adreno-EGL(18479): Build Date: 03/20/14 Thu
12-26 20:45:16.558: I/Adreno-EGL(18479): Local Branch: 0320_AU200_patches
12-26 20:45:16.558: I/Adreno-EGL(18479): Remote Branch: 
12-26 20:45:16.558: I/Adreno-EGL(18479): Local Patches: 
12-26 20:45:16.558: I/Adreno-EGL(18479): Reconstruct Branch: 
12-26 20:45:16.638: D/OpenGLRenderer(18479): Enabling debug mode 0
12-26 20:45:17.678: I/PersonaManager(18479): getPersonaService() name persona_policy
12-26 20:45:17.688: E/MoreInfoHPW_ViewGroup(18479): Parent view is not a TextView
12-26 20:45:17.708: D/skia(18479): GFXPNG PNG bitmap created width:228 height:228 bitmap id is 274 
12-26 20:45:17.708: D/skia(18479): GFXPNG PNG bitmap created width:228 height:228 bitmap id is 275 
12-26 20:45:17.718: D/skia(18479): GFXPNG PNG bitmap created width:12 height:12 bitmap id is 276 
12-26 20:45:17.718: D/AbsListView(18479): Get MotionRecognitionManager
12-26 20:45:17.728: D/AbsListView(18479): onVisibilityChanged() is called, visibility : 8
12-26 20:45:17.728: D/AbsListView(18479): unregisterIRListener() is called 
12-26 20:45:17.728: D/AbsListView(18479): onVisibilityChanged() is called, visibility : 0
12-26 20:45:17.728: D/AbsListView(18479): unregisterIRListener() is called 
12-26 20:45:17.738: D/AbsListView(18479): onVisibilityChanged() is called, visibility : 4
12-26 20:45:17.738: D/AbsListView(18479): unregisterIRListener() is called 
12-26 20:45:17.738: D/AbsListView(18479): onVisibilityChanged() is called, visibility : 0
12-26 20:45:17.738: D/AbsListView(18479): unregisterIRListener() is called 
12-26 20:45:17.748: D/AbsListView(18479): unregisterIRListener() is called 
12-26 20:45:17.768: W/dalvikvm(18479): threadid=11: thread exiting with uncaught exception (group=0x41737da0)
12-26 20:45:17.768: E/AndroidRuntime(18479): FATAL EXCEPTION: AsyncTask #1
12-26 20:45:17.768: E/AndroidRuntime(18479): Process: com.example.practiceapp, PID: 18479
12-26 20:45:17.768: E/AndroidRuntime(18479): java.lang.RuntimeException: An error occured while executing doInBackground()
12-26 20:45:17.768: E/AndroidRuntime(18479):    at android.os.AsyncTask$3.done(AsyncTask.java:300)
12-26 20:45:17.768: E/AndroidRuntime(18479):    at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
12-26 20:45:17.768: E/AndroidRuntime(18479):    at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
12-26 20:45:17.768: E/AndroidRuntime(18479):    at java.util.concurrent.FutureTask.run(FutureTask.java:242)
12-26 20:45:17.768: E/AndroidRuntime(18479):    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
12-26 20:45:17.768: E/AndroidRuntime(18479):    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
12-26 20:45:17.768: E/AndroidRuntime(18479):    at java.lang.Thread.run(Thread.java:841)
12-26 20:45:17.768: E/AndroidRuntime(18479): Caused by: android.database.sqlite.SQLiteException: near "display_name": syntax error (code 1): , while compiling: SELECT _id, photo_thumb_uri, display_name, has_phone_number FROM view_contacts_restricted WHERE ((1)) AND ((photo_thumb_uri=?display_name=?has_phone_number=?)) ORDER BY display_nameASC
12-26 20:45:17.768: E/AndroidRuntime(18479):    at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:181)
12-26 20:45:17.768: E/AndroidRuntime(18479):    at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:137)
12-26 20:45:17.768: E/AndroidRuntime(18479):    at android.content.ContentProviderProxy.query(ContentProviderNative.java:413)
12-26 20:45:17.768: E/AndroidRuntime(18479):    at android.content.ContentResolver.query(ContentResolver.java:464)
12-26 20:45:17.768: E/AndroidRuntime(18479):    at android.content.CursorLoader.loadInBackground(CursorLoader.java:65)
12-26 20:45:17.768: E/AndroidRuntime(18479):    at android.content.CursorLoader.loadInBackground(CursorLoader.java:43)
12-26 20:45:17.768: E/AndroidRuntime(18479):    at android.content.AsyncTaskLoader.onLoadInBackground(AsyncTaskLoader.java:312)
12-26 20:45:17.768: E/AndroidRuntime(18479):    at android.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:69)
12-26 20:45:17.768: E/AndroidRuntime(18479):    at android.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:57)
12-26 20:45:17.768: E/AndroidRuntime(18479):    at android.os.AsyncTask$2.call(AsyncTask.java:288)
12-26 20:45:17.768: E/AndroidRuntime(18479):    at java.util.concurrent.FutureTask.run(FutureTask.java:237)
12-26 20:45:17.768: E/AndroidRuntime(18479):    ... 3 more
12-26 20:45:17.778: D/AbsListView(18479): unregisterIRListener() is called 
12-26 20:45:17.818: D/AbsListView(18479): unregisterIRListener() is called 
12-26 20:45:17.858: D/AbsListView(18479): unregisterIRListener() is called 
12-26 20:45:17.868: D/AbsListView(18479): unregisterIRListener() is called 
12-26 20:45:18.398: D/AbsListView(18479): onDetachedFromWindow
12-26 20:45:18.398: D/AbsListView(18479): unregisterIRListener() is called 

向“ASC”添加空间后的Logcat

12-26 21:24:44.808: I/PersonaManager(25167): getPersonaService() name persona_policy
12-26 21:24:44.818: E/MoreInfoHPW_ViewGroup(25167): Parent view is not a TextView
12-26 21:24:44.848: D/skia(25167): GFXPNG PNG bitmap created width:228 height:228 bitmap id is 274 
12-26 21:24:44.848: D/skia(25167): GFXPNG PNG bitmap created width:228 height:228 bitmap id is 275 
12-26 21:24:44.858: D/skia(25167): GFXPNG PNG bitmap created width:12 height:12 bitmap id is 276 
12-26 21:24:44.858: D/AbsListView(25167): Get MotionRecognitionManager
12-26 21:24:44.868: D/AbsListView(25167): onVisibilityChanged() is called, visibility : 8
12-26 21:24:44.868: D/AbsListView(25167): unregisterIRListener() is called 
12-26 21:24:44.868: D/AbsListView(25167): onVisibilityChanged() is called, visibility : 0
12-26 21:24:44.868: D/AbsListView(25167): unregisterIRListener() is called 
12-26 21:24:44.868: D/AbsListView(25167): onVisibilityChanged() is called, visibility : 4
12-26 21:24:44.868: D/AbsListView(25167): unregisterIRListener() is called 
12-26 21:24:44.878: D/AbsListView(25167): onVisibilityChanged() is called, visibility : 0
12-26 21:24:44.878: D/AbsListView(25167): unregisterIRListener() is called 
12-26 21:24:44.878: D/AbsListView(25167): unregisterIRListener() is called 
12-26 21:24:44.898: D/AbsListView(25167): unregisterIRListener() is called 
12-26 21:24:44.908: W/dalvikvm(25167): threadid=11: thread exiting with uncaught exception (group=0x41737da0)
12-26 21:24:44.908: E/AndroidRuntime(25167): FATAL EXCEPTION: AsyncTask #1
12-26 21:24:44.908: E/AndroidRuntime(25167): Process: com.example.practiceapp, PID: 25167
12-26 21:24:44.908: E/AndroidRuntime(25167): java.lang.RuntimeException: An error occured while executing doInBackground()
12-26 21:24:44.908: E/AndroidRuntime(25167):    at android.os.AsyncTask$3.done(AsyncTask.java:300)
12-26 21:24:44.908: E/AndroidRuntime(25167):    at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
12-26 21:24:44.908: E/AndroidRuntime(25167):    at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
12-26 21:24:44.908: E/AndroidRuntime(25167):    at java.util.concurrent.FutureTask.run(FutureTask.java:242)
12-26 21:24:44.908: E/AndroidRuntime(25167):    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
12-26 21:24:44.908: E/AndroidRuntime(25167):    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
12-26 21:24:44.908: E/AndroidRuntime(25167):    at java.lang.Thread.run(Thread.java:841)
12-26 21:24:44.908: E/AndroidRuntime(25167): Caused by: android.database.sqlite.SQLiteException: near "display_name": syntax error (code 1): , while compiling: SELECT _id, photo_thumb_uri, display_name, has_phone_number FROM view_contacts_restricted WHERE ((1)) AND ((photo_thumb_uri=?display_name=?has_phone_number=?)) ORDER BY display_name ASC
12-26 21:24:44.908: E/AndroidRuntime(25167):    at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:181)
12-26 21:24:44.908: E/AndroidRuntime(25167):    at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:137)
12-26 21:24:44.908: E/AndroidRuntime(25167):    at android.content.ContentProviderProxy.query(ContentProviderNative.java:413)
12-26 21:24:44.908: E/AndroidRuntime(25167):    at android.content.ContentResolver.query(ContentResolver.java:464)
12-26 21:24:44.908: E/AndroidRuntime(25167):    at android.content.CursorLoader.loadInBackground(CursorLoader.java:65)
12-26 21:24:44.908: E/AndroidRuntime(25167):    at android.content.CursorLoader.loadInBackground(CursorLoader.java:43)
12-26 21:24:44.908: E/AndroidRuntime(25167):    at android.content.AsyncTaskLoader.onLoadInBackground(AsyncTaskLoader.java:312)
12-26 21:24:44.908: E/AndroidRuntime(25167):    at android.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:69)
12-26 21:24:44.908: E/AndroidRuntime(25167):    at android.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:57)
12-26 21:24:44.908: E/AndroidRuntime(25167):    at android.os.AsyncTask$2.call(AsyncTask.java:288)
12-26 21:24:44.908: E/AndroidRuntime(25167):    at java.util.concurrent.FutureTask.run(FutureTask.java:237)
12-26 21:24:44.908: E/AndroidRuntime(25167):    ... 3 more
12-26 21:24:44.918: D/AbsListView(25167): unregisterIRListener() is called 
12-26 21:24:45.008: D/AbsListView(25167): unregisterIRListener() is called 
12-26 21:24:45.008: D/AbsListView(25167): unregisterIRListener() is called 
12-26 21:24:45.148: D/AbsListView(25167): onDetachedFromWindow
12-26 21:24:45.158: D/AbsListView(25167): unregisterIRListener() is called 
12-26 21:24:46.978: I/Process(25167): Sending signal. PID: 25167 SIG: 9

【问题讨论】:

问题似乎是您查询的这一部分 AND ((photo_thumb_uri=?display_name=?has_phone_number=?)) 您需要通过 OR/AND 运算符将其分开 好的,谢谢 Rajen。我只是不知道它们有什么问题,这些是我查询中的 3 个常量。我会再看一遍。你认为我可以在FROMPROJECTIONFILTERPROJECTIONSELECTION_ARGS 中使用它们吗?我想知道是不是重复次数太多了。 【参考方案1】:

ContactsContract.Contacts.DISPLAY_NAME"ASC" 之间需要空格

改变这个

return new CursorLoader(getActivity(),
            contentUri,
            PROJECTION,
            FILTER,
            SELECTION_ARGS,
            ContactsContract.Contacts.DISPLAY_NAME + "ASC");

进入

return new CursorLoader(getActivity(),
            contentUri,
            PROJECTION,
            FILTER,
            SELECTION_ARGS,
            ContactsContract.Contacts.DISPLAY_NAME + " ASC");

【讨论】:

感谢 kalyan,我添加了一个空格,但仍然出现同样的错误。 好的,我在上面加了。

以上是关于SQLite 异常错误,使用 CursorLoader 和 ContactContracts的主要内容,如果未能解决你的问题,请参考以下文章

核心数据异常:向实体添加新属性后出现 SQLite“没有这样的列”错误

sqlite3 operationalerror异常

如何在 ios 中捕获数据库异常?

安卓SQLite常见错误

Android SQLite“没有这样的表”异常

使用 sqlite3 在 django 中出现“太多 SQL 变量”错误