Parse database initialization- app crashes when navigating back to MainActivity - java

When my project starts up it's fine. MainActivity starts and then it navigates to another page but when I navigate back to MainActivity I sometimes get this error. http://imgur.com/FVhWMHn
I'm positive this is from calling Parse.enableLocalDatastore before Parse.initialize but here is my code for mainActivity
Parse.enableLocalDatastore(this);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Parse.initialize(this, "MY_INFO", "MY_INFO_AGAIN");
// check if a user is not cached
ParseUser currentUser = ParseUser.getCurrentUser();
if (currentUser == null)
{
// prompt user to LoginOrSignUp screen
Intent intent = new Intent(MainActivity.this, LoginOrSignUpActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
}`
local data store is called before initialize but it still crashes. I don't get it. I can communicate with my data base just fine and everything but as soon as I navigate back to main it crashes

you should initialize your Parse SDK in separate class as follows
public class SampleApplication extends Application {
public void onCreate(){
super.onCreate();
Parse.enableLocalDatastore(getApplicationContext());
Parse.initialize(this, "PARSE_APP_KEY", "PARSE_CLIENT_KEY");
ParseInstallation.getCurrentInstallation().saveInBackground();
}
}
IMPORTANT!!! you need to put this class info in your AndroidManifest.xml file.
hope it helps!

Related

Android 11: Cannot come back from startActivityForResult or registerForActivityResult and launch

I have an app with a MainActivity and a SecondaryActivity.
When the MainActivity opens the SecondaryActivity, there is a situation in which I need the user to pick up a phone number from a list that is in the MainActivity.
I've used startActivityForResult to open back the MainActivity with an extra in the intent so that the MainActivity opens directly the fragment with the specific list, like this:
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("UserInfo", userInfo);
intent.putExtra("SecondaryActivity", true);
startActivityForResult(intent, RESULT_FROM_MAIN_ACTIVITY);
And when the user clicks on one element of that list, I set the result and finish the MainActivity in order to return to the SecondaryActivity, like this:
Intent returnIntent = new Intent();
returnIntent.putExtra(PHONE_NUMBER, phoneNumber);
setResult(Activity.RESULT_OK, returnIntent);
finish();
That worked wonderfully until now, but I've noticed that in Android 11 devices, I have 2 problems:
startActivityForResult starts the MainActivity directly in the onResume() function without passing by the onCreate() function, as it is for Android 10 devices and below. And this forces me to check each time the MainActivity's onResume() function is called, if there is any extra sent. Thing that unnecessarily add an extra charge to the already charged MainActivity.
I cannot come back to the SecondaryActivity using finish()! Instead of that, the app is simply closed.
I've tried to use the new Activity Result APIs, and more specifically: registerForActivityResult, like this (in the SecondaryActivity):
private ActivityResultLauncher<Intent> activityResultLauncher;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// ...
activityResultLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),
result -> {
manageResult(result.getResultCode(), result.getData());
});
}
public void onPhoneNumberClick() {
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("UserInfo", userInfo);
intent.putExtra("SecondaryActivity", true);
activityResultLauncher.launch(intent);
}
But, this doesn't change anything to the 2 problems that I described: onResume() is directly called in MainActivity and finish() close the app instead of closing the MainActivity and coming back to the SecondaryActivity. I understand, that the fact that the MainActivity was already opened when I use startActivityForResult or registerForActivityResult and launch can be the cause of those problems, but what can I do to solve them?
Edit:
My MainActivity is defined as singleTask in AndroidManifest and it seems that something changed in Android 11 for the management of activities defined like this. If I remove this tag, it solves the problem but I'm not sure why we defined this activity as singleTask and I don't want to see come back any bug that this was intended to solve...

How do I determine if setPersistenceEnabled is already enabled?

All works well. Once the app is running, and I press home and back to the app through the multitask viewer, it works well. But once it is running, and I press it's icon from the drawer, it crashes because it is calling again "setPersistenceEnabled()" when it is already running. So, how can I check if it is enabled before trying to enable it? My code:
public class SplashActivity extends AppCompatActivity {
private FirebaseUser firAuth;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getInstance().setPersistenceEnabled(true);
firAuth = FirebaseAuth.getInstance().getCurrentUser();
if (firAuth!=null) {
// User is signed in.
Intent intent = new Intent(this, Identificador.class);
startActivity(intent);
finish();
} else {
// No user is signed in.
Intent intent = new Intent(this, LoginActivity.class);
startActivity(intent);
finish();
}
};
}
I recommend you using the following lines of code:
private static boolean calledAlready = false;
if (!calledAlready) {
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
calledAlready = true;
}
Run your app in debug mode. Set a breakpoint at your SplashActivity onCreate() an run through your use case that crashes the app. You'll see that SplashActivity onCreate() is invoked every time you launch your app after you leave it, because that's how activities work when they're exited and re-entered.
If you want to prevent repeated calls to setPersistenceEnabled(), you'll have to guard them against the invocation of your launch activity's onCreate() by setting some global variable to indicate that it's already been called, or put the call in a ContentProvider that gets created only once per process. I suggest the latter.

onCreate in an Activity ignores all the call stack sequence

MainActivity has an attribute android:launchMode="singleInstance" in AndroidManifest.xml
Here's the onCreate method from MainActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.i(TAG, "onCreate() from MainActivity");
session = new TempSession(this);
// check if logged in. If not, take the user back to login activity.
session.checkLogin(); // <---- HERE
Toast.makeText(this, "logged in as " + session.getUsername(), Toast.LENGTH_SHORT).show();
// Prevents screen from turning off when in this Activity.
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
....
and the TempSession, it checks if user is logged in, and if not, it will take the user to the LoginActivity.
This is the checkLogin() method
public void checkLogin(){
// Check login status
if(!this.isLoggedIn() || getUsername() == null) {
// user is not logged in redirect him to Login Activity
Intent i = new Intent(context, LoginActivity.class);
// Closing all the Activities
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
// Add new Flag to start new Activity
i.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
// Staring Login Activity
context.startActivity(i);
}
}
From my understanding, where I marked <---- HERE from MainActivity, when it calls checkLogin(), shouldn't it finish all task before it proceeds?
Currently, my app would open up LoginActivity, but still proceeds to the next instructions (e.g. makes a Toast saying "logged in as null", and keeps going on in background) and calls onPause() -> onStop() .
Is there any way to stop the MainActivity from keep going at that point?
This situation causes pressing back from LoginActivity bypasses to MainActivity.
Let me know if you need more information.
Thank you in advance.
Is there any way to stop the MainActivity from keep going at that point?
Yes. Have checkLogin() return some value that indicates MainActivity#onCreate(...) should return instead of proceeding.
Calling startActivity(...) does not start an activity. Think of it as asking the Android framework to start an activity. It places this job at the end of the UI thread's work queue. That means that before it starts the new activity, it will finish any other jobs that are already in the work queue, including the rest of the current method and possibly other lifecycle methods of the current activity.
The reason that your toast still shows up is because merely starting a new activity does not destroy your old activity. It's merely pushed to the backstack. Of course you can change this using the android:launchMode attribute in your manifest. A simple strategy in your cause might be to simply return true from your checkLogin() method when the user is logged in and change your onCreate as follows:
if( session.checkLogin() ) {
Toast.makeText(this, "logged in as " + session.getUsername(), Toast.LENGTH_SHORT).show();
// Prevents screen from turning off when in this Activity.
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
....
}

Set starting Activity with code in Android App

im new in developing Android Apps.
I know how to set the starting Activity with the AndroidManifest.xml, but i need a way to check something first before i choose the starting Activity.
My Problem:
I created a loginActivity and a mainActivity.
I want to do the following: If i log me in, i'll set a flag to 1 and at the next app start, i want show directly the mainActivity and not the login.
Is there any way to do that? I thought about creating a splashscreen where i can check if im logged in before showing the first Activity.
Thanks, Philip
Updated Code - working:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// get preferences
SharedPreferences userDetails = getApplicationContext().getSharedPreferences("userdetails", 0);
String savedEmail = userDetails.getString("email", "");
String savedPassword = userDetails.getString("password", "");
Boolean savedRemember = userDetails.getBoolean("remember", false);
Boolean savedLogged = userDetails.getBoolean("logged", false);
// check if already logged in
if(savedLogged) {
// start the overview
Intent intent = new Intent(this, ActivityOverview.class);
startActivity(intent);
finish();
}
else {
// initialize the form layout
setContentView(R.layout.activity_login);
// get views
this.email = (EditText)findViewById(R.id.editTextEmail);
this.password = (EditText)findViewById(R.id.editTextPassword);
this.remember = (CheckBox)findViewById(R.id.checkBoxRemember);
// set values to views
this.email.setText(savedEmail);
this.password.setText(savedPassword);
this.remember.setChecked(savedRemember);
}
}
I have something similar in one of my apps. I let the user chose weather it should auto-login or not. This is saved in the SharedPreferences.
When the app starts and in the mainpage, you should check - BEFORE the setContentView(R.layout.activity_login); and set finish(); after startActivity();
if(savedLogged) {
Intent intent = new Intent(this, ActivityOverview.class);
startActivity(intent);
finish();
}
setContentView(R.layout.activity_login);
You don't really need a splash screen.
When the user successfully logs into your app, set a boolean flag in SharedPreferences to true. Check if this flag is true in the login activity's onCreate() and if it is, use an Intent to launch the main activity.
You do not need to display your activity. Not sure what exactly your code flow is going to be but you can safely start i.e. with LoginActivity. in your onCreate() check if you are already logged (whatever it means for you) and if so instantly start MainActivity killing LoginActivity with finish().
Going with a splashscreen would be a good idea. Starting the loginActivity would show the login screen for a split second. This would be undesirable.

Android call method from another activity

How would I call a method from a different activity?
In my main activity, I have a button that shows a dialog to set the difficulty level of the game.
Then you click start game which starts a new activity containing a view with all the game information.
I need to send the difficulty level chosen to the other activity but cannot seem to figure out how to.
You could put it in the extras with the intent:
Intent StartGame = new Intent(this, StartGame.class);
StartGame.putExtra("difficulty", difficultyLevel);
startActivity(StartGame);
Then in your StartGame.class you can retrive it like this(assuming its a string):
Bundle extras = getIntent().getExtras();
if (extras != null) {
String difficulty= extras.getString("difficulty");
}
Well I don't know how sound my solution is but I created a myApplication class which sub classes the Application class .
This holds the reference to the activity I wanted to call
import android.app.Application;
public class myApplication extends Application {
public PostAndViewActivity pv;
}
When the PostAndViewActivity calls the oncreate is sets the pv to point to itself.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
((myApplication) getApplication()).pv = this;
Then when I want to call the method I want I just use code like this:
((myApplication) getApplication()).pv.refreshYourself();
Perhaps a bit hacky but it works.....
I welcome some critisism for this ;-)

Categories