Android: forward search queries to one single activity that handles search - android

I have an activity handling search (ACTIVITY_1), which works perfectly when I use the search (via SEARCH button on the phone) within/from this activity.
However, when I use search from another activity (ACTIVITY_2..x) by implementing onNewIntent and forward the query string to my Search_Activity.class (ACTIVITY_1)
#Override
protected void onNewIntent(Intent intent) {
Log.i(TAG, "onNewIntent()");
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
Log.i(TAG, "===== Intent: ACTION_SEARCH =====");
Intent myIntent = new Intent(getBaseContext(), Search_Activity.class);
myIntent.setAction(Intent.ACTION_SEARCH);
myIntent.putExtra(SearchManager.QUERY, intent.getStringExtra(SearchManager.QUERY));
startActivity(myIntent);
}
}
it always pauses ACTIVITY_2 first and then goes to onCreate() of ACTIVITY_2.
Why does it recreate my ACTIVITY_2 when it is already there and doesn't go to onNewIntent directly?
Is there another way I can forward search queries directly to ACTIVITY_1? For example via a setting in the Manifest.xml
Is it possible to generally forward all search queries automatically to ACTIVITY_1 without even implementing onNewIntent in all the other activities?
Currently I have to put an <intent-filter> in every single activity to "activate" my custom search there and forward the query then to the activity that handles search via the onNewIntent (as shown above).
<activity android:name=".Another_Activity"
android:theme="#style/MyTheme">
<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>

I'm not sure I understand the chain of events your describing, but here's how you need to configure your application in the case were ACTIVITY_1 is the search Activity you always want to launch from all your other Activities when the user presses the 'search' button.
Assuming that the search button works perfectly on Activity1, you just need to add a bit of glue meta-data to your application telling it that all your other Activities should use ACTIVITY_1 for searching, as shown in the manifest snippet below:
<application>
<meta-data
android:name="android.app.default_searchable"
android:value=".ACTIVITY_1" />
<!-- All your activities, service, etc. -->
</application>
Using this, you should be able to remove the intent-filters from all but ACTIVITY_1, and you won't need to use the onNewIntent handler in any of your other Activities.

Related

Neither onCreate() nor onNewIntent() fires when opening the same URI twice

I have an app with only two activities, MainActivity and SecondActivity. MainActivity has an intent-filter in order to handle a particular set of URLs for deep-linking:
<activity android:name=".MainActivity">
...
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http" android:host="example.com" android:pathPrefix="/link" />
</intent-filter>
When an Intent with ACTION_VIEW and an uri is received, I want to redirect to SecondActivity depending on the full URL. Therefore, in both onCreate() and onNewIntent(), I call this method:
private void handleIntent(Intent intent) {
if (Intent.ACTION_VIEW.equalsIgnoreCase(intent.getAction()) && intent.getData() != null) {
if (intent.getData().toString().contains("/link/")) {
startActivity(new Intent(Intent.ACTION_VIEW, intent.getData(), this, SecondActivity.class));
}
}
}
I then test this code by adding a few links to an e-mail (such as http://example.com/link1/one and clicking on them. The problem I noticed is the following:
When I click on a link, MainActivity.onCreate() is correctly fired, and SecondActivity is called. If I then click the same (or another) link again, then all works well. However, if I go back from SecondActivity to MainActivity, then clicking on the same link does not execute my code -- the application is brought back to the front, and nothing else. Neither onCreate() nor onNewIntent() is called.
This would seem to be the correct behavior only if Android assumed that the Activity that declares the intent-filter is the one showing the content of the URI. However, in this case it's not, and I haven't found a way to work around it.
While this is a special case, a similar situation presents itself if the Activity shows a different Fragment depending on the URI. If I later replace that Fragment while staying in the same Activity, then clicking on the URL should redeliver the Intent so the original Fragment can be shown again -- but this does not happen.
Is there a way to receive this intent again? Due to the way the app is stuctured I cannot place the intent-filters on the child activities themselves (indeed, most times they are Fragments as mentioned above) nor declare any of these as singleTop (because they are reused elsewhere for other purposes).
FWIW, the full application code is available here.

android check if an activity was started from an action or from another activity?

In my manifest file, I have an activity declaration which looks something like this:
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
This activity is obviously launched on application start. User can navigate from this activity to another activity and from that one to another etc.
In another activity, I start MainActivity by using 'startActivity' method, ie. something like:
Intent intent = new Intent(AnotherActivity.this, MainActivity.class);
startActivity(intent);
In my MainActivity (in onCreate() method maybe), can I determine whether an activity was started from a action of from another activity? Is there something like "launcher listener"? I would like to avoid putting any extra content in the intent.
Can I simply put String s = getIntent().getAction(); in onCreate method and check whether it is has a value of MAIN?
Well the stock android launcher does send Intent.ACTION_MAIN as as the action. However, you can't be sure that some other launcher will have the same behaviour. Your best bet will be to pass some extra data with the Intent.

How to end old Activity when Search starts new Activity

I have an application that presents a sort of catalog of items in a ListView. The list is rather long, so I've implemented the Search capability like this:
<activity android:name=".ItemsOverview"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<!-- enable the search dialog to send searches to ItemsSearch -->
<meta-data android:name="android.app.default_searchable"
android:value=".ItemsSearch" />
</activity>
...
...
<activity android:name=".ItemsSearch">
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
</intent-filter>
<meta-data android:name="android.app.searchable"
android:resource="#xml/searchable" />
</activity>
ItemsSearch then presents the same ListView, but containing only items that match the Search criteria.
There are two fundamental problems with this:
ItemsSearch is an almost duplicate of ItemsOverview (but with some enhancements for the search capability);
ItemsSearch overlays ItemsOverview such that if three or four searches are done, it takes four or five presses of the Back button to get out. Not quite the desired effect. :)
I would like to, in some fashion, end the original Activity when the second Activity starts and, ideally, combine the two Classes (Overview and Search) into one. Is there a way for my Activity to detect that it's already running in another process, and to kill that other process at inception?
Once I understand this, I can probably figure out how to combine the two. What do others do when they need to utilize a filtered list?
If I understand, you would you like to clear the Activity Back Stack. Use the activity flags when you call your search Activity.
Intent intent = new Intent(this, Search.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
This is the developer page about the activity back stack.
To end old Activity when Search starts new Activity give finish() in odler activity and call new activity.
Intent intent = new (Intent(MainActivity.this,GPSActivity.class);
startActivityForResult(intent, ACTIVITY_GPS);
finish();
In this we can start new Activity GPSActivity and finishes MainActivity.

How can I finish the current activity when performing a search in Android?

I have search functionality in my app. When the search bar is invoked from a "show activity" and the user performs a search, I want to finish the show activity and take the user to the search activity. Is there a way to know if SearchManager.onDismissListener is invoked because of a search being performed?
What I want to avoid is to have several screens of search results > show > search results > show etc, and rather "go back" to search results whenever a search is performed, and thus only have one search activity and one show activity in the stack at any one time.
If I understand your question correctly, you want to prevent the search activity from being created multiple times.
The impact of the search dialog on your activity lifecycle in the Android docs has the explanation for what you want.
Essentially, you want to set android:launchMode to "singleTop" when defining your searchable activity in the manifest. From the example at the link, you would then have something like this:
<activity android:name=".SearchableActivity"
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"/>
</activity>
But be careful to follow their advice for handling intents with onCreate and onNewIntent, which rather than duplicate here I'll just refer you to that link.
You can do the same for what your show activity as well with the android:launchMode="singleTop"

How to have onSearchRequested not open a web browser

I have a button in my app. When it is pressed I call the onSearchRequested() method. When this is called the stock search box comes up so the user can type some junk in there. When they press "Go" I need the results returned back to my application but instead the stock browser is opened and a google search is performed. How can I tell it to return the results to my application instead.
I've tried these items in my manifest.xml file:
<meta-data android:name="android.app.default_searchable"
android:value=".MainActivity" />
<activity android:name=".MainActivity"
android:launchMode="singleTop"
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
</intent-filter>
I've also tried to capture the result in my onCreate with this:
Intent intent = getIntent();
if (Intent.ACTION_SEARCH.equals(intent.getAction()))
This is covered fairly well in the documentation. In particular, you are missing the searchable <meta-data> element (and, presumably, the corresponding XML file). Here is a sample project showing the use of search within an application.

Categories

Resources