I have built a small chat app using firebase. I have also implemented firebaseui for logging in. The problem I am facing is, if the user has not signed up. Whenever the app launches it should take me directly to FirebaseUi signup options but what is happening with current code is for a milli second it shows the layout of main activity and then goes to FirebaseUi.
Also when I am pressing back button before exiting it again shows me the layout of main activity. I want the activity to get destroyed and take me to home (android) but it shows me main activity for a millisecond and then the app exits.
Why is this happening?
public class MainActivity extends AppCompatActivity {
private static final int RC_SIGN_IN = 1;
private FirebaseAuth mAuth;
private FirebaseAuth.AuthStateListener mAuthStateListener;
private TextView mUserNameTextView;
private Button mSignOutButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mUserNameTextView = (TextView) findViewById(R.id.user_name_text_view);
mSignOutButton = (Button) findViewById(R.id.sign_out_button);
mAuth = FirebaseAuth.getInstance();
FirebaseUser user = mAuth.getCurrentUser();
mAuthStateListener = new FirebaseAuth.AuthStateListener() {
#Override
public void onAuthStateChanged(#NonNull FirebaseAuth firebaseAuth) {
FirebaseUser user = firebaseAuth.getCurrentUser();
if (user != null) {
// User is signed in
mUserNameTextView.setText(user.getDisplayName());
} else {
// User is signed out
startActivityForResult(
AuthUI.getInstance()
.createSignInIntentBuilder()
.setAvailableProviders(Arrays.asList(
new AuthUI.IdpConfig.EmailBuilder().build(),
new AuthUI.IdpConfig.GoogleBuilder().build()))
.build(),
RC_SIGN_IN);
}
}
};
mSignOutButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
signOut();
}
});
}
private void signOut() {
FirebaseAuth.getInstance().signOut();
mUserNameTextView.setText("");
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RC_SIGN_IN) {
if (resultCode == RESULT_OK) {
// Sign-in succeeded, set up the UI
Toast.makeText(this, "Signed in!", Toast.LENGTH_SHORT).show();
} else if (resultCode == RESULT_CANCELED) {
// Sign in was canceled by the user, finish the activity
Toast.makeText(this, "Sign in canceled", Toast.LENGTH_SHORT).show();
finish();
}
}
}
#Override
protected void onPause() {
super.onPause();
if (mAuthStateListener != null) {
// when app is paused remove the state listener
mAuth.removeAuthStateListener(mAuthStateListener);
}
}
#Override
protected void onResume() {
super.onResume();
// adding the state listener
mAuth.addAuthStateListener(mAuthStateListener);
}
}
I believe you won't be able to make the Main Activity not display for a millisecond upon app start, since you are first opening the Main Activity and then you redirect it (if I understood correctly).
I can however help you with your problem when you press the back button.
Add this to your FirebaseUi code as a normal method:
#Override
public void onBackPressed() {
Intent intent = new Intent(CurrentActivity.this, NextActivity.class);
//replace "CurrentActivity" and "NextActivity" with your activity names
startActivity(intent);
}
This will open the activity you want when the back button is pressed.
When you start new activity after logged in using FirebaseUI then you need to finish(will remove the activity from backstack) the Login Activity when you start activity.
Intent intent = new Intent(ActivityA.this, NextActivity.class);
startActivity(intent);
finish();
Related
I am developing an application where I press record button and it will automatically start video recording and stop after given duration. But what I found is just open video recording , I have to manually click record button and to save video, I have to click OK button.
Is there any way to do that automatically?
Here is my code:
public class MainActivity extends AppCompatActivity {
private static int CAMERA_PERMISSION_CODE=100;
private static int VIDEO_RECORD_CODE=101;
public Uri videoPath;
UploadTask uploadTask;
Button record_btn;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
record_btn=findViewById(R.id.record_button);
storageReference=FirebaseStorage.getInstance().getReference();
if (isCameraPresent()){
Log.i("VIDEO_RECORD_TAG","Camera is Detected");
getCameraPermission();
}else{
Log.i("VIDEO_RECORD_TAG","No Camera is detected");
}
record_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
recordVideo();
}
});
}
private boolean isCameraPresent(){
if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY)){
return true;
}else {
return false;
}
}
private void getCameraPermission(){
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
== PackageManager.PERMISSION_DENIED){
ActivityCompat.requestPermissions(this, new String[]
{Manifest.permission.CAMERA},CAMERA_PERMISSION_CODE);
}
}
private void recordVideo(){
Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
intent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, 5);
startActivityForResult(intent,VIDEO_RECORD_CODE);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode==VIDEO_RECORD_CODE){
if (resultCode==RESULT_OK){
assert data != null;
videoPath=data.getData();
Log.i("VIDEO_RECORD_TAG","Video is recorded and available at path" + videoPath);
}
else {
Log.i("VIDEO_RECORD_TAG","Video recording has some error");
}
}
}
You're using an Intent to capture video. What that does is literally ask another app to record video for you. When you're doing that you have to use that app as it is, which requires a button press. If you want to avoid that, you're going to have to directly use the camera yourself and handle the recording.
As an aside- if you're using an Intent to record video, you don't need Camera permission. You do if you're recording it yourself.
In Java, I am trying to implement a feature where only the admin (person who knows the device password) can access an information screen and when they click on a button within the app in the MainActivity, the lock screen will appear as a form of authentication and display another activity screen on success. Is this possible?
So far, I noticed that the authentication only displays when I open the app and not when I press the button in an onClickListener. Most of the solutions I've seen are doing it this way. I have the code in MainActivity within an onCreate() method.
MainActivity
ActivityResultLauncher<Intent> activityResultLaunch = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback<ActivityResult>() {
#Override
public void onActivityResult(ActivityResult result) {
if (result.getResultCode() == Activity.RESULT_OK) {
// There are no request codes
Intent data = result.getData();
} else {
finish();
}
}
});
start_end_button_add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
authScreen(activityResultLaunch);
}
});
private void authScreen(ActivityResultLauncher<Intent> activityResultLaunch) {
KeyguardManager mKeyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
if (!mKeyguardManager.isKeyguardSecure()) {
// Show a message that the user hasn't set up a lock screen.
} else {
Intent intent = mKeyguardManager.createConfirmDeviceCredentialIntent(null, null);
if (intent != null) {
startActivityForResult.launch(intent, REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS);
}
}
Intent intent = new Intent(DetectorActivity.this, SearchActivity.class);
startActivity(intent);
finish();
}
Currently, the app immediately goes to the SearchActivity class without having the lock screen displayed in between. Even if I get into the app after PIN code entered is a success, it still doesn't get into the activityResultLaunch success condition as per the new implementation referenced here by user Martin Zeitler.
Reference:
https://mobile-security.gitbook.io/mobile-security-testing-guide/android-testing-guide/0x05f-testing-local-authentication#:~:text=In%20Android%2C%20there%20are%20two,and%20the%20Biometric%20Authentication%20flow.
I am working on a login app using FirebaseAuth, I am implementing two separate Activities, one to work online and other for offline. There is third starter activity that tries to automatically login a user if his data is present on the SharedPreferences. When finish() is called on an activity signInWithEmailAndPassword won't stop.
when internet is not working and "Work Offline" button is clicked , it will lead the user to ActivityOffline. But when internet is restored while the user is on ActivityOffline , out of nowhere ActivityOnline will pop up because of signInWithEmailAndPassword on the starter activity which is already finished.
How can i stop signInWithEmailAndPassword when my Work Offline button is clicked?
public class Starter extends AppCompatActivity {
Button useOffline;
String email;
String password;
FirebaseAuth mAuth = FirebaseAuth.getInstance();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_starter);
Prefs prefs = new Prefs(this);
email = prefs.getStringEntry("email");
password = prefs.getStringEntry("password");
useOffline = findViewById(R.id.use_offline);
useOffline.setOnClickListener(v -> {
Intent intent = new Intent(Starter.this, OfflineActivity.class);
startActivity(intent);
finish();
});
final Handler handler = new Handler(Looper.getMainLooper());
handler.postDelayed(() -> useOffline.setVisibility(View.VISIBLE), 5000);
if (email.equals("") || password.equals("")) {
Intent intent = new Intent(Starter.this, LoginActivity.class);
startActivity(intent);
finish();
} else {
mAuth.signInWithEmailAndPassword(email, password).addOnCompleteListener(task -> {
if (task.isSuccessful()) {
prefs.setStringEntry("UID", Objects.requireNonNull(FirebaseAuth.getInstance().getCurrentUser()).getUid());
Intent intent = new Intent(Starter.this, OnlineActivity.class);
startActivity(intent);
} else {
prefs.removeEntry("email");
prefs.removeEntry("password");
Intent intent = new Intent(Starter.this, LoginActivity.class);
startActivity(intent);
}
finish();
});
}
}
}
You can set a boolean flag to true when offline button press and check this flag before start online activity.
I have a problem with my simple login app using SharingPreferences.
Imagine,that user logs in to application. He has "Log out" button inside his personal account. When user already logged in then he shouldn't return to login activity when he clicks "Back" button on his smartphone, he should return only then he clicks log out button and then he may fill fields with other data(other login,other password).
So, I can't finish() my first activity,because it is possible to return back.
Doesn't work ( it is impossible to return back to login (MainActivity) when I click LOG OUT button.
signInButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
sharedPreferencesEditor.putString("user_login",login.getText().toString());
sharedPreferencesEditor.putString("user_password",password.getText().toString());
sharedPreferencesEditor.apply();
Log.d("MyLog_name",sharedPreferences.getString("user_login",""));
Log.d("MyLog_pw",sharedPreferences.getString("user_password",""));
Log.d("MyTag",login.getText().toString());
Log.d("MyTag",password.getText().toString());
if(login.getText().toString().equals(getString(R.string.user_name)) && password.getText().toString().equals(getString(R.string.user_pw))){
Intent intent = new Intent(MainActivity.this, SuccessActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivityForResult(intent,1);
finish();
} else {
Toast.makeText(getApplicationContext(),"Wrong data(очищаю пароль)",Toast.LENGTH_SHORT).show();
password.setText("");
}
}
});
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == 1 && resultCode == RESULT_OK && data!=null){
String savedUser = data.getStringExtra("username");
Toast.makeText(getApplicationContext(),"Farewell, " + savedUser,Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(getApplicationContext(),"Error(Back button was pressed, no prohibition of back stack)",Toast.LENGTH_SHORT).show();
}
}
SuccessActivity.java
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_success);
welcome = (TextView)findViewById(R.id.welcome);
logOut = (Button) findViewById(R.id.logOut);
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
savedUserName = sharedPreferences.getString("user_login","");
welcome.setText("Welcome, " + savedUserName);
logOut.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent();
intent.putExtra("username",savedUserName);
setResult(RESULT_OK, intent);
finish();
}
});
}
Don't finish activity when you are using startActivityForResult() method just put your code ->
/////////
Intent intent = new Intent();
intent.putExtra("username",savedUserName);
setResult(RESULT_OK, intent);
finish();
///////////
in logOut click and on back pressed to get back to the Log In Activity
You will have to finish the LoginActivity while going for SuccessActivity and while clicking on Logout button you can start the LoginActivity once again Over there you can pass the data from SuccessActivity to LoginActivity and do needfull by checking if getIntent.getExtras() are null or not or you can check getIntent.hasExtra()
I'm working on an app that uses Firebase authentication to sign in users through phone number. I want to add a functionality such that there is only one-time login for the user, i.e. even if the user kills the app and starts it again, he should be logged in. Also, I don't want to add a logout feature. What can be done for this?
The simplest way to achieve this is to use a listener. Let's assume you have two activities, the LoginActivity and the MainActivity. The listener that can be created in the LoginActivity should look like this:
FirebaseAuth.AuthStateListener authStateListener = new FirebaseAuth.AuthStateListener() {
#Override
public void onAuthStateChanged(#NonNull FirebaseAuth firebaseAuth) {
FirebaseUser firebaseUser = firebaseAuth.getCurrentUser();
if (firebaseUser != null) {
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
startActivity(intent);
finish();
}
}
};
This basically means that if the user is logged in, skip the LoginActivity and go to the MainActivity.
Instantiate the FirebaseAuth object:
FirebaseAuth firebaseAuth = FirebaseAuth.getInstance();
And start listening for changes in your onStart() method like this:
#Override
protected void onStart() {
super.onStart();
firebaseAuth.addAuthStateListener(authStateListener);
}
In the MainActivity, you should do the same thing:
FirebaseAuth.AuthStateListener authStateListener = new FirebaseAuth.AuthStateListener() {
#Override
public void onAuthStateChanged(#NonNull FirebaseAuth firebaseAuth) {
FirebaseUser firebaseUser = firebaseAuth.getCurrentUser();
if (firebaseUser == null) {
Intent intent = new Intent(MainActivity.this, LoginActivity.class);
startActivity(intent);
}
}
};
Which basically means that if the user is not logged in, skip the MainActivity and go to the LoginActivity. In this activity you should do the same thing as in the LoginActivity, you should start listening for changes in the onStart().
In both activities, don't forget to remove the listener in the moment in which is not needed anymore. So add the following line of code in your onStop() method:
#Override
protected void onStop() {
super.onStop();
firebaseAuth.removeAuthStateListener(authStateListener);
}
You can save user login session in shared Preference
Do this when your login got Login Success
SharedPreferences pref = getApplicationContext().getSharedPreferences("MyPref", Activity.MODE_PRIVATE);
Editor editor = pref.edit();
editor.putBoolean("key_name", true); // Storing boolean - true/false
editor.commit();
and When Your apps is Starts (like Splash or login Page) use this
SharedPreferences sp=this.getSharedPreferences("MyPref", Context.MODE_PRIVATE);
boolean b = sp.getBoolean("key_name", false);
if(b==true){
//User Already Logged in skip login page and continue to next process
}else{
//User is Not logged in, show login Form
}
It will works for you.
This is from my working code from logging class:
private void LoginUserAccount(String email, String password)
{
if (TextUtils.isEmpty(email))
{
Toast.makeText(ResponseStartPage.this, "Please write Your Email", Toast.LENGTH_SHORT).show();
}
if (TextUtils.isEmpty(password))
{
Toast.makeText(ResponseStartPage.this, "Please write Your password", Toast.LENGTH_SHORT).show();
}
else
{
loadingBar.setTitle("Login Account");
loadingBar.setMessage("Please wait for verification...");
loadingBar.show();
mAuth.signInWithEmailAndPassword(email, password).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task)
{
if (task.isSuccessful())
{
String online_user_id = mAuth.getCurrentUser().getUid();
String DeviceToken = FirebaseInstanceId.getInstance().getToken();
usersReference.child(online_user_id).child("device_token").setValue(DeviceToken)
.addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid)
{
Intent mainIntent = new Intent(ResponseStartPage.this, ResponseMainActivity.class);
mainIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(mainIntent);
finish();
}
});
}
else
{
Toast.makeText(ResponseStartPage.this, "Please Check your email and password", Toast.LENGTH_SHORT).show();
}
loadingBar.dismiss();
}
});
}
}