検索アクティビティ (ActivitySearch.java) があり、ソフト キーボードの [移動] ボタンを使用すると結果が正しく返され、検索候補からすべての結果が返されます。Content Provider と Cursor LoaderCallbacks を使用しています。LoaderCallbacks を試して検索アクティビティを実行するのはこれが初めてです。
onClickItem/onClickItemListenter を介して提案された結果の 1 つをクリックし、検索リストビューに戻ってユーザーが最終的に選択できるようにしたいのですが、私のコードが正しくないことは明らかです。参考までに、プロジェクト内のすべてのアクティビティを検索可能にしました。たくさんのサンプルを見てきましたが、正しい方法を見つけることができませんでした。
ハードウェア検索キーを押している単純なアクティビティ (ActivityFloor.java) を使用しています。インテントを開始するボタンはわずか数個です。
私の検索アクティビティは、リストビューの結果にデフォルトの Android ビューを使用します。MyListActivity からのアクティビティも継承しますが、これは共通メニューをサポートするためのものです。
これが私のマニフェストです:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.birdsall.tda"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-feature android:name="android.hardware.camera" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme"
android:uiOptions="splitActionBarWhenNarrow"
android:exported="true" >
<meta-data android:name="com.google.android.apps.drive.APP_ID" android:value="id=12345" />
<intent-filter>
<action android:name="com.google.android.apps.drive.DRIVE_OPEN" />
<data android:mimeType="application/vnd.google-apps.drive-sdk.12345" />
<data android:mimeType="image/png" />
<data android:mimeType="image/jpeg" />
<data android:mimeType="image/jpg" />
</intent-filter>
<meta-data
android:name="android.app.default_searchable"
android:value=".ActivitySearch" />
<activity
android:name="com.birdsall.tda.ActivityMain"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".ActivityFloor" >
</activity>
<provider
android:name="com.birdsall.tda.TDAProvider"
android:authorities="com.birdsall.tda.contentprovidertda"
android:exported="true"
android:readPermission="true"
android:writePermission="true" />
<activity
android:name=".ActivitySearch"
android:label="Rule Search"
android:launchMode="singleTop" >
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data
android:name="android.app.searchable"
android:resource="@xml/searchable" />
</activity>
</application>
</manifest>
res/xml にある私の searchable.xml は次のとおりです。
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:label="@string/app_name"
android:searchSettingsDescription="@string/search_description"
android:searchSuggestAuthority="com.birdsall.tda.contentprovidertda"
android:searchSuggestIntentAction="android.intent.action.VIEW"
android:searchSuggestIntentData="content://com.birdsall.tda.TDAProvider/rules"
android:voiceSearchMode="showVoiceSearchButton|launchRecognizer" >
</searchable>
これが私の検索アクティビティです(ActivitySearch.java):
package com.birdsall.tda;
import android.app.Activity;
import android.app.LoaderManager;
import android.app.SearchManager;
import android.content.ContentUris;
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.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;
public class ActivitySearch extends MyListActivity implements
LoaderManager.LoaderCallbacks<Cursor> {
private static String QUERY_EXTRA_KEY = "QUERY_EXTRA_KEY";
private SimpleCursorAdapter adapter;
private final String TAG = "ActivitySearch";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i(TAG, "onCreate");
View mListView = getListView();
Log.i(TAG, "onCreate ... after setOnItemClickListener");
Toast.makeText(getApplicationContext(), "onCreate ... after setOnItemClickListener", Toast.LENGTH_LONG).show();
// Create a new adapter and bind it to the List View
adapter = new SimpleCursorAdapter(this,
android.R.layout.simple_list_item_1, null,
new String[] { TDAdb.COL_RULETITLE },
new int[] { android.R.id.text1 }, 0);
setListAdapter(adapter);
// Initiate the Cursor Loader
getLoaderManager().initLoader(0, null, this);
// Get the launch Intent
parseIntent(getIntent());
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
Log.i(TAG, "onNewIntent");
Toast.makeText(getApplicationContext(), "onNewIntent", Toast.LENGTH_LONG).show();
parseIntent(getIntent());
}
private void parseIntent(Intent intent) {
// If the Activity was started to service a Search request,
// extract the search query.
Log.i(TAG, "parseIntent");
Toast.makeText(getApplicationContext(), "parseIntent", Toast.LENGTH_LONG).show();
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
String searchQuery = intent.getStringExtra(SearchManager.QUERY);
// Perform the search, passing in the search query as an argument
// to the Cursor Loader
Bundle args = new Bundle();
args.putString(QUERY_EXTRA_KEY, searchQuery);
// Restart the Cursor Loader to execute the new query.
getLoaderManager().restartLoader(0, args, this);
}
}
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
Log.i(TAG, "onCreateLoader");
Toast.makeText(getApplicationContext(), "onCreateLoader", Toast.LENGTH_LONG).show();
String query = "0";
if (args != null) {
// Extract the search query from the arguments.
query = args.getString(QUERY_EXTRA_KEY);
}
// Construct the new query in the form of a Cursor Loader.
String[] projection = { TDAdb.KEY_ROWID, TDAdb.COL_RULETITLE };
String where = TDAdb.COL_RULETITLE + " LIKE \"%" + query + "%\"";
String[] whereArgs = null;
String sortOrder = TDAdb.COL_RULETITLE;
// Create the new Cursor loader.
return new CursorLoader(this, TDAProvider.CONTENT_URI_RULES,
projection, where, whereArgs, sortOrder);
}
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
// Replace the result Cursor displayed by the Cursor Adapter with
// the new result set.
Log.i(TAG, "onLoadFinished");
Toast.makeText(getApplicationContext(), "onLoadFinished", Toast.LENGTH_LONG).show();
if (adapter == null) {
Log.i(TAG, "onLoadFinished ... adapter is NULL");
Toast.makeText(getApplicationContext(), "onLoadFinished ... adapter is NULL", Toast.LENGTH_LONG).show();
this.finish();
}
Log.i(TAG, "onLoadFinished ... adapter is valued");
Toast.makeText(getApplicationContext(), "onLoadFinished ... adapter is valued", Toast.LENGTH_LONG).show();
adapter.swapCursor(cursor);
}
public void onLoaderReset(Loader<Cursor> loader) {
// Remove the existing result Cursor from the List Adapter.
Log.i(TAG, "onLoaderReset");
Toast.makeText(getApplicationContext(), "onLoaderReset", Toast.LENGTH_LONG).show();
adapter.swapCursor(null);
}
private void handleIntent(Intent intent) {
Log.i(TAG, "handleIntent");
Toast.makeText(getApplicationContext(), "handleIntent", Toast.LENGTH_LONG).show();
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
// Gets the search query from the voice recognizer intent
String query = intent.getStringExtra(SearchManager.QUERY);
// Set the search box text to the received query and submit the
// search
// mSearchView.setQuery(query, true);
}
}
@Override
protected void onListItemClick(ListView listView, View view, int position, long id) {
super.onListItemClick(listView, view, position, id);
Toast.makeText(getApplicationContext(),
" search listview position:" + position,
Toast.LENGTH_LONG).show();
// Create a URI to the selected item.
Uri selectedUri =
ContentUris.withAppendedId(TDAProvider.CONTENT_URI, id);
// Create an Intent to view the selected item.
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(selectedUri);
// Start an Activity to view the selected item.
startActivity(intent);
}
}
Micheal (下記) に感謝します。したがって、LOGCAT エラーは無視できます。
エラーが発生しますが、完全を期すために含めた logcat から onClickItem コーディングを実装しようとした後でのみです。
06-2923:56:57.416: I/TDAProvider(13786): query
06-2923:56:57.439: W/SuggestionsAdapter(13786): Search suggestions query threw an exception.
06-2923:56:57.439: W/SuggestionsAdapter(13786): java.lang.IndexOutOfBoundsException
06-2923:56:57.439: W/SuggestionsAdapter(13786): at android.net.Uri$PathSegments.get(Uri.java:978)
06-2923:56:57.439: W/SuggestionsAdapter(13786): at android.net.Uri$PathSegments.get(Uri.java:963)
06-2923:56:57.439: W/SuggestionsAdapter(13786): at com.birdsall.tda.TDAProvider.query(TDAProvider.java:180)
06-2923:56:57.439: W/SuggestionsAdapter(13786): at android.content.ContentProvider.query(ContentProvider.java:652)
06-2923:56:57.439: W/SuggestionsAdapter(13786): at android.content.ContentProvider$Transport.query(ContentProvider.java:189)
06-2923:56:57.439: W/SuggestionsAdapter(13786): at android.content.ContentResolver.query(ContentResolver.java:370)
06-2923:56:57.439: W/SuggestionsAdapter(13786): at android.content.ContentResolver.query(ContentResolver.java:313)
06-2923:56:57.439: W/SuggestionsAdapter(13786): at android.app.SearchManager.getSuggestions(SearchManager.java:823)
06-2923:56:57.439: W/SuggestionsAdapter(13786): at android.widget.SuggestionsAdapter.runQueryOnBackgroundThread(SuggestionsAdapter.java:190)
06-2923:56:57.439: W/SuggestionsAdapter(13786): at android.widget.CursorFilter.performFiltering(CursorFilter.java:49)
06-2923:56:57.439: W/SuggestionsAdapter(13786): at android.widget.Filter$RequestHandler.handleMessage(Filter.java:234)
06-2923:56:57.439: W/SuggestionsAdapter(13786): at android.os.Handler.dispatchMessage(Handler.java:99)
06-2923:56:57.439: W/SuggestionsAdapter(13786): at android.os.Looper.loop(Looper.java:137)
06-2923:56:57.439: W/SuggestionsAdapter(13786): at android.os.HandlerThread.run(HandlerThread.java:60)
06-2923:57:00.002: I/TDAProvider(13786): query
06-2923:57:00.049: I/TDAProvider(13786): query return cursor
06-2923:57:00.635: I/TDAProvider(13786): query
06-2923:57:00.635: I/TDAProvider(13786): query return cursor
06-2923:57:01.275: I/TDAProvider(13786): query
06-2923:57:01.275: I/TDAProvider(13786): query return cursor
06-2923:57:02.650: W/InputEventReceiver(13786): Attempted to finish an input event but the input event receiver has already been disposed.
06-2923:57:02.689: I/ActivitySearch(13786): onCreate
06-2923:57:02.728: D/AndroidRuntime(13786): Shutting down VM
06-2923:57:02.728: W/dalvikvm(13786): threadid=1: thread exiting with uncaught exception (group=0x40e1b2a0)
06-2923:57:02.728: E/AndroidRuntime(13786): FATAL EXCEPTION: main
06-2923:57:02.728: E/AndroidRuntime(13786): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.birdsall.tda/com.birdsall.tda.ActivitySearch}: java.lang.ClassCastException: com.birdsall.tda.ActivitySearch cannot be cast to android.view.View$OnClickListener
06-2923:57:02.728: E/AndroidRuntime(13786): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2136)
06-2923:57:02.728: E/AndroidRuntime(13786): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2174)
06-2923:57:02.728: E/AndroidRuntime(13786): at android.app.ActivityThread.access$700(ActivityThread.java:141)
06-2923:57:02.728: E/AndroidRuntime(13786): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1267)
06-2923:57:02.728: E/AndroidRuntime(13786): at android.os.Handler.dispatchMessage(Handler.java:99)
06-2923:57:02.728: E/AndroidRuntime(13786): at android.os.Looper.loop(Looper.java:137)
06-2923:57:02.728: E/AndroidRuntime(13786): at android.app.ActivityThread.main(ActivityThread.java:5059)
06-2923:57:02.728: E/AndroidRuntime(13786): at java.lang.reflect.Method.invokeNative(Native Method)
06-2923:57:02.728: E/AndroidRuntime(13786): at java.lang.reflect.Method.invoke(Method.java:511)
06-2923:57:02.728: E/AndroidRuntime(13786): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:792)
06-2923:57:02.728: E/AndroidRuntime(13786): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:555)
06-2923:57:02.728: E/AndroidRuntime(13786): at dalvik.system.NativeStart.main(Native Method)
06-2923:57:02.728: E/AndroidRuntime(13786): Caused by: java.lang.ClassCastException: com.birdsall.tda.ActivitySearch cannot be cast to android.view.View$OnClickListener
06-2923:57:02.728: E/AndroidRuntime(13786): at com.birdsall.tda.ActivitySearch.onCreate(ActivitySearch.java:39)
06-2923:57:02.728: E/AndroidRuntime(13786): at android.app.Activity.performCreate(Activity.java:5058)
06-2923:57:02.728: E/AndroidRuntime(13786): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
06-2923:57:02.728: E/AndroidRuntime(13786): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2100)
06-2923:57:02.728: E/AndroidRuntime(13786): ... 11 more
06-2923:57:04.392: I/Process(13786): Sending signal. PID: 13786 SIG: 9
事前に時間を割いていただき、ありがとうございます。
これが MyActivity の要点であり、私のアクティビティの共通メニューです。
package com.birdsall.tda;
import android.app.ListActivity;
import android.content.Intent;
import android.view.Menu;
import android.view.MenuItem;
public class MyListActivity extends ListActivity {
String selectParam = "";
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()) {
case android.R.id.home:
Intent intent = new Intent(this, ActivityMain.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
return true;
case R.id.am_index:
Intent i1 = new Intent(this, ActivityIndex.class);
startActivity(i1);
return true;
/* ... More menu items */
default:
return super.onOptionsItemSelected(item);
}
}
}