I have 3 activities SignIn (LAUNCHER), Main, StockTake (parent activity: Main).
Android Manifest below:
<application
......
<activity
android:name=".activities.MainActivity"
android:label="#string/title_activity_main">
</activity>
<activity android:name=".activities.SignInActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".activities.StockTakeActivity"
android:parentActivityName=".activities.MainActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".activities.MainActivity" />
</activity>
</application>
From Main Activity the user input data and move to the stocktake activity:
Intent intent = new Intent(this, StockTakeActivity.class);
startActivity(intent);
In the StockTake activity 'back' button is visible on top left corner in actionbar. When the back button '<-' is press the application is going to the Main activity, but the main activity screen is cleared from user input.
In StockTake activity:
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
NavUtils.navigateUpFromSameTask(this);
return true;
}
return super.onOptionsItemSelected(item);
}
I have the onSave... and onRestore... implemented. The onRestore is not been called.
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putString(PART_NUMBER_KEY, String.valueOf(txtPartNumber.getText()));
savedInstanceState.putString(PART_DESCRIPTION_KEY, String.valueOf(txtPartDescription.getText()));
....
}
#Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
String partNumber = savedInstanceState.getString(PART_NUMBER_KEY);
String partDescription = savedInstanceState.getString(PART_DESCRIPTION_KEY);
.....
}
What do i need to do to retain user input in Main activity when the user press the '<-' back button? I am on android 6 API 23.
You can try shared preferences to store the data and when you come back you retrieve them.
Initialization
SharedPreferences sharedpreferences;
sharedpreferences = getSharedPreferences("pref", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedpreferences.edit();
Add content to the code
editor.putString("name,"xyz");
Use it when you need it
sharedpreferences = this.getSharedPreferences("pref", Context.MODE_PRIVATE);
String lanSettings = sharedpreferences.getString("name", null);
remove android:parentActivityName=".activities.MainActivity" from the manifest file and add this in StockTakeActivity
#Override
public boolean onSupportNavigateUp() {
finish();
return true;
}
I end up removing android:parentActivityName=".activities.MainActivity" from the manifest file and made the change below to onOptionsItemSelected(...)
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
//NavUtils.navigateUpFromSameTask(this);
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
Related
I need to close an activity when a button is clicked. Unfortunately, when button is clicked, the activity does disappear but is still in the background. User can still select it and it comes back to front. What I need is the activity completely gone/destroyed.
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button)findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
finish();
}
});
}
#Override
protected void onDestroy() {
super.onDestroy();
}
}
I searched on SO on related questions, however, none of them help with closing the activity completely. I already tried adding return, adding another broadcast listener and passing command to call finish outside onCreate. So at this point, the question is - is this really possible or is this how Android works, you can call finish() but it is still in the background and user can re-launch it.
Here is xml file.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.app1.test.myapplication">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
EDIT: Adding android:excludeFromRecents="true" does not solve the issue. Here are steps to recreate this, if anyone thinks it is a duplicate or already solved, please try and post comment/answer, I will accept it.
Open Android Studio
Create empty activity project.
Add a button.
Add code in MainActivity's onCreate for button click listener.
Inside click listener, call finish.
Run the app and click button and see if the activity is still in background or not.
Just give it a try.
In you manifest.
<activity
android:excludeFromRecents="true"
android:name=".Activities.SplashActivity"
android:theme="#style/AppThemeSubActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Now in your java code.
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.item_search:
// Intent intent = new Intent(MainActivity.this, SearchActivity.class);
// startActivity(intent);
finish();
System.exit(0);}
}
put the extra line System.exit(0); after calling finish it works for me.
You need to put this in your XML manifest:android:excludeFromRecents="true"
in your Activity TAG.
<activity
...
android:excludeFromRecents="true">
</activity>
You could try this
android:excludeFromRecents="true", Use it in your manifest.
plz try this to go back
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button)findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
onBackPressed();
}
});
}
}
and this code to kill app process
moveTaskToBack(true);
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(1);
I have an application with three activities.
MainActivity which looks like that:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Button b = new Button(this);
b.setText("click me to go to child activity");
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(MainActivity.this, ChildActivity.class));
}
});
setContentView(b);
}
}
ChildActivity which looks like that:
public class ChildActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new TextView(this) {{
setText("I'm the child activity");
}});
}
}
And OtherActivity which looks like that:
public class OtherActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new TextView(this) {{
setText("I'm other activity");
}});
}
}
In the manifest I have such declaration:
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity android:name="pl.psobolewski.test.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name="pl.psobolewski.test.ChildActivity" />
<activity android:name="pl.psobolewski.test.OtherActivity" />
</application>
Now when I start the application, it starts with MainActivity, from there I can go to ChildActivity, but there is no way to go to OtherActivity.
Then in the manifest I change this line:
<activity android:name="pl.psobolewski.test.ChildActivity" />
to:
<activity android:name="pl.psobolewski.test.ChildActivity" android:parentActivityName="pl.psobolewski.test.OtherActivity" />
Now I start again this application on my phone, which has Android API 16. It starts with MainActivity, there I can press the button and move to ChildActivity. Now the ChildActivity looks a little bit different than before: the logo on ActionBar has a little arrow-like icon (documentation calls it "a left-facing caret") which means it can be used to move up. But when I press it I don't go to OtherActivity - even though it is declared as the parent of ChildActivity - but to the MainActivity.
I find it contrary with the Android documentation which says:
http://developer.android.com/guide/topics/manifest/activity-element.html
"android:parentActivityName
The system reads this attribute to determine which activity should be started when the use presses the Up button in the action bar. The system can also use this information to synthesize a back stack of activities with TaskStackBuilder."
I also thought that adding android:parentActivityName attribute without calling setDisplayHomeAsUpEnabled would not turn the application logo into the up button - the documentation at http://developer.android.com/training/implementing-navigation/ancestral.html suggests so.
My question is: why the "up" button moves me to the MainActivity and not to the OtherActivity?
The Action Bar up navigation handler has been implemented in such a way that if the parent of current activity has no parent, then an Intent is created with ACTION_MAIN & CATEGORY_LAUNCHER to start the activity. This results in MainActivity being launched.
Have a look at definition of getParentActivityIntent() in Activity.java
To overcome this, in your ChildActivity.java override below 2 methods of Activity.
#Override
public boolean shouldUpRecreateTask(Intent intent) {
return true; // This creates a new task stack
}
#Override
public Intent getParentActivityIntent() {
Intent intent = new Intent(this, OtherActivity.class);
return intent;
}
If you don't want to override getParentActivityIntent, then you need to define a parent activity for OtherActivity in AndroidManifest.xml file, to overcome the earlier mentioned reason.
If you don't override shouldUpRecreateTask, since OtherActivity does not appear in history stack, it will remove all activities until the root activity of the task is reached, resulting in 'in-app home' behavior.
I am setting Activity Theme to Theme.NoDisplay but When it open but on press back button Activity not closing/destroying. It should close/destroy on back press.
Guys help me why this is so and any solution to resolve this.
public class MainActivity extends Activity {
// Tag of the Activity
private static String TAG = "MainActivity";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DatabaseManager.init(this);
NFCIItem mNFCItem = new NFCIItem();
mNFCItem.setSerialNumber(1);
DatabaseManager.getInstance().addWishList(mNFCItem);
final List<NFCIItem> wishLists = DatabaseManager.getInstance().getAllNFCSerialNumber();
Log.v(TAG, wishLists.toString());
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
AndroidManifest.xml
<activity
android:name="com.example.appdemo.MainActivity"
android:label="#string/app_name"
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>
I imagine it is closing but you see no evidence of this because it is 'NoDisplay'. An Activity using this theme has no visible UI (hence it is not logical for such an Activity to process UI events) and should not be kept alive. See this question for example:
how to completely get rid of an activity's GUI (avoid a black screen)
If you do want this Activity's layout to be visible and to handle events, you should use a different theme. If on the otherhand this is an invisible Activity that just does some background processing, call finish() in onCreate to close it when that processing is done.
You can override the back button event to manually close the activity
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
YourActivity.this.finish();
return true;
}
}
You can override the back button to launch the main activity and instantly close it without animation. This will appear as a single action to the user.
#Override
public void onBackPressed() {
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
finish();
overridePendingTransition(R.anim.slide_in_right,
R.anim.slide_out_right);
}
So My application Consists of first activity which shows some text, and on action bar there is a File menu, in which I put My location option.
I call another activity in mainActivity with onOptionItemSelected as follows:
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_photo:
openPhoto();
return true;
case R.id.action_video:
openVideo();
return true;
case R.id.action_map:
Intent intent = new Intent(this, GPSTracker.class);
startActivity(intent);
return true;
default:
return super.onOptionsItemSelected(item);
}
in manifest i declare the second activity as follows:
<activity
android:name="com.example.locateme.GPSTracker"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
and in GPSTracker.java i write this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_gpstracker);
}
also there is my code for finding the location.
I am running the app, bu when i press My Location option the app crashes.
Here are the logcat errors after removing intent for GPS activity
The full code of the app is here, in case there may be something i missed.
Do i call the second activity in the wrong way?
java.lang.InstantiationException: can't instantiate class com.example.locateme.GPSTracker; no empty constructor
is quite obvious error.
Somewhere in your GPSTracker class you have a definition like
public GPSTracker(SomeClass referenceName) {
//...
}
This block of code should be removed or replaced with constructor without params. The first option if prefered: use onCreate as your constructor.
First, remove the intent-filter for Your GPS Activity in Your Manifest.xml, here You had set both activities (Main and GPS) as a launcher. Set only one Activity as LAUNCHER and MAIN. And then it will be good to see LogCat Output to know why it crashs
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.