Restrict User for only Fingerprint Authentication - android

Hy, I am a newbie currently learning Mobile development.
I am developing an application in which when the user presses the login button it will only give the option of Fingerprint authentication. but in my case, It gives options to the user to either uses Fingerprint or face authentication. How can I restrict the user to only Fingerprint authentication?
Here I am using the following Code:
package com.example.fingerprintauth
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.biometric.BiometricPrompt
import android.widget.Button
import android.widget.Toast
import androidx.core.content.ContextCompat
import java.util.concurrent.Executor
class MainActivity : AppCompatActivity() {
private lateinit var executor: Executor
private lateinit var biometricPrompt: BiometricPrompt
private lateinit var prompt: BiometricPrompt.PromptInfo
//private var flag =0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
executor=ContextCompat.getMainExecutor(this)
biometricPrompt= BiometricPrompt(this#MainActivity,executor,object:BiometricPrompt.AuthenticationCallback(){
override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
super.onAuthenticationError(errorCode, errString)
//authStatusTv.text = "Authentication Error: $errString"
Toast.makeText(this#MainActivity,"Authentication Error: $errString",Toast.LENGTH_SHORT).show()
}
override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
super.onAuthenticationSucceeded(result)
Toast.makeText(this#MainActivity,"Authentication Success",Toast.LENGTH_SHORT).show()
startActivity(
Intent(
this#MainActivity, Home::class.java
)
)
}
override fun onAuthenticationFailed() {
super.onAuthenticationFailed()
//authStatusTv.text = "Authentication Failed"
Toast.makeText(this#MainActivity,"Authentication Failed",Toast.LENGTH_SHORT).show()
}
})
val promptInfo=BiometricPrompt.PromptInfo.Builder()
.setTitle("Biometric Authentication")
.setSubtitle("Login Using Fingerprint authentication")
.setDeviceCredentialAllowed(true)
//.setAllowedAuthenticators(BIOMETRIC_STRONG or DEVICE_CREDENTIAL)
.build()
var authbtn = findViewById<Button>(R.id.authbtn)
authbtn.setOnClickListener {
biometricPrompt.authenticate(promptInfo)
}
}
}

Related

Firebase authentication issues, Kotlin

I am having some issues with Firebase auth. I'm building an app using using Kotlin but keep retrieving the error 'W/System: Ignoring header X-Firebase-Locale because its value was null.'
I had this working previously, when I had set up the application using activities. I've now moved towards MVP architecture, but this seems to have broken my firebase authentication. I have also ensured that Email/Password sign in method has been enabled in the Firebase console.
If anyone could please take a look and hopefully you can see where I am going wrong. Many thanks.
SignInView
package org.wit.hikingtrails.views.signIn
import android.content.Intent
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import org.wit.hikingtrails.databinding.ActivitySignInBinding
import com.google.firebase.auth.FirebaseAuth
import org.wit.hikingtrails.activities.SignUpActivity
import org.wit.hikingtrails.views.hikeList.HikeListView
import org.wit.hikingtrails.views.signUp.SignUpView
class SignInView : AppCompatActivity() {
lateinit var presenter: SignInPresenter
private lateinit var binding: ActivitySignInBinding
private lateinit var firebaseAuth: FirebaseAuth
override fun onCreate(savedInstanceState: Bundle?) {
presenter = SignInPresenter( this)
super.onCreate(savedInstanceState)
binding = ActivitySignInBinding.inflate(layoutInflater)
setContentView(binding.root)
firebaseAuth = FirebaseAuth.getInstance()
binding.textView.setOnClickListener {
val intent = Intent(this, SignUpView::class.java)
startActivity(intent)
}
binding.button.setOnClickListener {
val email = binding.emailEt.text.toString()
val pass = binding.passET.text.toString()
if (email.isNotEmpty() && pass.isNotEmpty()) {
presenter.doLogin(email, pass)
} else {
Toast.makeText(this, "Empty Fields Are not Allowed !!", Toast.LENGTH_SHORT).show()
}
}
}
override fun onStart() {
super.onStart()
if(firebaseAuth.currentUser != null){
val intent = Intent(this, HikeListView::class.java)
startActivity(intent)
}
}
}
SignInPresenter:
package org.wit.hikingtrails.views.signIn
import android.content.ContentValues.TAG
import android.content.Intent
import android.util.Log
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import com.google.firebase.auth.FirebaseAuth
import org.wit.hikingtrails.views.hikeList.HikeListView
import timber.log.Timber
import timber.log.Timber.i
class SignInPresenter (val view: SignInView) {
private lateinit var loginIntentLauncher : ActivityResultLauncher<Intent>
init{
registerLoginCallback()
}
var auth: FirebaseAuth = FirebaseAuth.getInstance()
fun doLogin(email: String, pass: String) {
// view.showProgress()
auth.signInWithEmailAndPassword(email, pass).addOnCompleteListener(view) { task ->
if (task.isSuccessful) {
val launcherIntent = Intent(view, HikeListView::class.java)
loginIntentLauncher.launch(launcherIntent)
} else {
i("Login failed:")
// val launcherIntent = Intent(view, HikeListView::class.java)
// loginIntentLauncher.launch(launcherIntent)
}
// view.hideProgress()
}
}
private fun registerLoginCallback(){
loginIntentLauncher =
view.registerForActivityResult(ActivityResultContracts.StartActivityForResult())
{ }
}
}
For anyone that was having the same issue: The issue was with my API key. In kotlin, to debug, I used Timber.i( "signInWithCredential:failure ${task.exception?.message}") within the else statement of doLogin() in the presenter

use google sign in to connect to google sheets api

I've been trying to write an android app with access to a google sheet. Unfortunately, I need to be able to write to the sheet as well as read so I can't use an api-key. I've used the google sheets api quick start: https://developers.google.com/sheets/api/quickstart/java
The problem I've encountered is that whenever I get far enough that asks me to login to google, this shows up:
I then followed the instructions for how to login to my app using google sign in. This is my MainActivity for it:
package com.example.frcscout22sheets
import Home
import android.content.ContentValues.TAG
import android.content.Intent
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import com.example.frcscout22sheets.databinding.ActivityMainBinding
import com.google.android.gms.auth.api.signin.GoogleSignIn
import com.google.android.gms.auth.api.signin.GoogleSignInAccount
import com.google.android.gms.auth.api.signin.GoogleSignInClient
import com.google.android.gms.auth.api.signin.GoogleSignInOptions
import com.google.android.gms.common.SignInButton
import com.google.android.gms.common.api.ApiException
import com.google.android.gms.common.api.Scope
import com.google.android.gms.tasks.Task
import com.google.api.services.sheets.v4.SheetsScopes
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var mGoogleSignInClient: GoogleSignInClient
companion object {
val instance = MainActivity()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken("975626648989-jf3cl536froqejdc741ai934ek540ovv.apps.googleusercontent.com")
.requestScopes(Scope(SheetsScopes.SPREADSHEETS))
.requestServerAuthCode("975626648989-jf3cl536froqejdc741ai934ek540ovv.apps.googleusercontent.com")
.requestEmail()
.build()
mGoogleSignInClient = GoogleSignIn.getClient(this, gso);
val dataFragment = Data()
val allianceSelectionFragment = AllianceSelection()
val homeFragment = Home()
val signin = findViewById<SignInButton>(R.id.sign_in_button)
setCurrentFragment(homeFragment)
signin.setOnClickListener {
signIn()
}
binding.bottomNavigationView.setOnItemSelectedListener {
when (it.itemId) {
R.id.data -> setCurrentFragment(dataFragment)
R.id.alliance_selection -> setCurrentFragment(allianceSelectionFragment)
R.id.home -> setCurrentFragment(homeFragment)
}
true
}
}
private fun setCurrentFragment(fragment: Fragment) =
supportFragmentManager.beginTransaction().apply {
replace(R.id.flFragment, fragment)
commit()
}
private fun signIn() {
val signInIntent: Intent = mGoogleSignInClient.signInIntent
startActivityForResult(signInIntent, 1)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
// Result returned from launching the Intent from GoogleSignInClient.getSignInIntent(...);
if (requestCode == 1) {
// The Task returned from this call is always completed, no need to attach
// a listener.
val task: Task<GoogleSignInAccount> = GoogleSignIn.getSignedInAccountFromIntent(data)
handleSignInResult(task)
}
}
private fun handleSignInResult(completedTask: Task<GoogleSignInAccount>) {
try {
val account = completedTask.getResult(ApiException::class.java)
// Signed in successfully, show authenticated UI.
} catch (e: ApiException) {
// The ApiException status code indicates the detailed failure reason.
// Please refer to the GoogleSignInStatusCodes class reference for more information.
Log.w(TAG, "signInResult:failed code=" + e.statusCode)
}
}
}
however, it's unclear to me where to go from here. When using the quickstart instructions, I would get the credentials from the .json that I downloaded from the cloud console and use that to get the credential which was then used to build the service in a different class:
private val service = Sheets.Builder(
HTTPTRANSPORT,
jsonfactory,
getCredentials(context, HTTPTRANSPORT)
How do I use the google sign in to access the sheets api? Thanks for the help!

Getting FATAL EXCEPTION while running the applications second screen

I am working on a android application that is NewsApp. I had made 2 activity. First is MainActivity and Second is HomeActivity. There is a button on MainActivity that is Register. If user press the button the MainActivity will be finish and HomeActivity appears but in my case when the user click register button the HomeActivity is not appearing and emulator show "App has stopped".
Since I am new to this I am not able to spot where the problem is and don't know how I can resolve it.
Thanks in advance.
The Error I am getting is:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.project.newsapp, PID: 8723
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.EditText.setText(java.lang.CharSequence)' on a null object reference
at com.project.newsapp.HomeActivity.onResponse(HomeActivity.kt:108)
at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:70)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
I am also attaching my HomeActivity and MainActivity code so you can tell me where I am doing it wrong.
My HomeActivity Code:
package com.project.newsapp
import android.app.ProgressDialog
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import com.project.newsapp.contract.Request
import com.project.newsapp.contract.Response
import com.project.newsapp.network.IRequestContract
import com.project.newsapp.network.NetworkClient
import com.project.newsapp.utils.Constant
import com.project.newsapp.utils.DataProvider
import com.project.newsapp.utils.showToast
import kotlinx.android.synthetic.main.activity_home.*
import kotlinx.android.synthetic.main.activity_home.btnExit
import kotlinx.android.synthetic.main.activity_main.*
import retrofit2.Call
import retrofit2.Callback
class HomeActivity : AppCompatActivity(), Callback<Response>, View.OnClickListener {
lateinit var userId:String
lateinit var userName:String
private val retrofitClient = NetworkClient.getNetworkClient()
private val requestContract = retrofitClient.create(IRequestContract::class.java)
private lateinit var sharedPreferences: SharedPreferences
private lateinit var progressDialog: ProgressDialog
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_home)
progressDialog = ProgressDialog(this)
progressDialog.setMessage("Please wait...")
progressDialog.setCancelable(true)
sharedPreferences = getSharedPreferences(Constant.PREF_NAME, Context.MODE_PRIVATE)
title = "NewsApp"
userId = intent.getStringExtra(Constant.KEY_USER_ID).toString()
userName = intent.getStringExtra(Constant.KEY_USER_NAME).toString()
txtUserName.text = "Welcome $userName"
btnAllNews.setOnClickListener (this)
btnMyNews.setOnClickListener (this)
btnSignOut.setOnClickListener (this)
btnExit.setOnClickListener (this)
}
override fun onStart() {
super.onStart()
progressDialog.show()
val request = Request(
action = Constant.GET_NEWS,
userId = userId
)
val callResponse = requestContract.makeApiCall(request)
callResponse.enqueue(this)
}
override fun onClick(v: View?) {
when(v?.id){
R.id.btnAllNews -> {
if(DataProvider.response.allNews.size>0){
Intent(this,ViewAllNewsActivity::class.java).apply {
startActivity(this)
}
}else{
showToast("Blogs are not available")
}
}
R.id.btnMyNews -> {
}
R.id.btnSignOut -> {
signOut()
}
}
}
private fun signOut(){
val editor = sharedPreferences.edit()
editor.clear().commit()
Intent(this,MainActivity::class.java).apply{
startActivity(this)
finish()
}
}
override fun onResponse(call: Call<Response>, response: retrofit2.Response<Response>) {
if(progressDialog.isShowing)
progressDialog.dismiss()
if(response.body()!=null){
val serverResponse = response.body()
if(serverResponse!!.status){
DataProvider.response = serverResponse
}else{
showToast(serverResponse.message)
edUserName.setText("")
}
}
else{
showToast("Server is not responding. Please try again later.")
}
}
override fun onFailure(call: Call<Response>, t: Throwable) {
if(progressDialog.isShowing)
progressDialog.dismiss()
showToast("Server is not responding. Please try again later.")
}}
My MainActivity Code:
package com.project.newsapp
import android.app.ProgressDialog
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.project.newsapp.contract.Request
import com.project.newsapp.contract.Response
import com.project.newsapp.network.IRequestContract
import com.project.newsapp.network.NetworkClient
import com.project.newsapp.utils.Constant
import com.project.newsapp.utils.showToast
import kotlinx.android.synthetic.main.activity_main.*
import retrofit2.Call
import retrofit2.Callback
class MainActivity : AppCompatActivity(), Callback<Response> {
private val retrofitClient = NetworkClient.getNetworkClient()
private val requestContract = retrofitClient.create(IRequestContract::class.java)
private lateinit var progressDialog:ProgressDialog
private lateinit var sharedPreferences:SharedPreferences
lateinit var userName:String
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
progressDialog = ProgressDialog(this)
progressDialog.setMessage("Please wait...")
progressDialog.setCancelable(true)
sharedPreferences = getSharedPreferences(Constant.PREF_NAME, Context.MODE_PRIVATE)
checkIfUserAlreadyRegistered()
btnRegister.setOnClickListener {
userName = edUserName.text.toString().trim().uppercase()
if(userName.isNullOrEmpty()){
showToast("Please Enter your Name")
}else{
progressDialog.show()
val request = Request(
action = Constant.REGISTER_USER,
userName = userName
)
val callResponse = requestContract.makeApiCall(request)
callResponse.enqueue(this)
}
}
/*btnExit.setOnClickListener {
finish()
}*/
}
override fun onFailure(call: Call<Response>, t: Throwable) {
if(progressDialog.isShowing)
progressDialog.dismiss()
showToast("Server is not responding. Please try again later.")
edUserName.setText("")
}
override fun onResponse(call: Call<Response>, response: retrofit2.Response<Response>) {
if(progressDialog.isShowing)
progressDialog.dismiss()
if(response.body()!=null){
val serverResponse = response.body()
if(serverResponse!!.status){
saveUserToPref(serverResponse.userId,userName)
Intent(this, HomeActivity::class.java).apply {
putExtra(Constant.KEY_USER_ID, serverResponse.userId)
putExtra(Constant.KEY_USER_NAME, userName)
startActivity(this)
finish()
}
}else{
showToast(serverResponse.message)
edUserName.setText("")
}
}
else{
showToast("Server is not responding. Please try again later.")
edUserName.setText("")
}
}
private fun saveUserToPref(userId:String, userName:String){
val editor = sharedPreferences.edit()
editor.putString(Constant.KEY_USER_ID,userId)
editor.putString(Constant.KEY_USER_NAME,userName)
editor.commit()
}
private fun checkIfUserAlreadyRegistered(){
val userId = sharedPreferences.getString(Constant.KEY_USER_ID,"invalid user id")
val userName = sharedPreferences.getString(Constant.KEY_USER_NAME,"invalid user name")
if(!userId.contentEquals("invalid user id")
&& !userName.contentEquals("invalid user name")){
Intent(this, HomeActivity::class.java).apply {
putExtra(Constant.KEY_USER_ID, userId)
putExtra(Constant.KEY_USER_NAME, userName)
startActivity(this)
finish()
}
}
}}
Kotlin synthetic accessors are deprecated.
One of the reasons why they are deprecated is that they lead to the error that you are seeing. edUserName appears to be null, implying that R.layout.activity_home does not actually have a widget whose ID maps to edUserName.
The problem may come from:
import kotlinx.android.synthetic.main.activity_main.*
Most likely, that should not be in HomeActivity, since you are not using activity_main there.

my app keep crashing after tryed to connect it to firebase kotlin

I created a simple login and sup app and connect it to firebase.
so far the logging layout does not even show up it's just crushing while lanching which makes me so confused?
[![eroo message][1]][1]
this is my login/main activity
import android.content.Intent
import android.os.Bundle
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.auth.FirebaseUser
class MainActivity : AppCompatActivity() {
private lateinit var auth: FirebaseAuth
val button: Button = findViewById(R.id.buGotosub)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
auth = FirebaseAuth.getInstance()
button.setOnClickListener {
startActivity(Intent(this,SubscribAcc::class.java))
finish()
}
}
public override fun onStart() {
super.onStart()
// Check if user is signed in (non-null) and update UI accordingly.
val currentUser = auth.currentUser
updarUI(currentUser)
}
fun updarUI(currentUser : FirebaseUser?){
}
} ```

How can I be sure that my SHA-1 key is populated properly in the Android app?

I am in the process of implementing sign-in via the Google account in the Android app. Now I have the known issue of com.google.android.gms.common.api.ApiException: 10
when trying to sign in.
Most StackOverflow answers refer to improper SHA-1 key and advise to match it between local .gradlew signing report, google developers console, and firebase console. I did all of that, removed my SHA-1 and created a new one during the new build, made sure that it matches my local key store, Google Developer Console, and Firebase Console. Also, I hardcoded web_client_id and made sure my package name is the same in Google Developers and Firebase Consoles. Still doesn't work.
So the idea is maybe in within at the app SHA-1 key is not populated properly at the compile time? There is a known similar issue with the web_client_id which we need to hardcode. Web_client_id is populated from the same place where the SHA-1 key is stored: google-services.json file.
Could you please help:
How can I make sure that my SHA-1 is populated properly?
How can I log my SHA-1 key at run time?
Are there other ideas to solve this login problem?
Below is my code for the sign in fragment class:
package com.exa.myProject.login
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import com.exa.myProject.R
import com.exa.myProject.list.ListNonRespondedActivity
import com.exa.myProject.unsorted.Global.Companion.TAG
import com.exa.myProject.unsorted.Global.Companion.toastString
import com.google.android.gms.auth.api.signin.GoogleSignIn
import com.google.android.gms.auth.api.signin.GoogleSignInAccount
import com.google.android.gms.auth.api.signin.GoogleSignInClient
import com.google.android.gms.auth.api.signin.GoogleSignInOptions
import com.google.android.gms.common.SignInButton
import com.google.android.gms.common.api.ApiException
import com.google.android.gms.tasks.Task
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.auth.FirebaseUser
import com.google.firebase.auth.GoogleAuthProvider
import com.google.firebase.auth.ktx.auth
import com.google.firebase.ktx.Firebase
private const val RC_SIGN_IN = 100
class GoogleSignInFragment : Fragment(){
lateinit var auth: FirebaseAuth
var googleSignInClient: GoogleSignInClient? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(getString(R.string.default_web_client_id_hardcoded))
.requestEmail()
.build()
googleSignInClient = this.activity?.let { GoogleSignIn.getClient(it, gso) }
auth = Firebase.auth
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_google_sign_in, container, false)
val signInButton: SignInButton = view.findViewById<View>(R.id.sign_in_button) as SignInButton
signInButton.setOnClickListener {
signIn()
}
signInButton.setSize(SignInButton.SIZE_STANDARD)
return view
}
override fun onStart() {
super.onStart()
val currentUser = auth.currentUser
updateUI(currentUser)
}
private fun signIn() {
val signInIntent = googleSignInClient?.signInIntent
startActivityForResult(signInIntent, RC_SIGN_IN)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == RC_SIGN_IN) {
val task = GoogleSignIn.getSignedInAccountFromIntent(data)
handleSignInResult(task)
}
}
private fun firebaseAuthWithGoogle(idToken: String) {
val credential = GoogleAuthProvider.getCredential(idToken, null)
this.activity?.let {
auth.signInWithCredential(credential)
.addOnCompleteListener(it) { task ->
if (task.isSuccessful) {
Log.i(TAG, "signInWithCredential:success")
val user = auth.currentUser
updateUI(user)
} else {
Log.i(TAG, "signInWithCredential:failure", task.exception)
updateUI(null)
}
}
}
}
private fun updateUI(model: FirebaseUser?){
val signInStatus = if (model == null) getString(R.string.user_not_signed) else
getString(R.string.welcome) + model.displayName
toastString(signInStatus)
if (model != null) {
val intent = Intent(this.activity, ListNonRespondedActivity::class.java)
startActivity(intent)
}
}
private fun handleSignInResult(task: Task<GoogleSignInAccount>) {
try {
val account = task.getResult(ApiException::class.java)!!
Log.d(TAG, "firebaseAuthWithGoogle:" + account.id)
firebaseAuthWithGoogle(account.idToken!!)
} catch (e: ApiException) {
Log.w(TAG, "Google sign in failed", e)
updateUI(null)
}
}
}

Categories

Resources