【发布时间】:2023-04-04 11:16:01
【问题描述】:
我在使用基于 this tutorial 通过 Volley 解析的 JSON 数据过滤列表时遇到问题,当该列表通过 Google 应用程序中的 Google 系统语音操作中的 Search in App 意图进行过滤时。
遇到的具体问题如下:
应用程序最初根本没有运行(如果应用程序正在运行或在后台,搜索将完美运行)。
通过 adb 触发 Intent:
cd C:...\android-sdk\platform-toolsadb shell am start -a "com.google.android.gms.actions.SEARCH_ACTION" --es query "[query keyword]" -n "com.testapp/.MainActivity"
正确的应用程序打开,但列表为空,即没有过滤结果。
然后应用程序崩溃。
下面是堆栈跟踪:
02-15 17:54:03.331: D/AndroidRuntime(31982): Shutting down VM
02-15 17:54:03.341: E/AndroidRuntime(31982): FATAL EXCEPTION: main
02-15 17:54:03.341: E/AndroidRuntime(31982): Process: com.test.app, PID: 31982
02-15 17:54:03.341: E/AndroidRuntime(31982): java.lang.IndexOutOfBoundsException: Invalid index 0, size is 0
02-15 17:54:03.341: E/AndroidRuntime(31982): at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
02-15 17:54:03.341: E/AndroidRuntime(31982): at java.util.ArrayList.get(ArrayList.java:308)
02-15 17:54:03.341: E/AndroidRuntime(31982): at com.test.app.adapter.CustomListAdapter.getView(CustomListAdapter.java:92)
02-15 17:54:03.341: E/AndroidRuntime(31982): at android.database.DataSetObservable.notifyChanged(DataSetObservable.java:37)
02-15 17:54:03.341: E/AndroidRuntime(31982): at android.widget.BaseAdapter.notifyDataSetChanged(BaseAdapter.java:50)
02-15 17:54:03.341: E/AndroidRuntime(31982): at com.test.app$1.onResponse(MainActivity.java:152)
02-15 17:54:03.341: E/AndroidRuntime(31982): at com.test.app$1.onResponse(MainActivity.java:1)
02-15 17:54:03.341: E/AndroidRuntime(31982): at com.android.volley.toolbox.JsonRequest.deliverResponse(JsonRequest.java:65)
02-15 17:54:03.341: E/AndroidRuntime(31982): at com.android.volley.ExecutorDelivery$ResponseDeliveryRunnable.run(ExecutorDelivery.java:99)
02-15 17:54:03.341: E/AndroidRuntime(31982): at android.os.Handler.handleCallback(Handler.java:739)
02-15 17:54:03.341: E/AndroidRuntime(31982): at android.os.Handler.dispatchMessage(Handler.java:95)
02-15 17:54:03.341: E/AndroidRuntime(31982): at android.os.Looper.loop(Looper.java:145)
02-15 17:54:03.341: E/AndroidRuntime(31982): at android.app.ActivityThread.main(ActivityThread.java:6843)
02-15 17:54:03.341: E/AndroidRuntime(31982): at java.lang.reflect.Method.invoke(Native Method)
02-15 17:54:03.341: E/AndroidRuntime(31982): at java.lang.reflect.Method.invoke(Method.java:372)
02-15 17:54:03.341: E/AndroidRuntime(31982): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1404)
02-15 17:54:03.341: E/AndroidRuntime(31982): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1199)
我的应用包含一个 MainActivity,它是显示列表的可搜索 Activity、一个模型类、一个适配器类和一个用于列表项的控制器类(类似于现有的 Android ListView 教程)。
以下是代码(部分代码省略):
主活动
//[…]
public class MainActivity extends AppCompatActivity {
//[…]
private List<Item> itemList = new ArrayList<Item>();
public static ListView listView;
private CustomListAdapter adapter;
private static final String GMS_SEARCH_ACTION = "com.google.android.gms.actions.SEARCH_ACTION";
private String qq;
@Override
protected void onCreate(Bundle savedInstanceState) {
//[…]
onNewIntent(getIntent());
}
public void onNewIntent(Intent intent) {
super.onNewIntent(intent);
String action = intent.getAction();
if (action!= null && (action.equals(Intent.ACTION_SEARCH)||action.equals(GMS_SEARCH_ACTION))) {
qq = intent.getStringExtra(SearchManager.QUERY);
doSearch(qq);
}
}
/* FIXME - Current problem: From adb command, ListView can only be filtered successfully only if app is still running in background (i.e. onPause()). ListView filtering works ok if searching within the app. If app is not running, sending the search command causes the app to open but nothing is filtered, and then crashes shortly after.*/
private void doSearch(String qq) {
CharSequence query = qq.toUpperCase(Locale.getDefault());
MainActivity.this.adapter.getFilter().filter(query);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
// […]
MenuItem searchItem = menu.findItem(R.id.menu_search);
SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
SearchableInfo searchableInfo = searchManager.getSearchableInfo(getComponentName());
searchView.setSearchableInfo(searchableInfo);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String qq) {
doSearch(qq);
return false;
}
@Override
public boolean onQueryTextChange(String qq) {
doSearch(qq);
return false;
}
});
return super.onCreateOptionsMenu(menu);
}
}
适配器类
// […]
public class CustomListAdapter extends BaseAdapter {
private Activity activity;
private LayoutInflater inflater;
private List<Item> items, default_items;
private Filter myFilter;
ImageLoader imageLoader = AppController.getInstance().getImageLoader();
public CustomListAdapter(Activity activity, List<Item> items) {
this.activity = activity;
this.items = items;
this.default_items = items;
}
//[…]
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//…
}
public Filter getFilter() {
if (myFilter == null) { myFilter = new MYFilter();}
return myFilter;
}
private class MYFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence query) {
FilterResults results = new FilterResults();
// If no filter implemented, return the whole list
if (query == null || query.length() == 0) {
results.values = default_ items;
results.count = default_ items.size();
}
else {
List<Item> nitems = new ArrayList<Item>();
items = default_nitems;
for (Item t : items) {
// Filter logic implemented here, items are added to nitems if it meets conditions
}
results.values = nitems;
results.count = nitems.size();
}
return results;
}
@Override
protected void publishResults(CharSequence query, FilterResults results) {
if (results.count == 0){
items = (List<Item>) results.values;
MainActivity.emptyView.setVisibility(View.VISIBLE);
MainActivity.listView.setVisibility(View.GONE);
}
else {
items = (List< Item >) results.values;
MainActivity.listView.setVisibility(View.VISIBLE);
MainActivity.emptyView.setVisibility(View.GONE);
notifyDataSetChanged();
}
}
}
}
清单
<?xml version="1.0" encoding="utf-8"?>
<manifest ... >
<application
android:name=".app.AppController"
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" android:allowTaskReparenting="true">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:screenOrientation="portrait"
android:exported="true"
android:launchMode="singleTop" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
<meta-data
android:name="android.app.searchable"
android:resource="@xml/searchable" />
<intent-filter>
<action android:name="com.google.android.gms.actions.SEARCH_ACTION" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
<meta-data
android:name="android.app.default_searchable"
android:value=".MainActivity" />
</activity>
<!-- ... -->
</application>
</manifest>
感谢您提供解决此问题的任何帮助。
【问题讨论】:
-
项目结构基于this tutorial。
-
java.lang.IndexOutOfBoundsException: Invalid index 0, size is 0在CustomListAdapter.java第 92 行
标签: java android listview android-intent google-voice-actions