I have an Activity that holds a list. Via the Android onSearchRequested() I implemented a search.
The results are shown as a list with the same adapter in another Activity. Working fine so far.
Also, I want to be able to search from that second Activity showing the new results in the same list.
My AndroidManifest.xml for the two activities:
<activity android:name=".ListActivity" android:label="List">
<meta-data android:name="android.app.default_searchable" android:value=".SearchActivity" />
</activity>
<activity android:name=".SearchActivity" android:label="Results">
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
</intent-filter>
<meta-data android:name="android.app.searchable" android:resource="#xml/search" android:value=".SearchActivity" />
</activity>
The SearchActivity's onResume():
#Override
protected void onResume() {
super.onResume();
Intent queryIntent = getIntent();
String value = queryIntent.getStringExtra(SearchManager.QUERY);
setView(value);
}
The setView() method does a foreach loop through all objects adding them to a result-array which is used for a new Adapter that the list shows.
ca = new CustomAdapter(this, R.layout.customadapter, resultArray);
list.setAdapter(pa);
list.invalidate();
When trying to search from the second Activity the search bar appears, I can enter my search value, send it - but the list doesn't change (and even the keyboard stays).
What's missing?
Edit: Tried to make it easier to understand.
Found that question which describes kind of the same problem.
Instead of overriding onResume() I have to override onNewIntent()
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
String value = intent.getStringExtra(SearchManager.QUERY);
setView(value);
}
Related
This question already has an answer here:
Android: dynamically creating controls and orientation change
(1 answer)
Closed 8 years ago.
I have 2 edittext these are dynamically created. when entered some text and change orientation edittext data losing.
because onSaveInstanceState calling 2 times. while debugging first time I am getting values. but 2nd time the values are null.
Use Shared-preferences to save the data at the first time and get the data after changing the orientation:
I hope this will help you. Use Like this:
public static void setSharedPrefStringData(Context context, String key,
String value) {
SharedPreferences appInstallInfoSharedPref = context
.getSharedPreferences(Constants.SHARED_PREF_NAME,
context.MODE_MULTI_PROCESS);
Editor appInstallInfoEditor = appInstallInfoSharedPref.edit();
appInstallInfoEditor.putString(key, value);
appInstallInfoEditor.commit();
}
public static String getSharedPrefStringData(Context context, String key) {
SharedPreferences userAcountPreference = context.getSharedPreferences(
Constants.SHARED_PREF_NAME, Context.MODE_MULTI_PROCESS);
return userAcountPreference.getString(key, "");
}
Let me know if any concern.
you can override onConfigurationChanged please visit http://developer.android.com/reference/android/app/Activity.html
you can do this as follows
public void onConfigurationChanged(Configuration currentConfig) {
super.onConfigurationChanged(currentConfig);
//yours implementation with respect to edittext
}
Please try to work with onConfigurationChanged method and override in the given way !!
suppose you have a main activity as MainActivity
and registered to manifest as follows
<activity android:name=".MainActivity " >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
</activity>
As a first step you can add the attribute android:configChanges inside the activity tag.
<activity android:name=".MainActivity "
android:configChanges="orientation|keyboardHidden" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
</activity>
Next step is about necessary to implement the logic for handling this layout change manually at yours activity code. For this you need to override the method
onConfigurationChanged() inside MainActivity .
public void onConfigurationChanged(Configuration currentConfig) {
super.onConfigurationChanged(currentConfig);
//yours implementation with respect to edittext
}
I was trying to make application, it was working but now when I run it in emulator it's not even giving me the welcome screen. Code:
public class TestArabActivity extends Activity {
/** Called when the activity is first created. */
TextView tvTop,tvBottom;
TableLayout tlStart;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.welcome_screen);
//init variables
initVars();
}
private void initVars(){
tvTop = (TextView) findViewById(R.id.tv_start_TopTittle);
tvBottom = (TextView) findViewById(R.id.tv_strat_BottomTittle);
tlStart = (TableLayout) findViewById(R.id.tl_start);
}
}
I used debugger and saw these:
the value of savedInstanceState = null
values of tvTop, tvBottom and tlStart are null also
Why those values are null? I know this is the problem.
Anyone know how to solve it? Thanks.
Use DDMS to debug your application,if it throws any exception, you can see from the stack trace where the problem comes from. if it does not throw any exception. then probably you forgot to declear intent-filter in the menifest:
<activity android:name="TestArabActivity" android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
I've read a few articles here (and other places) that describe how to dynamically choose which activity to show when launching an app. Below is my code:
AndroidManifest.xml
<activity android:name=".StartupActivity"
android:theme="#android:style/Theme.NoDisplay">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
StartupActivity.java
public class StartupActivity extends Activity
{
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
Intent intent;
if (RandomClass.getSomeStaticBoolean())
{
intent = new Intent(this, ActivityOften.class);
}
else
{
intent = new Intent(this, ActivityRare.class);
}
startActivity(intent);
finish();
}
}
Both ActivityOften and ActivityRare are declared in the manifest (without the launcher category of course) and extend ListActivity and Activity respectively. 99% of the time the 1st activity to get shown is ActivityOften based on RandomClass.getSomeStaticBoolean().
So launching my app from the icon for the 1st time I break inside the StartupActivity.onCreate. The choice is properly made. But then any subsequent attempts to launch the app (from a shortcut or the apps menu) show the ActivityOften again. No further breaks occur inside the StartupActivity class. Despite the fact that I know that RandomClass.getSomeStaticBoolean() has changed value and that ActivityRare should appear, the 1st activity keeps popping up.
Any ideas?
Thanks, Merci, Gracias, Danke, Grazie!
Sean
It is happening because your application activity is loaded from the history stack.
Set android:noHistory=true in the manifest for both ActivityOften and ActivityRare. That should solve your problem.
Just as a suggestion, you could just have one activity instead of three by choosing the content View dynamically. i.e.
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
if (RandomClass.getSomeStaticBoolean())
{
setContentView(R.layout.Often);
// Set up often ....
}
else
{
setContentView(R.layout.Rare);
// Set up rare ....
}
}
This would mean that you would have to write setup code both views in on activity, which can get a bit messy.
in my app I am trying to add new screen. In my activity I've:
public void addItem(View v) {
Intent i = new Intent(SQLiteListActivity.this, add_screen.class);
startActivity(i);
}
In add_screen.java:
public class add_screen extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView tv = new TextView(this);
tv.setText("Hello, Android");
setContentView(tv);
}
}
In file add_screen.xml I've layout this screen. In file AndroidManifest.xml I added this next activity, especially:
<activity class=".Add_screen" android:name="ADD_ITEM" android:label="Add item">
</activity>
I am still getting an error message about "Application has been stopped." I am newbie in Android development, I tried to do this by some tutorial, I've everything by it, but I don't know why, I'm still getting the error message above...
Can you help me, please, with this problem? I've no idea, what could be wrong.
Try replacing the activity tag in your manifest with this instead:
<activity
android:name=".add_screen"
android:label="Add item"
>
<intent-filter>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
You shouldn't need the class attribute, I don't even know if that's recognized.
Edit: Try the above instead?
I followed the steps described on http://developer.android.com/guide/topics/search/search-dialog.html to implement a search feature in my notepad application.
My problem is, that when I finish the search a new activity opens capturing my search query. But what I really want, is the query returned to the current activity instead of starting a new one.
Is this possible?
UPDATE:
AndroidManifest.xml
<activity android:name="MyNotepad"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<action android:name="android.intent.action.SEARCH"></action>
</intent-filter>
<meta-data android:resource="#xml/searchable" android:name="android.app.searchable"></meta-data>
</activity><activity android:name="Preferences" android:label="Preferences" >
</activity>
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">
</searchable>
JAVA-code
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_pad);
Intent intent = getIntent();
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
String query = intent.getStringExtra(SearchManager.QUERY);
Toast.makeText(getApplicationContext(), query, Toast.LENGTH_LONG).show();
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch(item.getItemId())
{
case R.id.menuItemSearch:
startSearch("", false, null, false);
break;
}
return true;
}
Even if I use the search-button on the phone it doesn't work. I therefor believe that the problem is in the AndroidManifest.xml
In your Application Manifest you need to define the current activity as a searchable activity.
<activity android:name="BrowseItems" android:label="#string/browseitems"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
</intent-filter>
<meta-data android:name="android.app.searchable"
android:resource="#xml/itemsearchable" />
</activity>
You then use the following code, which is from http://developer.android.com/guide/topics/search/search-dialog.html#LifeCycle
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.search);
handleIntent(getIntent());
}
#Override
protected void onNewIntent(Intent intent) {
setIntent(intent);
handleIntent(intent);
}
private void handleIntent(Intent intent) {
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
String query = intent.getStringExtra(SearchManager.QUERY);
// Do work using string
}
}
You can then use the string to reload your activity, if its a list activity you can call your code that you use to load data and use the string in that.
Add to AndroidManifest.xml in your Searchable Activity:
android:launchMode="singleTop"
so, your AndroidManifest.xml looks like:
<activity android:name="MyNotepad"
android:label="#string/app_name"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<action android:name="android.intent.action.SEARCH"></action>
</intent-filter>
<meta-data android:resource="#xml/searchable" android:name="android.app.searchable"></meta-data>
</activity><activity android:name="Preferences" android:label="Preferences" >
The reason:
From this post:
The activity launch mode has four valid values:
"standard"
"singleTop"
"singleTask"
"singleInstance"
The 'standard' is the default value. The four values fall into two groups:
'standard' and 'singleTop' can instantiate multiple activity instances and the instance will stay in the same task.
For 'singleTask' or 'singleInstance', the activity class uses the singleton pattern, and that instance will be the root activity of a new task. Let's examine each value:
"standard":
Multiple instances of the activity class can be instantiated and multiple instances can be added to the same task or different tasks. This is the common mode for most of the activities.
"singleTop":
The difference from 'standard' is, if an instance of activity already exists at the top of the current task and system routes intent to this activity, no new instance will be created because it will fire off an onNewIntent() method instead of creating a new object.
I simply use this:-
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String s) {
//on submit
return false;
}
#Override
public boolean onQueryTextChange(String s) {
//get all text changes
return false;
}
});
This is best used when you have to search across a listview and have to filter out items. I never go by implementing the search function using the manifest file. The 2 methods do all the job.
I was also facing the same problem, then I wrote this code and it solved my problem.
Implement this in your Activity
**implements SearchView.OnQueryTextListener, SearchView.OnCloseListener**
Add this function in the class:
private void setupSearchView()
{
searchView.setIconifiedByDefault(true);
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
if (searchManager != null)
{
List<SearchableInfo> searchables = searchManager.getSearchablesInGlobalSearch();
// Try to use the "applications" global search provider
SearchableInfo info = searchManager.getSearchableInfo(getComponentName());
for (SearchableInfo inf : searchables)
{
if (inf.getSuggestAuthority() != null && inf.getSuggestAuthority().startsWith("applications"))
{
info = inf;
}
}
searchView.setSearchableInfo(info);
}
searchView.setOnQueryTextListener(this);
searchView.setOnCloseListener(this);
}
Call the function in the onCreateOptionsMenu(Menu menu)
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
//restoreActionBar();
// Associate searchable configuration with the SearchView
//SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
searchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
//searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
setupSearchView();
return super.onCreateOptionsMenu(menu);
}
This will totally solve your problem..
Happy Coding!!
Briefly:
Add android:launchMode="singleTop" to the searchable activity definition in the AndroidManifest.xml
Implement onNewIntent in the searchable activity and handle the search there.
I followed Lachlan's clue of "You can then use the string to reload your activity", and finally worked this out. So please read Lachlan's post first, and then take the following 3 steps "to reload your activity":
Save query string in ApplicationContext.
Finish the new opened search Activity.
Override OnResume, get query string you just saved, and then refresh the list.
Codes in List Activity:
private void handleIntent(Intent intent) {
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
String searchText = intent.getStringExtra(SearchManager.QUERY);
((MyApp)this.getApplicationContext()).setSearchText(searchText);
this.finish();
}
}
protected void onResume() {
super.onResume();
String searchText = ((MyApp)this.getApplicationContext()).getSearchText();
//refresh your list here...
}
MyApp class: (This original idea is from here: Android: How to declare global variables?)
public class MyApp extends Application {
private String mSearchText;
public String getSearchText() {
return mSearchText;
}
public void setSearchText(String searchText) {
this.mSearchText = searchText;
}
}
Don't forget to add property android:name=".MyApp" to your application in the Manifest file. Good luck!
in the manifest file, add:
android:launchMode="singleTop"
To your search activity. Then, let your search activity implement SearchView.OnSuggestionListener
finally:
mSearchView.setOnSuggestListener(this)
this way you can handle the suggestion click event with out creating a new instance of your search activity.
It doesn't bring up a new activity if the SearchView.OnSuggestionListener on the searchView is set, and the overridden methods return true (overriding the default behavior). You can do that in the onCreateOptionsMenu() implementation, like this:
searchView.setOnSuggestionListener(new SearchView.OnSuggestionListener() {
#Override
public boolean onSuggestionSelect(int position) {
return true;
}
#Override
public boolean onSuggestionClick(int position) {
CursorAdapter selectedView = searchView.getSuggestionsAdapter();
Cursor cursor = (Cursor) selectedView.getItem(position);
int index = cursor.getColumnIndexOrThrow(SearchManager.SUGGEST_COLUMN_TEXT_1);
searchView.setQuery(cursor.getString(index), true);
return true;
}
});
No need to force the activity to singleTop or other hacks.
Just add
<application>
<meta-data
android:name="android.app.default_searchable"
android:value="#Activity_Name" />
<!-- All your activities, service, etc. -->
</application>
in your android_manifest.xml file where #Activity_Name is the name of the activity that handles the search.