Android - 当用户选择搜索建议时如何传递数据?

时间:2014-09-30 20:06:41

标签: android search search-suggestion

我正在使用搜索建议创建SearchActivity。当您开始在SearchView中输入单词时,建议会按预期显示,但是当您单击其中一个建议时,我最终会出现此错误:

  

没有这样的专栏:产品

这似乎与我的searchable.xml条目有关...

android:searchSuggestIntentData="content://com.example.dbcontentprovider/products

...因为传递给我的DbContentProvider类的query()方法的URI是......

  

内容://com.example.dbcontentprovider/products

......然而,我认为它应该是......

  

内容://com.example.dbcontentprovider/products/(id_of_selected_product)

我认为问题可能是我没有正确使用投影地图中的SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID数据,但我已经尝试了我能想到的每一个组合,但我无处可去。

Android文档没有任何帮助,我工作的Reto Meier书并没有提到任何问题,所以任何人都可以提出解决方案。

我的相关代码位是......

DbContentProvider.java:

package com.example;

import java.util.HashMap;

import android.app.SearchManager;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;

public class DbContentProvider extends ContentProvider {

private static final String LOG_TAG = SQLiteOpenHelper.class.getSimpleName();
private static final String CONTENT_URI_BASE = "com.example.dbcontentprovider";

public static final Uri CONTENT_URI = Uri.parse("content://"
        + CONTENT_URI_BASE + "/products");

// The index (key) column name for use in where clauses.
public static final String KEY_ID = "_id";
public static final String KEY_ID_AS = SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID;
public static final String KEY_BRAND_NAME = "brand_name";
public static final String KEY_BRAND_NAME_AS = SearchManager.SUGGEST_COLUMN_TEXT_1;
public static final String KEY_PARENT_COMPANY_ID = "parent_company_id";
public static final String KEY_LAST_MODIFIED_ON = "last_modified_on";

private static final HashMap<String, String> SEARCH_SUGGEST_PROJECTION_MAP;
static {
    SEARCH_SUGGEST_PROJECTION_MAP = new HashMap<String, String>();
    SEARCH_SUGGEST_PROJECTION_MAP.put(KEY_ID, KEY_ID + " AS " + KEY_ID);
    SEARCH_SUGGEST_PROJECTION_MAP.put(KEY_BRAND_NAME_AS, KEY_BRAND_NAME + " AS " + KEY_BRAND_NAME_AS);
    SEARCH_SUGGEST_PROJECTION_MAP.put(KEY_PARENT_COMPANY_ID, KEY_PARENT_COMPANY_ID + " AS " + SearchManager.SUGGEST_COLUMN_TEXT_2);
    SEARCH_SUGGEST_PROJECTION_MAP.put(KEY_LAST_MODIFIED_ON, KEY_LAST_MODIFIED_ON);
    SEARCH_SUGGEST_PROJECTION_MAP.put(KEY_ID_AS, KEY_ID + " AS " + KEY_ID);

}

private static final int ALL_ROWS = 1;
private static final int SINGLE_ROW = 2;
private static final int SEARCH_SUGGEST = 3;



/*
 * Create the UrIMatcher object, where a URI ending in 'products' will
 * correspond to a request for all items, and 'products/[rowID]' represents
 * a single row.
 */
private static final UriMatcher uriMatcher;
static {
    uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
    uriMatcher.addURI(CONTENT_URI_BASE, "products", ALL_ROWS);
    uriMatcher.addURI(CONTENT_URI_BASE, "products/#", SINGLE_ROW);
    uriMatcher.addURI(CONTENT_URI_BASE, SearchManager.SUGGEST_URI_PATH_QUERY, SEARCH_SUGGEST);
    uriMatcher.addURI(CONTENT_URI_BASE, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", SEARCH_SUGGEST);
    uriMatcher.addURI(CONTENT_URI_BASE, SearchManager.SUGGEST_URI_PATH_SHORTCUT, SEARCH_SUGGEST);
    uriMatcher.addURI(CONTENT_URI_BASE, SearchManager.SUGGEST_URI_PATH_SHORTCUT + "/*", SEARCH_SUGGEST);
}

private DbHelper dbHelper;

@Override
public boolean onCreate() {
    dbHelper = new DbHelper(getContext());
    return true;
}

@Override
public Cursor query(Uri uri, String[] projection, String selection,
        String[] selectionArgs, String sortOrder) {

    Log.d(LOG_TAG, "query()");
    Log.d(LOG_TAG, "    projection: " + Utilities.toString(projection));
    Log.d(LOG_TAG, "    selection: " + selection);
    Log.d(LOG_TAG, "    selectionArgs: " + Utilities.toString(selectionArgs));
    Log.d(LOG_TAG, "    sortOrder: " + sortOrder);

    // Open the database
    SQLiteDatabase db = dbHelper.getReadableDatabase();

    String groupBy = null;
    String having = null;

    SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();

    // Specify the table on which to perform the query. This can be a
    // specific table or a join as required.
    queryBuilder.setTables(DbHelper.BRAND_NAMES_TABLE);

    // If this is a row query, limit the result set to the passed in row
    switch (uriMatcher.match(uri)) {
        case SINGLE_ROW:
            Log.d(LOG_TAG, "query (single): " + uri);
            String rowID = uri.getPathSegments().get(1);
            queryBuilder.appendWhere(KEY_ID + " = " + rowID);
            break;
        case SEARCH_SUGGEST: 
            Log.d(LOG_TAG, "query (suggestion): " + uri);
            String query = uri.getPathSegments().get(1);
            queryBuilder.appendWhere(KEY_BRAND_NAME + " LIKE \"%" + query + "%\"");
            queryBuilder.setProjectionMap(SEARCH_SUGGEST_PROJECTION_MAP); 
            break;
        case ALL_ROWS:
            //Don't modify
            Log.d(LOG_TAG, "query (all rows): " + uri);
            break;
        default:
            Log.d(LOG_TAG, "query (default): " + uri);
            break;
    }

    String sql = queryBuilder.buildQuery(projection, selection, groupBy, having, sortOrder, null);
    Log.d(LOG_TAG, "sql: " + sql);

    // Execute the query
    Cursor cursor = queryBuilder.query(db, projection, selection, selectionArgs, groupBy, having, sortOrder);

    Log.d(LOG_TAG, "cursor count: " + cursor.getCount());

    return cursor;
}

@Override
public Uri insert(Uri uri, ContentValues values) {
    // Open a read / write database to support the transaction.
    SQLiteDatabase db = dbHelper.getWritableDatabase();

    // Insert the values into the table
    long id = db.insert(DbHelper.BRAND_NAMES_TABLE, null, values);

    // Construct and return the URI of the newly inserted row.
    if (id > -1) {
        // Construct and return the URI of the newly inserted row.
        Uri insertedId = ContentUris.withAppendedId(CONTENT_URI, id);

        // Notify any observers of the change in the data set.
        getContext().getContentResolver().notifyChange(insertedId, null);

        return insertedId;
    } else {
        return null;
    }
}

@Override
public int update(Uri uri, ContentValues values, String selection,
        String[] selectionArgs) {

    // Open a read / write database to support the transaction.
    SQLiteDatabase db = dbHelper.getWritableDatabase();

    // If this is a row URI, limit the deletion to the specified row.
    switch (uriMatcher.match(uri)) {
    case SINGLE_ROW:
        String rowID = uri.getPathSegments().get(1);
        selection = KEY_ID + " = " + rowID + (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : "");
        break;
    default:
        break;
    }

    // Perform the update.
    int updateCount = db.update(DbHelper.BRAND_NAMES_TABLE, values,
            selection, selectionArgs);

    // Notify any observers of the change in the data set.
    getContext().getContentResolver().notifyChange(uri, null);

    return updateCount;
}

@Override
  public int delete(Uri uri, String selection, String[] selectionArgs) {
    // Open a read / write database to support the transaction.
    SQLiteDatabase db = dbHelper.getWritableDatabase();

    // If this is a row URI, limit the deletion to the specified row.
    switch (uriMatcher.match(uri)) {
        case SINGLE_ROW : 
            String rowID = uri.getPathSegments().get(1);
            selection = KEY_ID + " = " + rowID+ (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : "");
            break;
        default:
            break;
    }

    // To return the number of deleted items you must specify a where
    // clause. To delete all rows and return a value pass in "1".
    if (selection == null)
      selection = "1";

    // Perform the deletion.
    int deleteCount = db.delete(DbHelper.BRAND_NAMES_TABLE, 
      selection, selectionArgs);

    // Notify any observers of the change in the data set.
    getContext().getContentResolver().notifyChange(uri, null);

    // Return the number of deleted items.
    return deleteCount;
  }

@Override
public String getType(Uri uri) {
    // Return a string that identifies the MIME type
    // for a Content Provider URI
    switch (uriMatcher.match(uri)) {
    case ALL_ROWS:
        return "vnd.android.cursor.dir/vnd.mobilewebexpert.elemental";
    case SINGLE_ROW:
        return "vnd.android.cursor.item/vnd.mobilewebexpert.elemental";
    case SEARCH_SUGGEST:
        return SearchManager.SUGGEST_MIME_TYPE;
    default:
        throw new IllegalArgumentException("Unsupported URI: " + uri);
    }
}

private class DbHelper extends SQLiteOpenHelper {

    private static final String DATABASE_NAME = "products.db";
    private static final String BRAND_NAMES_TABLE = "brand_names";
    private static final int DATABASE_VERSION = 1;

    // SQL Statement to create a new database.
    private static final String DATABASE_CREATE_SQL = "CREATE TABLE " + 
            BRAND_NAMES_TABLE + " (" + 
            KEY_ID + " integer PRIMARY KEY AUTOINCREMENT, " +
            KEY_BRAND_NAME + " text NOT NULL, " +
            KEY_PARENT_COMPANY_ID + " integer NOT NULL DEFAULT '0', " +
            KEY_LAST_MODIFIED_ON + " datetime NOT NULL DEFAULT CURRENT_TIMESTAMP);";


    public DbHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    /*
     * Called when no database exists in disk and the help class needs to create a new
     * one.
     */
    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(DATABASE_CREATE_SQL);
    }

    /*
     * Called when there is a database version mismatch meaning that the version of the
     * database on disk needs to be upgraded to the current version.
     */
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        Log.w(LOG_TAG, "Upgrading database from from version " + oldVersion + " to " + newVersion);

        //Drop the old table
        db.execSQL("DROP TABLE IF EXISTS " + BRAND_NAMES_TABLE);

        //Create new one
        onCreate(db);
    }

}
}

SearchActivity.java:

package com.example;

import android.app.Activity;
import android.app.LoaderManager;
import android.app.SearchManager;
import android.app.SearchableInfo;
import android.content.Context;
import android.content.CursorLoader;
import android.content.Intent;
import android.content.Loader;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.widget.SearchView;
import android.widget.Toast;

public class SearchActivity extends Activity implements LoaderManager.LoaderCallbacks<Cursor> {
private static final String LOG_TAG = SearchActivity.class.getSimpleName();

private static final int LOADER_ID = 0;

@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    String[] resultColumns = {DbContentProvider.KEY_ID, DbContentProvider.KEY_BRAND_NAME};
    String where;
    if (args.getString(DbContentProvider.KEY_BRAND_NAME) != null) {
        where = DbContentProvider.KEY_BRAND_NAME + " LIKE \"%" + args.getString(DbContentProvider.KEY_BRAND_NAME) + "%\""; //todo - use fulltext search
    }
    else {
        where = DbContentProvider.KEY_ID + " = " + args.getString(DbContentProvider.KEY_ID);
    }
    String[] whereArgs = null;
    String order = null; //todo
    return new CursorLoader(SearchActivity.this, DbContentProvider.CONTENT_URI, resultColumns, where, whereArgs, order);
}

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
    // Replace the result Cursor displayed by the Cursor Adapter with  
    // the new result set.
    try {
        int idColumnIndex = cursor.getColumnIndexOrThrow(DbContentProvider.KEY_ID);
        int brandNameColumnIndex = cursor.getColumnIndexOrThrow(DbContentProvider.KEY_BRAND_NAME);
        if (cursor.getCount() > 0) {                
            while(cursor.moveToNext()) {
                final String id = cursor.getString(idColumnIndex);
                final String brandName = cursor.getString(brandNameColumnIndex);

                new Handler().post(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(SearchActivity.this, "Search result: " + id + ". " + brandName, Toast.LENGTH_SHORT).show();
                    }
                });

            }
        }
        else {
            Toast.makeText(SearchActivity.this, "No results found.", Toast.LENGTH_SHORT).show();
        }
    }
    catch(Exception e) {
        Log.e(LOG_TAG, "Search exception", e);
    }
    finally {
        try {
            cursor.close();
        }
        catch(Exception ignore) {
        }
    }

    // This handler is not synchonrized with the UI thread, so you 
    // will need to synchronize it before modiyfing any UI elements
    // directly.

}

@Override
public void onLoaderReset(Loader<Cursor> loader) {
    // Remove the existing result Cursor from the List Adapter.
    //adapter.swapCursor(null);

    // This handler is not synchonrized with the UI thread, so you 
    // will need to synchronize it before modiyfing any UI elements
    // directly.

}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_search);

    // Use the Search Manager to find the SearchableInfo related to this Activity
    SearchManager searchManager = (SearchManager)getSystemService(Context.SEARCH_SERVICE);
    SearchableInfo searchableInfo = searchManager.getSearchableInfo(getComponentName());

    // Bind the Activity's SearchableInfo to the Search View
    final SearchView searchView = (SearchView)findViewById(R.id.searchView);
    searchView.setSearchableInfo(searchableInfo);
    searchView.setIconifiedByDefault(false);
    searchView.setSubmitButtonEnabled(true);
    //searchView.setQueryRefinementEnabled(true);

    /*
     * If this Activity was launched with a search intent, then see to it
     */
    parseIntent(getIntent());

}

@Override
public void onNewIntent(Intent intent){
    super.onNewIntent(intent);
    parseIntent(intent);
}

private void parseIntent(Intent intent) {

    /*
     * If the activity was started to service a Search request, extract the query
     */
    if (Intent.ACTION_SEARCH.equals(intent.getAction())) { //Normal search submitted
        String searchQuery = intent.getStringExtra(SearchManager.QUERY);
        performSearch(DbContentProvider.KEY_BRAND_NAME, searchQuery);
    }
    else if (Intent.ACTION_VIEW.equals(intent.getAction())) { //Suggestion was clicked
        Log.d(LOG_TAG, "intent: " + intent);
        String query = intent.getExtras().get(SearchManager.USER_QUERY).toString();
        Log.d(LOG_TAG, "query: " + query);
        Uri detailUri = intent.getData();
        Log.d(LOG_TAG, "detailUri: " + detailUri);
        String id = detailUri.getLastPathSegment();
        Log.d(LOG_TAG, "id: " + id);
        performSearch(DbContentProvider.KEY_ID, id);
    } 
}

private void performSearch(String searchKey, String searchValue) {
    //Toast.makeText(this, "Search query: \"" + searchQuery + "\"", Toast.LENGTH_SHORT).show();
    Bundle args = new Bundle();
    args.putString(searchKey, searchValue);
    getLoaderManager().restartLoader(LOADER_ID, args, this);
}
}

searchable.xml:

<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:label="@string/app_name"
android:hint="@string/search_hint"

android:searchSuggestAuthority="com.example.dbcontentprovider"
android:searchSuggestIntentAction="android.intent.action.VIEW"
android:searchSuggestIntentData="content://com.example.dbcontentprovider/products"
android:searchSuggestThreshold="3"

android:includeInGlobalSearch="true"
android:searchSettingsDescription="@string/search_settings_description"
android:queryAfterZeroResults="true"
android:voiceSearchMode="showVoiceSearchButton" >   
</searchable>

的AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk
    android:minSdkVersion="11"
    android:targetSdkVersion="19" />

<uses-permission 
    android:name="android.permission.INTERNET" />

<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name=".SplashActivity"
        android:label="@string/app_name_short"
        android:launchMode="singleTop" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity
        android:name=".RegisterActivity"
        android:label="@string/title_activity_register" >
    </activity>
    <activity
        android:name=".LoginActivity"
        android:label="@string/title_activity_login" >
    </activity>
    <activity
        android:name=".SearchActivity"
        android:label="@string/app_name"
        android:launchMode="singleTop" >
        <intent-filter>
            <action android:name="android.intent.action.SEARCH" />
        </intent-filter>
        <meta-data
            android:name="android.app.searchable" 
            android:resource="@xml/searchable" />
        <meta-data
            android:name="android.app.default_searchable" 
            android:value=".SearchActivity" />
    </activity>

    <provider
        android:name=".DbContentProvider"
        android:authorities="com.example.dbcontentprovider"
        android:exported="true" />

</application>

</manifest>

并且(在一分钱......),点击建议后,这里是上述代码的LogCat输出...

  

09-30 21:01:39.720:D / AbsListView(4571):onDetachedFromWindow   09-30 21:01:39.720:D / AbsListView(4571):调用unregisterIRListener()   09-30 21:01:39.770:D / SearchActivity(4571):intent:Intent {act = android.intent.action.VIEW dat = content://com.example.dbcontentprovider/products flg = 0x10000000 cmp = com.example /.SearchActivity(有额外的)}   09-30 21:01:39.770:D / SearchActivity(4571):查询:hei    09-30 21:01:39.770:D / SearchActivity(4571):detailUri:content://com.example.dbcontentprovider/products   09-30 21:01:39.770:D / SearchActivity(4571):id:products   09-30 21:01:39.780:D / SQLiteOpenHelper(4571):query()   09-30 21:01:39.780:D / SQLiteOpenHelper(4571):projection:{&#34; _id&#34;,&#34; brand_name&#34;}    09-30 21:01:39.780:D / SQLiteOpenHelper(4571):选择:_id =产品   09-30 21:01:39.780:D / SQLiteOpenHelper(4571):selectionArgs:null   09-30 21:01:39.780:D / SQLiteOpenHelper(4571):sortOrder:null   09-30 21:01:39.780:D / SQLiteOpenHelper(4571):query(所有行):content://com.example.dbcontentprovider/products    09-30 21:01:39.780:D / SQLiteOpenHelper(4571):sql:SELECT _id,brand_name FROM brand_names WHERE(_id = products)   09-30 21:01:39.780:E / SQLiteLog(4571):( 1)没有这样的栏目:产品   09-30 21:01:39.780:W / dalvikvm(4571):threadid = 16:线程退出,未捕获异常(group = 0x41ebcda0)   09-30 21:01:39.780:E / AndroidRuntime(4571):致命异常:AsyncTask#3   09-30 21:01:39.780:E / AndroidRuntime(4571):处理:com.example,PID:4571   09-30 21:01:39.780:E / AndroidRuntime(4571):java.lang.RuntimeException:执行doInBackground()时发生错误   09-30 21:01:39.780:E / AndroidRuntime(4571):在android.os.AsyncTask $ 3.done(AsyncTask.java:300)   09-30 21:01:39.780:E / AndroidRuntime(4571):at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)   09-30 21:01:39.780:E / AndroidRuntime(4571):at java.util.concurrent.FutureTask.setException(FutureTask.java:222)   09-30 21:01:39.780:E / AndroidRuntime(4571):at java.util.concurrent.FutureTask.run(FutureTask.java:242)   09-30 21:01:39.780:E / AndroidRuntime(4571):at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)   09-30 21:01:39.780:E / AndroidRuntime(4571):at java.util.concurrent.ThreadPoolExecutor $ Worker.run(ThreadPoolExecutor.java:587)   09-30 21:01:39.780:E / AndroidRuntime(4571):at java.lang.Thread.run(Thread.java:841)    09-30 21:01:39.780:E / AndroidRuntime(4571):引起:android.database.sqlite.SQLiteException:没有这样的列:产品(代码1):,同时编译:SELECT _id,brand_name FROM brand_names WHERE(_id =产品)   09-30 21:01:39.780:E / AndroidRuntime(4571):在android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)   09-30 21:01:39.780:E / AndroidRuntime(4571):在android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:1121)   09-30 21:01:39.780:E / AndroidRuntime(4571):在android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:694)   09-30 21:01:39.780:E / AndroidRuntime(4571):在android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588)   09-30 21:01:39.780:E / AndroidRuntime(4571):在android.database.sqlite.SQLiteProgram。(SQLiteProgram.java:58)   09-30 21:01:39.780:E / AndroidRuntime(4571):在android.database.sqlite.SQLiteQuery。(SQLiteQuery.java:37)   09-30 21:01:39.780:E / AndroidRuntime(4571):在android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:44)   09-30 21:01:39.780:E / AndroidRuntime(4571):在android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1436)   09-30 21:01:39.780:E / AndroidRuntime(4571):在android.database.sqlite.SQLiteQueryBuilder.query(SQLiteQueryBuilder.java:400)   09-30 21:01:39.780:E / AndroidRuntime(4571):在android.database.sqlite.SQLiteQueryBuilder.query(SQLiteQueryBuilder.java:294)    09-30 21:01:39.780:E / AndroidRuntime(4571):at com.example.DbContentProvider.query(DbContentProvider.java:124)   09-30 21:01:39.780:E / AndroidRuntime(4571):在android.content.ContentProvider.query(ContentProvider.java:857)   09-30 21:01:39.780:E / AndroidRuntime(4571):在android.content.ContentProvider $ Transport.query(ContentProvider.java:200)   09-30 21:01:39.780:E / AndroidRuntime(4571):在android.content.ContentResolver.query(ContentResolver.java:464)   09-30 21:01:39.780:E / AndroidRuntime(4571):在android.content.CursorLoader.loadInBackground(CursorLoader.java:65)   09-30 21:01:39.780:E / AndroidRuntime(4571):在android.content.CursorLoader.loadInBackground(CursorLoader.java:43)   09-30 21:01:39.780:E / AndroidRuntime(4571):在android.content.AsyncTaskLoader.onLoadInBackground(AsyncTaskLoader.java:312)   09-30 21:01:39.780:E / AndroidRuntime(4571):在android.content.AsyncTaskLoader $ LoadTask.doInBackground(AsyncTaskLoader.java:69)   09-30 21:01:39.780:E / AndroidRuntime(4571):在android.content.AsyncTaskLoader $ LoadTask.doInBackground(AsyncTaskLoader.java:57)   09-30 21:01:39.780:E / AndroidRuntime(4571):在android.os.AsyncTask $ 2.call(AsyncTask.java:288)   09-30 21:01:39.780:E / AndroidRuntime(4571):at java.util.concurrent.FutureTask.run(FutureTask.java:237)   09-30 21:01:39.780:E / AndroidRuntime(4571):... 3更多

0 个答案:

没有答案