i'm trying to close the preference activity after i click the back button..but when i press it then click the multi tasking button i see two activities opened for my app the one i'm currently on and the preferenceActvivty which i was on before i pressed back
this is my code
public class List extends PreferenceActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getFragmentManager().beginTransaction().replace(android.R.id.content, new SetFrag()).commit();
}
public static class SetFrag extends PreferenceFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.settings_main);
}
}
#Override
public void onBackPressed() {
super.onBackPressed();
List.this.finish ();
}
Thanks for help.
I got the solution, Usually we need to code before super.onBackPressed() to be called.
So change your code in to this
public class List extends PreferenceActivity {
// do some stuff
#Override
public void onBackPressed() {
List.this.finish ();
}
Edit :
So here is my final answer
paste this custom exit activity in your package
public class ExitActivity extends Activity
{
#SuppressLint("NewApi")
#Override protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
if(android.os.Build.VERSION.SDK_INT >= 21)
{
finishAndRemoveTask();
}
else
{
finish();
}
}
public static void exitApplication(Context context)
{
Intent intent = new Intent(context, ExitActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NO_ANIMATION | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
context.startActivity(intent);
}
}
add in manifest
<activity
android:name=".ExitActivity"
android:autoRemoveFromRecents="true"
android:theme="#android:style/Theme.NoDisplay" />
And call it with
#Override
public void onBackPressed() {
ExitActivity.exitApplication(getApplicationContext());
}
Good luck
Problem solved!!
step 1:In the MainActivity, add flag "FLAG_ACTIVITY_NO_HISTORY" to the Intent, then start the SettingsActivity.
step 2: Override the onBuildStartFragmentIntent() method of SettingsActivity(PreferenceActivity) for adding flag FLAG_ACTIVITY_FORWARD_RESULT,so that the activityresult can return to the MainActivity.
Like below:
#Override
public Intent onBuildStartFragmentIntent (String fragmentName,
Bundle args,
int titleRes,
int shortTitleRes)
{
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setClass(this, getClass());
intent.putExtra(EXTRA_SHOW_FRAGMENT, fragmentName);
intent.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS, args);
intent.putExtra(EXTRA_SHOW_FRAGMENT_TITLE, titleRes);
intent.putExtra(EXTRA_SHOW_FRAGMENT_SHORT_TITLE, shortTitleRes);
intent.putExtra(EXTRA_NO_HEADERS, true);
intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);//the new statement
return intent;
}
Related
I have a MainActivity with some cards which have different names. onClick, the title is passed as an intent via the adapter to the secondActivity and displayed as the header. From there, I can go to other activities. If I come back from one of these other activities (via the back button created by establishing second activity as the parent activity) the header is gone. How do I keep the header that was originally passed on as an intent or should I go about this completely different?
I have tried using onResume() and onStart() in the secondActivity to reassign the intent from a global variable.
The adapter class, where the card onClick method is written:
#Override
public void onBindViewHolder(final TripHolder tripHolder, final int position) {
Trip trip = trips.get(position);
tripHolder.setDetails(trip);
tripHolder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(context, SecondActivity.class);
TextView card_title = v.findViewById(R.id.TripNamecl);
intent.putExtra("card_title", card_title.getText().toString());
context.startActivity(intent);
}
});
}
The secondActivity where the header should be displayed:
public class SecondActivity extends AppCompatActivity {
String name;
TextView header;
static final String STATE_HEADER = "header";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
name = getIntent().getStringExtra("card_title");
header = findViewById(R.id.TripsHeader);
header.setText(name);
}
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putString(STATE_HEADER, name);
}
#Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
name = savedInstanceState.getString(STATE_HEADER);
header.setText(name);
}
public void launchMapsActivity(View view) {
Uri gmmIntentUri = Uri.parse("geo:48.8566°,2.3522");
Intent mapIntent = new Intent(Intent.ACTION_VIEW, gmmIntentUri);
mapIntent.setPackage("com.google.android.apps.maps");
if (mapIntent.resolveActivity(getPackageManager()) != null) {
startActivity(mapIntent);
}
}
public void launchTravelActivity(View view) {
Intent intent = new Intent(this, TravelActivity.class);
startActivity(intent);
}
public void launchPlansActivity(View view) {
Intent intent = new Intent(this, PlansActivity.class);
startActivity(intent);
}
}
SOLUTION:
The solution was to put android:launchMode="singleTop" into the manifest file for the secondactivity. It's described in more detail here: How can I return to a parent activity correctly?
In order to do it you should override onSavedInstanceState in your SecondActivity.
You can use something like that, obv adapt it to your needs:
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
//here you can save your variables
savedInstanceState.putString("myHeader", name);
}
#Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
//here you can retrieve your variables
name = savedInstanceState.getString("myHeader");
}
Let me know if this worked! good luck
remove header.setText(name); from onResume and onStart methods
If you want to save data in first activity between lifecicle method calls you have to save your data in Bundle object.
Override method onSaveInstanceState(Bundle bundle) of your activity:
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("AStringKey", variableData);
outState.putString("AStringKey2", variableData2);
}
And also override Activity method onRestoreInstanceState(Bundle savedInstanceState):
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState){
super.onRestoreInstanceState(savedInstanceState);
variableData = savedInstanceState.getInt("AStringKey");
variableData2 = savedInstanceState.getString("AStringKey2");
setYourHeaderMethodExample(variableData2)
}
When coming back from third activity to second activity onStart() and onResume() method call executes. Try not using onStart() and onResume() for setting the header and use onCreate method for setting the header.
onCreate() method executes only once in its lifetime, but onStart() and onResume() will execute whenever the activity comes to screen. So when coming back from third activity we don't have any values in the intent.
In your second activity's onCreate method add:
getSupportActionBar().setHomeButtonEnabled(true);
and override the onOptionsItemSelected() method in the class and add the following code:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case android.R.id.home:
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
You don't need to override the onStart() and onResume() methods.
I just wanted to create an application that works like an HTML page or something. Just after clicked button, new site is opening.
I don't know why there are 5 errors: 2 Errors:(15, 11 and 15,18) error: illegal start of expression, and 2 Errors:(15, 31 and 15,41) error: ';' expected.
Here's the code:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
{
public void nextStep(View view) {
Intent i = new Intent(this, SecondaryActivity.class);
startActivity(i);
}
}
}
Coud you help me? :/
your message is not formated
It shows like if
{ public void nextStep(View view) {Intent i = new Intent(this, SecondaryActivity.class);startActivity(i); }
is inside you onCreate function,
if true, you can't write a function inside another function
There was problem with bracket.Try this
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void nextStep(View view) {
Intent i = new Intent(this, SecondaryActivity.class);
startActivity(i);
}
}
I develop android app. It needs save Internet data and login/password pair. I need to check that in every activity. How to do that optimally? My solution:
I create the BaseActivity class:
public class BaseActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
checkRequirements();
}
private void checkRequirements() {
if (needToCheckInternetConnection())
checkInternetConnection();
//check other requirements
}
private void checkInternetConnection() {
if (!Updater.getInstance(context).checkInternetConnection()) {
Bundle data = new Bundle();
data.putSerializable(SplashScreenActivity.FIELD_ACTION, SplashScreenActivity.Action.SHOW_TEXT);
data.putString(SplashScreenActivity.FIELD_TEXT, getString(R.string.splashScreenInternetNotAvailable));
changeActivity(SplashScreenActivity.class, data);
}
}
protected void changeActivity(Class<?> goTo, Bundle data) {
Intent intent = new Intent(context, goTo);
if (data != null)
intent.putExtras(data);
startActivity(intent);
finish();
}
}
And I extends all activity classes from this.
But finish() not working. So, how to change that architecture or force to work the finish() method?
In my App the user has to login.
They open the app on the login page
They enter email/password and hit login
A LoadingScreenActivity is opened that has a swirly circle and is running an AsyncTask that goes to my database and retrieves all the users info
After the AsyncTask is completed it starts an intent to launch MainPageActivity.
There are two problems with this at the moment:
If the user logs in and then goes to the home screen while the app loads the MainPageActivity will open as soon as it is ready (on top of the existing home page) even though the app has been minimised
If the user logs in and then goes to the home screen while the app loads and then returns to the loading screen the AsyncTask will complete twice over
For problem 1. At the moment my onPostExecute() method in LoadingScreenActivity looks like this:
#Override
public void onPostExecute() {
//open the main page
Intent mainPage = new Intent(getApplicationContext(), MainPageActivity.class);
mainPage.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
mainPage.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK );
startActivity(mainPage);
}
Is there a way I could detect in this method if the main page activity should be opened yet?
For problem 2. I've hit a complete road block on this, is there a way to detect if the activity has simply been re opened rather than started for the first time? I'd really appreciate any tips on this, I'm quite new to android so I'm not even convinced an Async task is the way to go with this.
Thanks for your time
LoadingScreenActivity.java
public class LoadingScreenActivity extends Activity implements TaskFragment.TaskCallbacks {
private static final String TAG_TASK_FRAGMENT = "task_fragment";
private TaskFragment mTaskFragment;
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
FragmentManager fm = getFragmentManager();
mTaskFragment = (TaskFragment) fm.findFragmentByTag(TAG_TASK_FRAGMENT);
// If the Fragment is non-null, then it is currently being
// retained across a configuration change.
if (mTaskFragment == null) {
mTaskFragment = new TaskFragment();
fm.beginTransaction().add(mTaskFragment, TAG_TASK_FRAGMENT).commit();
}
setContentView(R.layout.loading_screen);
ActionBar actionBar = getActionBar();
actionBar.hide();
TextView title = (TextView) findViewById(R.id.loading_title);
TextView progress = (TextView) findViewById(R.id.loading_progress);
title.setText(R.string.app_name);
progress.setText("Loading your info");
}
#Override
public Context onPreExecute() {
return getApplicationContext();
}
#Override
public void onProgressUpdate(int percent) {
}
#Override
public void onCancelled() {
Intent login = new Intent(getApplicationContext(), LoginActivity.class);
login.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(login);
finish();
}
#Override
public void onPostExecute() {
//open the main page
Intent mainPage = new Intent(getApplicationContext(), MainPageActivity.class);
mainPage.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
mainPage.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK );
startActivity(mainPage);
}
}
and TaskFragment.java
public class TaskFragment extends Fragment {
static interface TaskCallbacks {
Context onPreExecute();
void onProgressUpdate(int percent);
void onCancelled();
void onPostExecute();
}
private TaskCallbacks mCallbacks;
private DummyTask mTask;
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
mCallbacks = (TaskCallbacks) activity;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Retain this fragment across configuration changes.
setRetainInstance(true);
// Create and execute the background task.
mTask = new DummyTask();
mTask.execute();
}
#Override
public void onDetach() {
super.onDetach();
mCallbacks = null;
}
private class DummyTask extends AsyncTask<Void, Integer, Void> {
Context context;
boolean running = true;
#Override
protected void onPreExecute() {
if (mCallbacks != null) {
context = mCallbacks.onPreExecute();
}
}
#Override
protected Void doInBackground(Void... ignore) {
//Get the current thread's token
synchronized (this)
{
if(running){
DatabaseHandler dbHandler = new DatabaseHandler(context);
dbHandler.populateSQLiteDatabase();
}
}
return null;
}
#Override
protected void onProgressUpdate(Integer... percent) {
if (mCallbacks != null) {
mCallbacks.onProgressUpdate(percent[0]);
}
}
#Override
protected void onCancelled() {
if (mCallbacks != null) {
mCallbacks.onCancelled();
}
}
#Override
protected void onPostExecute(Void ignore) {
if (mCallbacks != null) {
mCallbacks.onPostExecute();
}
}
}
}
in your activity in the manifest just add android:configChanges="keyboardHidden|orientation|screenSize"
and in the activity implement this
#Override
public void onConfigurationChanged(Configuration newConfig) {
};
I'm afraid, i don't really understand your first problem.
About the second one, there are a couple of ways depending on your minimum API level. Starting from API 14 you may register ActivityLifecycle Callbacks inside an Android Application. To do this, i would recommend:
Inherit Android application with a custom one
Replace the Android application in your manifest
inside your custom application register itself as activity lifecycle listener
inside the abstract methods you get the instance of the currently applying activity (may safe object.name() in a String)
depending on your handling you may safe a boolean value or whatever to identify the behaviour
methods inside your custom application are accessible by casting (MyCustomApplication)getApplication()
Heres a snippet:
package com.example.preferencestest;
import android.app.Activity;
import android.app.Application;
import android.app.Application.ActivityLifecycleCallbacks;
import android.os.Bundle;
public class MyCustomApplication extends Application implements ActivityLifecycleCallbacks {
private String storedActivity;
private Boolean doOrNot = false;
public MyCustomApplication() {}
public Boolean getDoOrNot() { return doOrNot;}
public void setDoOrNot(Boolean doOrNot) { this.doOrNot = doOrNot; }
#Override
public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(this);
}
// these two are the most important ones since they will be fired everytime
#Override
public void onActivityResumed(Activity activity) {
if (activity.getClass().getName().equals(storedActivity)) {
doOrNot = true;
}
}
#Override
public void onActivityPaused(Activity activity) {
storedActivity = activity.getClass().getName();
}
#Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) { }
#Override
public void onActivityStarted(Activity activity) { }
#Override
public void onActivityStopped(Activity activity) { }
#Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) { }
#Override
public void onActivityDestroyed(Activity activity) { }
}
inside your Manifest you MUST declare this new Applicationclass like this:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.preferencestest"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="21" />
<application
android:name="com.example.preferencestest.MyCustomApplication"
{...}
Then inside your Activity you may do this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Boolean whatToDo = ((MyCustomApplication)getApplication()).getDoOrNot();
}
Using onConfigurationChanged has a couple of disadvantages. There are a couple of actions (placing device in dock, turning display and so on) which restart the Activity. You should rather save the current state of the Activity with
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
#Override
protected void onRestoreInstanceState(Bundle state) {
super.onRestoreInstanceState(state);
}
I abstract my model like this:first there is a class UserInfo which holds user information:
public class UserInfo extends Application{
private int userid;
public void setUserId(int id)
{
userid=id;
}
public int getUserId()
{
return userid;
}
}
Then in MainActivity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
userinfo=(UserInfo)getApplication();
userinfo.setUserId(1354);
....
Intent intent=new Intent(MainActivity.this,VoteActivity.class);
startActivity(intent);
}
public
#Override void onResume()
{
super.onResume();
TextView text=(TextView)MainActivity.this.findViewById(R.id.usernameText);
text.setText(userinfo.getUserId()+" ");
}
And in VoteActivity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_vote);
userinfo=(UserInfo)getApplication();
Button back=(Button)findViewById(R.id.backButton);
back.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View arg0) {
userinfo.setUserId(-100);
Intent intent=new Intent(VoteActivity.this,MainActivity.class);
startActivity(intent);
}});
}
The result is: when MainActivity first run, userid in UserInfo is 1354 ; And when VoteActivity first run, userid in UserInfo is 1354 too.However when back to MainActivity from VoteAcitivy userid remains 1354 which should be -100.What is wrong with this use of Application context?
You're starting a new activity in your onClick method :
Intent intent=new Intent(VoteActivity.this,MainActivity.class);
startActivity(intent);
And you direct set your id in the MainActivity :
userinfo.setUserId(1354);
That's why you get (1354). You should call finish in your on click (instead of starting the MainActivity).
The activity's stack look like this : MainActivity - VoteActivity - MainActivity and I think you want it to look like this : MainActivity after pressed on your Button
#Override
public void onClick(View arg0) {
userinfo.setUserId(-100);
finish();
}});
How you do you get back for your MainActivity? Pressing the device's back button or clicking on your button? If you press the device's back button your onClickListener won't be called, so that's why id remains the same.
#Override
public void onClick(View arg0) {
userinfo.setUserId(-100);
Intent intent=new Intent(VoteActivity.this,MainActivity.class);
startActivity(intent);
}});
when you click on your back button you restart MainActivity. The MainActivity onCreate will be excuted again. Is MainActivity flagged as singleInstance?