I am trying to geth step count and heart rpm from the Google Fit Api. I am aware that the getHistoryClient and getSensorClient are deprecated.
Please how can I replace this methods with the Sensor Manager. I do not seem to undersatnd the documentation.
class MainActivity : AppCompatActivity(), SensorEventListener {
private val listOfPermissionNotGranted = mutableListOf<String>()
lateinit var permissionsLauncher: ActivityResultLauncher<Array<String>>
lateinit var signInLauncher: ActivityResultLauncher<Intent>
private val sensorManager: SensorManager by lazy { getSystemService(SENSOR_SERVICE) as SensorManager }
private val accelerometer by lazy { sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) }
lateinit var googleApiClient: GoogleSignInClient
#RequiresApi(Build.VERSION_CODES.Q)
#OptIn(ExperimentalTime::class)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
signInLauncher = registerForActivityResult(StartActivityForResult()) { result ->
if (result.resultCode == RESULT_OK) {
val task = GoogleSignIn.getSignedInAccountFromIntent(result.data)
if (task.isSuccessful) {
Toast.makeText(this, "Signed in", Toast.LENGTH_LONG).show()
Log.d("MainUser", "${task.result}")
val fitnessOptions = FitnessOptions.builder()
.addDataType(DataType.TYPE_STEP_COUNT_DELTA, FitnessOptions.ACCESS_READ)
.addDataType(
DataType.AGGREGATE_STEP_COUNT_DELTA,
FitnessOptions.ACCESS_READ
)
.build()
Fitness.getHistoryClient(this, GoogleSignIn.getAccountForExtension(this, fitnessOptions))
.readDailyTotal(DataType.TYPE_STEP_COUNT_DELTA)
.addOnSuccessListener { result ->
val totalSteps =
result.dataPoints.firstOrNull()?.getValue(Field.FIELD_STEPS)?.asInt() ?: 0
// Do something with totalSteps
Log.i("Main", "total $totalSteps")
}
.addOnFailureListener { e ->
Log.i("Main", "There was a problem getting steps.", e)
}
// val googleSignInAccount =
// GoogleSignIn.getAccountForExtension(this, fitnessOptions)
}
}
}
permissionsLauncher = registerForActivityResult(RequestMultiplePermissions()) { permissionMap ->
val permitted = permissionMap.all { it.value }
if (permitted) {
val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestScopes(Fitness.SCOPE_ACTIVITY_READ)
.build()
googleApiClient = GoogleSignIn.getClient(this, gso)
val signInIntent = googleApiClient.signInIntent
signInLauncher.launch(signInIntent)
}
}
permissionsLauncher.launch(
arrayOf(
Manifest.permission.BODY_SENSORS,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACTIVITY_RECOGNITION
)
)
listOfPermissionNotGranted.forEach { permission ->
Toast.makeText(this, "$permission is not granted", Toast.LENGTH_LONG).show()
}
}
override fun onResume() {
super.onResume()
sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL)
}
override fun onPause() {
super.onPause()
sensorManager.unregisterListener(this)
}
override fun onSensorChanged(event: SensorEvent?) {
if (event?.sensor?.type == Sensor.TYPE_STEP_DETECTOR) {
Log.d("MainSensorStep detected", "${event.values[0]}")
Toast.makeText(this, "Step is detected ${event.values[0]}", Toast.LENGTH_LONG).show()
} else if (event?.sensor?.type == Sensor.TYPE_STEP_COUNTER) {
Log.d("MainSensorStep counting", "${event.values[0]}")
Toast.makeText(this, "Step is counting ${event.values[0]}", Toast.LENGTH_LONG).show()
}
}
override fun onAccuracyChanged(sensor: Sensor?, p1: Int) {
Log.d("MainSensor", "$sensor")
}
}
You might want to go over this answer in a separate, but related SO post, and get a better understanding of the different approaches.
If you need to collate processed steps information from the User, then Google Fit is the better approach. You can see how you get the same step count as what's on the google fit app using the cited example code in their official docs: https://developers.google.com/fit/scenarios/read-daily-step-total#android
I see that you're also using the Android API for Fit, you might want to explore Android Health Connect too as the Android API for Fit will be deprecated soon.
Related
My Goal: I wanted to retieve my Step Counter data from Google FIT API with a small Android App. Therefore I tried the tutorial code:
I implemented the log in code which is necessary to use Google FIT (https://developers.google.com/identity/sign-in/android/sign-in)
Then I implemented the Google Fit request for the historical step counter data (https://developers.google.com/fit/android/history)
I granted access to the FIT API for my app.
My Problem:
The code seems to work properly. The successListener is called but there is no data retrieved. What am I doing wrong?
My Code (sorry, it' copy paseted from the tutorial, not formated, not properly):
class GoogleFitStepCounterActivity : AppCompatActivity() {
val GOOGLE_FIT_PERMISSIONS_REQUEST_CODE = 123456
private val RC_SIGN_IN = 1
private var mGoogleSignInClient: GoogleSignInClient? = null
// Configure sign-in to request the user's ID, email address, and basic
// profile. ID and basic profile are included in DEFAULT_SIGN_IN.
var gso: GoogleSignInOptions = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.build()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val signInButton = findViewById<SignInButton>(R.id.sign_in_button)
signInButton.setSize(SignInButton.SIZE_STANDARD)
signInButton.setOnClickListener {
signIn()
}
// Build a GoogleSignInClient with the options specified by gso.
mGoogleSignInClient = GoogleSignIn.getClient(this, gso);
}
override fun onStart() {
super.onStart()
val account = GoogleSignIn.getLastSignedInAccount(this)
updateUI(account)
}
private fun updateUI(account: GoogleSignInAccount?) {
if (account != null)
{
this.requestGoogleFITData()
}
}
private fun signIn() {
val signInIntent = mGoogleSignInClient!!.signInIntent
startActivityForResult(signInIntent, RC_SIGN_IN)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
super.onActivityResult(requestCode, resultCode, data)
// Result returned from launching the Intent from GoogleSignInClient.getSignInIntent(...);
// Result returned from launching the Intent from GoogleSignInClient.getSignInIntent(...);
if (requestCode === RC_SIGN_IN) {
// 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.
updateUI(account)
} 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)
updateUI(null)
}
}
fun requestGoogleFITData()
{
var fitnessOptions = FitnessOptions.builder()
.addDataType(DataType.TYPE_STEP_COUNT_DELTA, FitnessOptions.ACCESS_READ)
.addDataType(DataType.AGGREGATE_STEP_COUNT_DELTA, FitnessOptions.ACCESS_READ)
.build()
val account = GoogleSignIn.getAccountForExtension(this, fitnessOptions)
if (!GoogleSignIn.hasPermissions(account, fitnessOptions)) {
GoogleSignIn.requestPermissions(
this, // your activity
GOOGLE_FIT_PERMISSIONS_REQUEST_CODE, // e.g. 1
account,
fitnessOptions)
} else {
accessGoogleFit()
}
}
private fun accessGoogleFit() {
val end = LocalDateTime.now()
val start = end.minusYears(1)
val endSeconds = end.atZone(ZoneId.systemDefault()).toEpochSecond()
val startSeconds = start.atZone(ZoneId.systemDefault()).toEpochSecond()
val readRequest = DataReadRequest.Builder()
.aggregate(DataType.AGGREGATE_STEP_COUNT_DELTA)
.setTimeRange(startSeconds, endSeconds, TimeUnit.SECONDS)
.bucketByTime(1, TimeUnit.DAYS)
.build()
val fitnessOptions = FitnessOptions.builder()
.addDataType(DataType.TYPE_STEP_COUNT_DELTA, FitnessOptions.ACCESS_READ)
.addDataType(DataType.AGGREGATE_STEP_COUNT_DELTA, FitnessOptions.ACCESS_READ)
.build()
val account = GoogleSignIn.getAccountForExtension(this, fitnessOptions)
Fitness.getHistoryClient(this, account)
.readData(readRequest)
.addOnSuccessListener({ response ->
// Use response data here
//Log.i(TAG, "OnSuccess()")
// The aggregate query puts datasets into buckets, so flatten into a
// single list of datasets
for (dataSet in response.buckets.flatMap { it.dataSets }) {
dumpDataSet(dataSet)
}
})
.addOnFailureListener(
{
e -> Log.d(TAG, "OnFailure()", e)
})
}
fun dumpDataSet(dataSet: DataSet) {
Log.i(TAG, "Data returned for Data type: ${dataSet.dataType.name}")
for (dp in dataSet.dataPoints) {
Log.i(TAG,"Data point:")
Log.i(TAG,"\tType: ${dp.dataType.name}")
Log.i(TAG,"\tStart: ${dp.getStartTimeString()}")
Log.i(TAG,"\tEnd: ${dp.getEndTimeString()}")
for (field in dp.dataType.fields) {
Log.i(TAG,"\tField: ${field.name.toString()} Value: ${dp.getValue(field)}")
}
}
}
fun DataPoint.getStartTimeString() = Instant.ofEpochSecond(this.getStartTime(TimeUnit.SECONDS))
.atZone(ZoneId.systemDefault())
.toLocalDateTime().toString()
fun DataPoint.getEndTimeString() = Instant.ofEpochSecond(this.getEndTime(TimeUnit.SECONDS))
.atZone(ZoneId.systemDefault())
.toLocalDateTime().toString()
}
I wanted to integrate google sign In in my app using firebase and I followed all the instructions from enabling google sign In in my firebase console and adding SHA-1 certificate fingerprint and adding the google-services.json file in the app directory.
But whenever I am trying to sign In after selecting the google account the response code is coming out be 0 always and hence unable to sign In.
Here is the Code:-
class SignInActivity : AppCompatActivity() {
private lateinit var googleSignInClient: GoogleSignInClient
private lateinit var auth:FirebaseAuth
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_sign_in)
val gso= GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(getString(R.string.default_web_client_id))
.requestEmail()
.build()
googleSignInClient = GoogleSignIn.getClient(this,gso)
signInButton.setOnClickListener {
resultLauncher.launch(googleSignInClient.signInIntent)
}
}
private var resultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()){result->
Log.i("resultCode",result.resultCode.toString())
val intent=result.data
Log.i("intentData",intent.toString())
if(result.resultCode == Activity.RESULT_OK)
{
Log.i("resultCode","reachedHere")
val task = GoogleSignIn.getSignedInAccountFromIntent(intent)
handleSignInResult(task)
}
else{
Log.i("unsuccessfulSignIN",result.resultCode.toString())
}
}
private fun handleSignInResult(task: Task<GoogleSignInAccount>?) {
try{
val account= task?.getResult(ApiException::class.java)!!
Log.i("account","firebaseAuthWithGoogle:"+account.id)
firebaseAuthWithGoogle(account.idToken!!)
}catch (e : ApiException){
Log.i(ContentValues.TAG, "Google sign in failed", e)
}
}
private fun firebaseAuthWithGoogle(idToken: String) {
signInButton.visibility= View.GONE
progressBar.visibility= View.VISIBLE
val credential= GoogleAuthProvider.getCredential(idToken,null)
GlobalScope.launch(Dispatchers.IO) {
val auth=auth.signInWithCredential(credential).await()
val firebaseUser=auth.user
Log.i("user",firebaseUser.toString())
withContext(Dispatchers.Main){
updateUI(firebaseUser)
}
}
}
private fun updateUI(firebaseUser: FirebaseUser?) {
if(firebaseUser != null)
{
val intent= Intent(this,MainActivity::class.java)
startActivity(intent)
Log.i("intent","Intent Started")
// Toast.makeText(applicationContext,"Sign In Successful",Toast.LENGTH_SHORT).show()
finish()
}
else{
signInButton.visibility= View.VISIBLE
progressBar.visibility=View.GONE
Toast.makeText(this,"Sign In failed", Toast.LENGTH_SHORT).show()
}
}
}
Here is the logcat ( I have highlighted the result code that I logged)
I am very new to android development and this my first time working with firebase
I wanted to add the sign in with google feature of firebase I connected my app to firebase then added the SHA-1 certificate fingerprint and wrote the below code.
Once I click on the sign in button the intent opens a chooser to select a google account but after selecting one account nothing happens even there is no exceptions or error in the logcat.
Code:
class SignInActivity : AppCompatActivity() {
private lateinit var googleSignInClient:GoogleSignInClient
private lateinit var auth:FirebaseAuth
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_sign_in)
val gso= GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(getString(R.string.default_web_client_id))
.requestEmail()
.build()
googleSignInClient = GoogleSignIn.getClient(this,gso)
signInButton.setOnClickListener {
resultLauncher.launch(googleSignInClient.signInIntent)
}
}
private var resultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()){
val intent=it.data
if(it.resultCode == Activity.RESULT_OK)
{
val task = GoogleSignIn.getSignedInAccountFromIntent(intent)
handleSignInResult(task)
}
}
private fun handleSignInResult(task: Task<GoogleSignInAccount>?) {
try{
val account= task?.getResult(ApiException::class.java)!!
Log.i("account","firebaseAuthWithGoogle:"+account.id)
firebaseAuthWithGoogle(account.idToken!!)
}catch (e : ApiException){
Log.i(TAG, "Google sign in failed", e)
}
}
private fun firebaseAuthWithGoogle(idToken: String) {
signInButton.visibility= View.GONE
progressBar.visibility=View.VISIBLE
val credential=GoogleAuthProvider.getCredential(idToken,null)
GlobalScope.launch(Dispatchers.IO) {
val auth=auth.signInWithCredential(credential).await()
val firebaseUser=auth.user
Log.i("user",firebaseUser.toString())
withContext(Dispatchers.Main){
updateUI(firebaseUser)
}
}
}
private fun updateUI(firebaseUser: FirebaseUser?) {
if(firebaseUser != null)
{
val intent=Intent(this,MainActivity::class.java)
startActivity(intent)
Log.i("intent","Intent Started")
// Toast.makeText(applicationContext,"Sign In Successful",Toast.LENGTH_SHORT).show()
finish()
}
else{
signInButton.visibility= View.VISIBLE
progressBar.visibility=View.GONE
Toast.makeText(this,"Sign In failed",Toast.LENGTH_SHORT).show()
}
}
}
Logcat:
I am very new to android development and this is my first time with firebase.
I built an app with google login.
When I connect the device to the android studio the log in work perfect, But when I download my app from google play it fails to connect for some reason...
I tried to find a solution and I couldn't find one...
That's the code ... I would love if anyone has any idea what the problem is..
Thanks for your time!
class firstActivity : AppCompatActivity(){
private lateinit var auth: FirebaseAuth
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
auth = FirebaseAuth.getInstance()
val acct = GoogleSignIn.getLastSignedInAccount(this)
if (acct != null) {
val personName = acct.displayName
val personGivenName = acct.givenName
val personFamilyName = acct.familyName
val personEmail = acct.email
val personId = acct.id
}
val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(getString(R.string.default_web_client_idd))
.requestEmail()
.build()
val mGoogleSignInClient = GoogleSignIn.getClient(this, gso);
signinButtonGoogle.setOnClickListener {
val signInIntent: Intent = mGoogleSignInClient.getSignInIntent()
startActivityForResult(signInIntent, Companion.RC_SIGN_IN)
}
}
public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
GoogleSignInApi.getSignInIntent(...);
if (requestCode == Companion.RC_SIGN_IN) {
val task = GoogleSignIn.getSignedInAccountFromIntent(data)
try {
val account = task.getResult(ApiException::class.java)
firebaseAuthWithGoogle(account!!)
} catch (e: ApiException) {
Toast.makeText(applicationContext, "Google sign in failed", Toast.LENGTH_SHORT)
.show()
}
}
}
private fun firebaseAuthWithGoogle(acct: GoogleSignInAccount) {
val progressDialog = ProgressDialog(this)
progressDialog.setMessage("Connecting...")
progressDialog.setCancelable(false)
progressDialog.show()
val credential = GoogleAuthProvider.getCredential(acct.idToken, null)
auth.signInWithCredential(credential)
.addOnCompleteListener(this) { task ->
if (task.isSuccessful) {
val user = auth.currentUser
signinButtonGoogle.visibility = View.VISIBLE
Handler().postDelayed({ progressDialog.dismiss() }, 0)
val leagueIntent = Intent(this, homeActivity::class.java)
startActivity(leagueIntent)
} else {
Toast.makeText(applicationContext, "Authentication Failed.", Toast.LENGTH_SHORT).show()
signinButtonGoogle.visibility = View.VISIBLE
Handler().postDelayed({ progressDialog.dismiss() }, 0)
}
}
}
companion object {
const val RC_SIGN_IN = 123
}
}
because google play have another SH1 for relase , so you can find it like image and goto firbase manger for your prokect then add new one ,
image
After update from
androidx.camera:camera-core:1.0.0-alpha03
to
androidx.camera:camera-core:1.0.0-alpha06
signatures of methods setTargetAspectRatio (in ImageCaptureConfig.Builder) and takePicture (in ImageCapture) have been changed.
Official documentation and info in web doesn't show how to use new methods (how to specify executor).
Code which broken after update:
...
val captureConfig = ImageCaptureConfig.Builder()
.setTargetAspectRatioCustom(Rational(1, 1)) //this method changed
.setFlashMode(flashMode)
.setLensFacing(lensFacing)
.build()
val capture = ImageCapture(captureConfig)
binding.takeAPhoto.setOnClickListener {
...
val imageFile = createTempFile(System.currentTimeMillis().toString(), ".jpg")
capture.takePicture(imageFile, object : ImageCapture.OnImageSavedListener { //this method also changed
override fun onImageSaved(file: File) {
...
}
override fun onError(useCaseError: ImageCapture.UseCaseError, message: String, cause: Throwable?) {
...
})
}
}
Does anyone have (or know where to find) example of how to use new methods?
Thanks in advance
The official Google Codelabs which obviously have been updated recently use: Executors.newSingleThreadExecutor()
Reference: https://codelabs.developers.google.com/codelabs/camerax-getting-started/#4
Edit: Since #kos's response also makes sense to me, I've added these two official Android docs references:
https://developer.android.com/reference/java/util/concurrent/Executors.html#newSingleThreadExecutor()
https://developer.android.com/reference/java/util/concurrent/Executors.html#newCachedThreadPool()
This way every reader of this topic can make up his/her own mind with respect to executors.
FURTHER EDIT: There are crucial API changes since 1.0.0-alpha07 so I studied some of the docs. There's a GitHub sample showing executor retrieval like so mainExecutor = ContextCompat.getMainExecutor(requireContext())(Source)
If some of you already implemented CameraX and it works fine, I'd definitely wait for the beta release as recommended by Android's release notes
I faced same thing as you are facing. I resolved it from my side.
class MainActivity : AppCompatActivity(), Executor {
private var right: Int = 0
private var bottom: Int = 0
private var left: Int = 0
private var top: Int = 0
private lateinit var preview: Preview
private val REQUEST_CODE_PERMISSIONS = 10
private val REQUIRED_PERMISSIONS = arrayOf(Manifest.permission.CAMERA)
private lateinit var imageCapture: ImageCapture
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if (allPermissionsGranted()) {
viewFinder.post { startCamera() }
} else {
ActivityCompat.requestPermissions(this, REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS)
}
viewFinder.addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ ->
updateTransform()
}
buttonPlus.setOnClickListener {
if (right < 100) {
right += 100
bottom += 100
left += 100
top += 100
val my = Rect(left, top, right, bottom)
preview.zoom(my)
}
}
buttonMinus.setOnClickListener {
if (right > 0) {
right -= 100
bottom -= 100
left -= 100
top -= 100
val my = Rect(left, top, right, bottom)
preview.zoom(my)
}
}
}
#SuppressLint("RestrictedApi")
private fun startCamera() {
val metrics = DisplayMetrics().also { viewFinder.display.getRealMetrics(it) }
val screenAspectRatio = Rational(metrics.widthPixels, metrics.heightPixels)
val previewConfig = PreviewConfig.Builder().apply {
setTargetAspectRatioCustom(screenAspectRatio)
setTargetRotation(viewFinder.display.rotation)
}.build()
preview = Preview(previewConfig)
preview.setOnPreviewOutputUpdateListener {
val parent = viewFinder.parent as ViewGroup
parent.removeView(viewFinder)
parent.addView(viewFinder, 0)
viewFinder.surfaceTexture = it.surfaceTexture
updateTransform()
}
CameraX.bindToLifecycle(this, preview)
captureImage()
}
#SuppressLint("RestrictedApi")
private fun captureImage() {
val imageCaptureConfig = ImageCaptureConfig.Builder()
.apply {
setTargetAspectRatioCustom(Rational(1, 1))
setCaptureMode(ImageCapture.CaptureMode.MIN_LATENCY)
}.build()
imageCapture = ImageCapture(imageCaptureConfig)
CameraX.bindToLifecycle(this, imageCapture)
capture_button.setOnClickListener {
val file = File(this.externalMediaDirs.first(), "${System.currentTimeMillis()}.jpg")
imageCapture.takePicture(file, this, object : ImageCapture.OnImageSavedListener {
override fun onImageSaved(file: File) {
val msg = "Photo capture succeeded: ${file.absolutePath}"
Log.d("CameraXApp", msg)
}
override fun onError(imageCaptureError: ImageCapture.ImageCaptureError, message: String, cause: Throwable?) {
val msg = "Photo capture failed: $message"
Log.e("CameraXApp", msg)
cause?.printStackTrace()
}
})
}
}
override fun execute(command: Runnable) {
command.run()
}
private fun updateTransform() {
val matrix = Matrix()
val centerX = viewFinder.width / 2f
val centerY = viewFinder.height / 2f
val rotationDegrees = when (viewFinder.display.rotation) {
Surface.ROTATION_0 -> 0
Surface.ROTATION_90 -> 90
Surface.ROTATION_180 -> 180
Surface.ROTATION_270 -> 270
else -> return
}
matrix.postRotate(-rotationDegrees.toFloat(), centerX, centerY)
viewFinder.setTransform(matrix)
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
if (requestCode == REQUEST_CODE_PERMISSIONS) {
if (allPermissionsGranted()) {
viewFinder.post { startCamera() }
} else {
Toast.makeText(this, "Permissions not granted by the user.", Toast.LENGTH_SHORT).show()
finish()
}
}
}
private fun allPermissionsGranted() = REQUIRED_PERMISSIONS.all {
ContextCompat.checkSelfPermission(baseContext, it) == PackageManager.PERMISSION_GRANTED
}
override fun onDestroy() {
super.onDestroy()
imageCapture.let {
CameraX.unbind(imageCapture)
}
}
}
And the output is (As I print log in onImageSaved method)
Photo capture succeeded: /storage/emulated/0/Android/media/com.akshay.cameraxzoominoutdemo/1571052301192.jpg
It's working fine for me, try out this.
You can do it like this.
imageCapture.takePicture(file, { it.run() }, object : ImageCapture.OnImageSavedListener {
override fun onImageSaved(file: File) {}
override fun onError(useCaseError: ImageCapture.ImageCaptureError, message: String, cause: Throwable?) {}
})
Here is a change log for the changes in alpha06 : https://developer.android.com/jetpack/androidx/releases/camera
setTargetAspectRatio() method now takes AspectRatio enum with 4_3 or 16_9 value.
takePicture() method takes (file, metadata, executor, imageSavedListener) // could use executor as per your case/need. example is val executor = Executors.newSingleThreadExecutor()
instead of useCase.onPreviewOutputUpdateListener = use useCase.setOnPreviewOutputUpdateListener()
FYI : CameraX will be in Beta in Dec 2019
Inside your click listener call this function/method :
private fun saveImage(){
val file = File(this.externalMediaDirs.first(), "${System.currentTimeMillis()}.jpg")
val fileB = ImageCapture.OutputFileOptions.Builder(file).build()
imageCapture.takePicture(fileB, ContextCompat.getMainExecutor(this), object : ImageCapture.OnImageSavedCallback {
override fun onImageSaved(fileB: ImageCapture.OutputFileResults) {
val msg = "${fileB.savedUri} - ${file.absolutePath} - ${file.toURI()}"
}
override fun onError(imageCaptureError: ImageCaptureException) {
val msg = "Photo capture failed: ${imageCaptureError.toString()}"
}
})
}
And the msg in onImageSaved will contain something like this :
null - /storage/emulated/0/Android/media/com.mua.camx/1607589430984.jpg - file:/storage/emulated/0/Android/media/com.mua.camx/1607589430984.jpg
You have to only run the command as below.
#Override
public void execute(Runnable command) {
command.run(); // <-- THIS IS NEEDED
}
CameraX provides with built-in executors and take picture can be implemented as below:
imgCaptureButton.setOnClickListener(new View.OnClickListener() {
#Override
#SuppressLint("RestrictedApi")
public void onClick(View v) {
imgCap.takePicture(CameraXExecutors.mainThreadExecutor(),new ImageCapture.OnImageCapturedListener() {
#Override
public void onCaptureSuccess(ImageProxy image, int rotationDegrees) {
super.onCaptureSuccess(image, rotationDegrees);
// Play with the Image here.
}
});
}
});
It does not use File to save the image, instead saves the image as a buffer in the memory.