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);
}
Related
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);
}
[CLOSED]
I have a two activity called A and B.
ActivityA (Launcher) shows list data (RecyclerView) and data is downloaded from the WebService.
ActivityB shows list item detail when i press list item.
The problem is:
When i press back button from ActivityB, ActivityA's onCreate() method working and re-downloading already downloaded datas like relaunching app. I don't want to re-download or re-call onCreate() method.
I tested two device has pre Marshmallow OS:
Samsung Galaxy S5 (OS version 4.4.4)
Sony Xperia (OS version 4.1.2)
and the result is:
When i press back button from ActivityB, ActivityA is not re-downloading. ActivityA already shows lastly positioned list. I want this in Marshmallow.
My Marshmallow device is Nexus 5 (OS version 6.0.1)
How can i solve this problem?
[SOME CODE BELOW]
// This is ActivityA
public class MainView extends AppCompatActivity {
...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_view);
...
if (NetworkChecker.isNetAvailable(context)) {
mDataSet = update(); // this method calling WebService
} else {
mDataSet = Database.getDatas(); // this method reading datas from sqlite.
}
createListView(mDataSet);
...
}
private void createListView(List<NamecardEntity> mDataSet) {
mRecyclerView = (RecyclerView) findViewById(R.id.itemsRecyclerView);
mRecyclerView.setHasFixedSize(true);
RecyclerView.ItemDecoration itemDecoration =
new DividerItemDecorator(getContext(), LinearLayoutManager.VERTICAL);
mRecyclerView.addItemDecoration(itemDecoration);
LinearLayoutManager mLayoutManager = new LinearLayoutManager(getContext());
mRecyclerView.setLayoutManager(mLayoutManager);
mAdapter = new ListAdapter(getActivity(), getActivity().getApplicationContext(), mDataSet);
mRecyclerView.setAdapter(mAdapter);
mRecyclerView.addOnScrollListener(onScrollListener);
}
...
}
public class ListAdapter extends RecyclerSwipeAdapter<ListAdapter.SimpleViewHolder> {
...
#Override
public void onBindViewHolder(final SimpleViewHolder viewHolder, final int position) {
Entity item = mDataset.get(position);
...
viewHolder.front.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
activity.startActivity(new Intent(mContext, DetailView.class));
}
});
...
}
}
// This is ActivityB
public class DetailView extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.detail_view);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
if (getSupportActionBar() != null) {
getSupportActionBar().setTitle("");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
...
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_activity_filter, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
finish();
return true;
case R.id.action_filter:
// TODO filter
return true;
}
return true;
}
}
// In Manifest.xml
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".MainView"
android:label="#string/app_name"
android:screenOrientation="portrait"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".DetailView"
android:screenOrientation="portrait"
android:theme="#style/AppTheme.NoActionBar" />
</application>
[EDITED] I FOUND REASEN
I put some Log into ActivityA Lifecycle, and the result is:
When i run the application on the Xperia. (pre Marshmallow test result):
ActivityA state log is:
onCreate
onStart
onResume
then select list item and starting ActivityB
ActivityA state log is:
onPause
onStop
then i press back button from ActivityB and navigate back to A
ActivityA state log is:
onRestart
onStart
onResume
When i run the application on the Nexus 5. (Marshmallow test result):
ActivityA state log is:
onCreate
onStart
onResume
then select list item and starting ActivityB
ActivityA state log is:
onPause
onStop
onDestroy <- this is the reason, why this method called in Marshmallow
then i press back button from ActivityB and navigate back to A
ActivityA state log is:
onCreate <- onCreate() called, cause onDestory() called already, this is the problem
onStart
onResume
ACTIVITY LIFECYCLE IS WORKS DIFFERENT IN MARSHMALLOW, WHY? THAT IS THE WHY I GETTING PROBLEM. PLS HELP
Android Marshmallow is working fine. You have this problem because you didn't correctly adhere to the activity lifecycle.
Note that it is up to Android to destroy the Activity or not. You have to take account on that. Turns out in your case on previous Android versions your Activity was destroyed, so when you navigated back it passed through onCreate(). Now it does not destroy it, so it doesn't go through onCreate().
The correct way to refresh data is to always do it on the onResume() method to make sure it will be called no matter if Android destroys the Activity or not.
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.
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'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.