-
Notifications
You must be signed in to change notification settings - Fork 6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
App foundation: introducing CameraX #23
Conversation
…ntation in BackgroundSurfaceManager
…ation code for readability
…d SurfaceFragmentHandler
…e and simplified distinction in BackgroundSurfaceManager
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good overall and works well 👍 Just a few comments, some are just Kotlin FYIs as we discussed 😀
} | ||
|
||
fun getCurrentVideoFile(): File? { | ||
return camera2BasicHandler.currentFile | ||
return cameraBasicHandler.currentFile |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some weird indentation showed up here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 addressed in: bf3b76a
// the photoEditorView layout has been recreated so, re-assign its TextureView | ||
cameraBasicHandler.textureView = photoEditorView.textureView | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm probably missing something - could you explain why in the CAMERAX
case we don't need to add a texture listener here as in the other cases?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Excellent question! It's all taken care of by the lifecycle binding CameraX uses so, we only need to tell the CameraX use case what we want from it, for example start recording video (or stopping an in-progress recording), or starting feeding the surface with the images being buffered from the camera preview, etc.
Copying from the referenced documentation in the link above for easy reading:
Instead of an application placing specific start and stop method calls in onResume() and onPause(), the application specifies a lifecycle to associate the camera with, using CameraX.bindToLifecycle(). The startup, shutdown, and production of data are governed by the specified Android Architecture Lifecycle. That lifecycle then informs CameraX when to configure the camera capture session and ensures camera state changes appropriately to match lifecycle transitions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah I follow - I don't think it clicked for me that the texture listener hook was for lifecycle management. Thanks for the details, super helpful 👍
@@ -23,11 +29,16 @@ class BackgroundSurfaceManager( | |||
private val savedInstanceState: Bundle?, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The activity
val here in the constructor seems to be unused.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -42,3 +42,40 @@ dependencies { | |||
androidTestImplementation 'androidx.test:runner:1.2.0' | |||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' | |||
} | |||
|
|||
android.buildTypes.all { buildType -> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All of this looks good, though I think we should take care of adding gradle.properties
to .gitignore
sooner than later and add a gradle.properties-example
file. I'll open an issue to track that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Opened: #27.
def inputFile = checkGradlePropertiesFile() | ||
def properties = loadPropertiesFromFile(inputFile) | ||
properties.any { property -> | ||
if (property.key.toLowerCase().startsWith("portkey.use.")) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting - in WPAndroid we don't have this handling and instead just use BuildConfig.VALUE.toBoolean()
when accessing it. This is probably better 😀
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TBH that was a TIL for me as well when I introduced / borrowed these scripts :D
// setOnVideoSizeChangedListener(this) | ||
setAudioStreamType(AudioManager.STREAM_MUSIC) | ||
start() | ||
if (currentFile != null && currentFile!!.exists()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can Kotlinify this a bit and fix a nullability warning in the code (the call is actually safe but the IDE doesn't know that):
currentFile?.takeIf { it.exists() }?.let { file ->
...
val inputStream = FileInputStream(file)
...
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice! addressed in e0f25fa (plus removed some commented code)
Also TIL:
the call is actually safe but the IDE doesn't know that
// val descriptor = assetManager!!.openFd("small.mp4") | ||
val inputStream = FileInputStream(currentFile) | ||
mediaPlayer = MediaPlayer().apply { | ||
setDataSource(inputStream.getFD()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Kotlinification note, not a blocker)
This can use property access syntax: inputStream.fd
.
photoeditor/build.gradle
Outdated
// CameraX core library | ||
def camerax_version = "1.0.0-alpha04" | ||
// CameraX view library | ||
def camerax_view_version = "1.0.0-alpha01" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one and the one below seems to be unused.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
addressed in 26767fc
permissions: Array<String>, | ||
grantResults: IntArray | ||
) { | ||
if (!PermissionUtils.allRequiredPermissionsGranted(activity!!)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can remove the !!
force unwrap here by wrapping the whole function body in a null check:
activity?.let { activity ->
...
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ended up removing this entirely in bbcf4df, to match the same thing we did in e2fe8ee , related comment here: #22 (comment)
Awesome @mzorz, ! |
NOTE: please after reviewing, review and merge #25 first before merging this one 👍
This PR introduces Android Jetpack's Camera X. It's important to note the
VideoCapture
use case is still under theRestrictedApi
annotation, so using it herecarefullyhoping they'll make it public soon.This PR also introduces some simplification of the abstraction of a
VideoRecorderFragment
, which has the capabilities implemented by theinterface VideoRecorderHandler
:startRecordingVideo()
stopRecordingVideo()
and
interface SurfaceFragmentHandler
:activate()
deactivate()
This way, we kept both the
Camera2
API implementation inCamera2BasicHandling
class, and encapsulated theCameraX
API implementation within theCameraXBasicHandling
class, both of which are nothing else but instances of the aforementionedVideoRecorderFragment
.This also led to a simplification in the
BackgroundSurfaceManager
code, which is now easier to read and should pretty much take care of all the basic background surfaces handling such as turning the camera on/off, start/stop recording, and switch background surfaces (static, video player, camera preview).Also this PR introduces a
BuildConfig.USE_CAMERAX
flag ingradle.properties
, which is used in order to use one API or the other depending on this setting.This way, should we need to fall back to the stable Camera2 API we can do so, by just turning the flag.
This PR introduces only the following two use cases, to just be able to match the current functionality in the app:
In a follow up PR we'll implement the still image capture use case as well (it's coded in our Camera2 fragment handler implementation as well, but needs to be wired up).
Note there of course may be differences in handling to our own implementation, but we'll be able to choose among each of the alternatives.
To Test
Camera preview
. Check you see the camera view.Camera preview
option in the overflow menu again to START recording (note no indication that recording started is shown so, you'll have to believe)Camera preview
option in the overflow menu a third time to STOP recording. This will silently save the original recording file.Save
option (last option in the menu)