Why does Android main activity go unresponsive after I change preferences? - android

After i start my preferences activity
Intent settingsActivity = new Intent(getBaseContext(), PreferenceWithHeaders.class);
startActivity(settingsActivity);
I change settings or i dont, but when i press the back button, the preferences screen closes and main activity is gray and unresponsive. Another back-button press makes the activity responsive again.
Preference activity class starts like this.
public class PreferenceWithHeaders extends PreferenceActivity implements SharedPreferences{
public static final String PREFERENCE_FILENAME = "preferences";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
Any ideas why this happens? I tried serching with numerous searches for this problem.

Related

How to be directed to page automatically?

I am writing a calculator. There are main 2 modes: polish and reverse polish system.
Anytime MainActivity is called, I like the MainActivity to direct the user to the correct page.
public class MainActivity extends BaseActivity
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
Intent intent;
String CalculatorMode = Memory.getPreference("CalculatorMode", this);
if (CalculatorMode.equals("Calc_reverse"))
intent = new Intent(this, Calc_reverse.class);
else
intent = new Intent(this, Calc_normal.class);
startActivity(intent);
}
}
After the user is directed to Calc_normal.class or Calc_reverse.class, and if he pressed the back button, he get back to the MainActivity. But nothing happen! The onCreate() is no more called. How to fix this, and is there a better way to write this? I am trying to learn, and any help is very welcome.
Instead of onCreate() you can call your methods in onStart() which will be called anytime you navigate.
onCreate() won't be called unless the activity is destroyed, you can check the activity lifecycle.
http://developer.android.com/reference/android/app/Activity.html
onStart() activity will be visible to user but won't interact.

Pressing back button stops and destroys my Activity insted of resuming it

I' working on an app with TabGroupActivity.
I'm launching through a tabhost activies so i can have more than one Intents in each tab:
public class MainTabActivity extends TabActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_tab);
final TabHost tabHost = getTabHost();
tabHost.addTab(tabHost.newTabSpec("tab2")
.setIndicator("Que")
.setContent(new Intent(this, TabGroup2Activity.class)));
}
TabGroup2Activity class:
public class TabGroup2Activity extends TabGroupActivity{
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent i = new Intent(getApplicationContext(),QueActivity.class);
startChildActivity("categorias", i);
}
}
I got the TabGroupActivity from this page:
My issue is when i'm clicking on the second tab, i get my QueActivity.class opened. It's basically a listview with items retrieved from a Data Base. When i clic a row i get a new intent opened with information passed by Bundle object.
The problem is when i hit the back button in this intent, i go back to the QueActivity Intent, which was on onPause() event, but it goes to onStop(), onDestroy() and onStart() event insted going to other state (onResume i think) where there is no need to be created again. The issue is the Intent being created again executes SQL querys and things that i don't need to execute anymore.
I'd like to press the go back and retreive the last intent in a way i don't have to create it again.
I hope I've explained myself succesfully.
Make sure that you have closed the CURSOR off DB in your activity wherever you have used it.
stopManagingCursor(c);
Try this:
<activity ... android:launchMode="singleTop" />
In your manifest file.
This thing is device specific, some devices didnt go to onresume, and start life cycle from start, To handle that you can use Savedinstatnce, to save a state .

Android app : show PreferenceFragment as a dialog?

I'm new to Android (with iOS background) and I would like to do the following :
I've made a PreferenceFragment in which I ask the user his credentials to connect to my WebServices. When I detect that those credentials are rejected by my server, I would like to show to my user a dialog (modal) where he can edit his preferences (credentials).
I've manage to do it using PreferenceActivity. So when I click a bouton, I execute the following code :
Intent settingsActivity = new Intent(getActivity().getBaseContext(), PreferencesConnection.class);
startActivity(settingsActivity);
Which load a PreferenceActivity as a Dialog with an XML ressource :
addPreferencesFromResource(R.xml.preferences_connection);
But this is depreciated. I can I do the same, but with Fragment? Should I use DialogFragment to show my PreferenceFragment, or not? Would it be easier to just rebuilt my credentials in a DialogFragment? Should I use a Activity instead of Fragment?
To do an old fashioned, single page settings screen without PreferenceHeaders, do as follows:
In your activity that invokes the settings screen (example is in onMenuItemSelected):
case R.id.menuSettings:
Intent settingsIntent = new Intent(this, SettingsActivity.class);
startActivityForResult(settingsIntent, GC.SETTINGS_ACTIVITY_ID);
break;
In your XML folder, create an old fashioned PreferenceScreen. PreferenceCategory, ListPreference, CheckBoxPreference, etc. Do not use PreferenceHeaders
Create a settings activity:
package com.mycompany.project1;
import android.os.Bundle;
import android.preference.PreferenceActivity;
import android.preference.PreferenceFragment;
public class SettingsActivity extends PreferenceActivity {
private final static String TAG = "SettingsAcitivity";
public SettingsActivity() {}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MyLog.d(TAG, "onCreate");
getFragmentManager().beginTransaction()
.replace(android.R.id.content, new LocationFragment()).commit();
}
public static class LocationFragment extends PreferenceFragment {
private String TAG = "LocationFragment";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MyLog.d(TAG, "onCreate");
addPreferencesFromResource(R.xml.settings);
}
}
}
Do not associate a dialog theme with the settings activity. You will get weird results for certain preference types such as radio buttons. (I tried the dialog thing and couldn't find the coding error(s). Everything worked fine when I used the standard activity theme instead of the dialog theme. Evidently the holo dialog theme collides with settings definitions.
Note: I used startActivityforResult so I could reinitialize specific settings values that changed.

Notification opens activity, press back button, prevent opening back stack activity?

This looks very similar to my previous question because it's some sort of follow up. I was not very happy with the only solution given; also, the solution was for a problem slightly different from this one. So let me try to explain the problem again...
A notification is created at boot (with a BroadcastReceiver).
My app main activity is opened and the home button is pressed (the activity will be sent to the back stack).
I pull down the status bar and press on the notification previously created at boot.
That will start some activity, different from the main one.
I press the back button and the main activity is displayed.
This is not very different from my previous question... The thing is, "main activity" was just an example. I could have opened the app main activity and then opened the about activity through a menu option and pressed the home button. The back stack would now be MainActivity ยป AboutActivity. Which means that when the back button is pressed while in "some activity" (started by pressing the notification), we would be brought to the top of the back stack, that is, the about activity.
What basically want is to prevent any other activity to be opened when I press the back button while in "some activity" (again, started by pressing the notification). I want to be brought exactly where I was, that could be the desktop or some other app's activity, but not my app's MainActivity nor AboutAcitivity cause that's not where I was, those were in the back stack, "sleeping" in the background.
I have come up with a solution, but I don't think it's very elegant and I was looking for something more, well, elegant... If you have any other suggestion, please, let me know.
Anyway, this is my proposed solution:
// I use this class for public static (or public static final) members and
// methods
public final class AppHelper {
public static final String KEY_RESUME_FROM_NOTIFICATION = "resumeFromNotification";
private static boolean sResumeFromNotification = false;
public static boolean getResumeFromNotification() {
return sResumeFromNotification;
}
public static void setResumeFromNotification(boolean resumeFromNotification) {
sResumeFromNotification = resumeFromNotification;
}
}
public class MainActivity extends ListActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
(...)
}
#Override
protected void onResume() {
super.onResume();
if(AppHelper.getResumeFromNotification()) {
AppHelper.setResumeFromNotification(false);
moveTaskToBack(true);
}
}
}
public class AboutActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
(...)
}
#Override
protected void onResume() {
super.onResume();
if(AppHelper.getResumeFromNotification()) {
AppHelper.setResumeFromNotification(false);
moveTaskToBack(true);
}
}
}
public class SomeActivity extends Activity {
// This will be called when the notification is pressed and the activity is
// not opened yet
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
(...)
extractIntentExtras(intent);
}
// This will be called if the activity is already opened and the
// notification is pressed
#Override
protected void onNewIntent(Intent intent) {
extractIntentExtras(intent);
super.onNewIntent(intent);
}
private void extractIntentExtras(Intent intent) {
Bundle bundleExtras = intent.getExtras();
if(bundleExtras != null) {
// These intent extras are set on the Intent that starts this activity
// when the notification is pressed
AppHelper.setResumeFromNotification(bundleExtras.getBoolean(
AppHelper.KEY_RESUME_FROM_NOTIFICATION));
mRowId = bundleExtras.getLong(AgendaNotesAdapter.KEY_ROW_ID);
populateNoteUpdateFields();
}
}
}
I don't know, but this solution doesn't look very elegant to me (but it works as I expect it) and I'm looking for alternatives or for strong opinions on my proposed solution as an acceptable and good solution. Thoughts?
After doing some more reading perhaps this is the combination of flags you need:
Intent intent = new Intent(mContext, SomeActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
startActivity(intent);
I think that should force your SomeActivity class to be launched in a completely new task.
When launching the Activity from the notification, you can control how the Activity you are about to open is put on the back stack, and what task it's associated with with Intent flags. You can try something like:
Intent intent = new Intent(mContext, SomeActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
If that doesn't work, try setting a few of the other flags until you get the desired behavior.
Do you ever want your MainActivity to stay in history? If not then my simple, crude solution is to finish the MainActivity when it is paused.
(Call this in your MainActivity)
#Override
public void onPause() {
finish();
}
This will ensure that your MainActivity is removed from history when you navigate away from it, and will never appear when the back button is pressed.
This could be used for AboutActivity as well.

Activity instance remains in the memory after onDestroy()

I know that this topic has been already beaten enough, but I still don't understand completely if Android System has fine behavior in following case:
I created small app consists of two classes, here is the code:
Main.java
public class Main extends Activity {
private Button bv;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
bv = (Button) findViewById(R.id.hello_txt);
bv.setOnClickListener(
new OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(Main.this, Main2.class);
startActivity(i);
}
}
);
}
}
Main2.java
public class Main2 extends Activity {
private TextView countOfActivities;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
countOfActivities = new TextView(this);
setContentView(countOfActivities);
countOfActivities.setText("Count of Activities: " + getInstanceCount());
}
}
When I clicked on the button from first activity several times, I get that even after pressing BACK button that should call second Activity's onDestroy() it's instance remains in the memmory.
Only after creating about 35 instances next click let me know, that GC cleared the memmory.
I just want to completely be sure that it is normal system's behavior.
Following pictures from Emulator and LogCat
Button clicked 10 times
LogCat output after clicked
Yes, the system works fine.
When you press the back button, your activity is removed from the activity stack.
onDestroy() may have been called, this doesn't mean that the instance was actually unallocated from the memory.

Categories

Resources