forked from hardcoresushi/DroidFS
Update dependencies & Add camera capture mode settings
This commit is contained in:
parent
ba42938f5a
commit
b65ac79175
@ -56,8 +56,8 @@ dependencies {
|
||||
implementation fileTree(dir: "libs", include: ["*.jar"])
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||
implementation "androidx.core:core-ktx:1.6.0"
|
||||
implementation "androidx.appcompat:appcompat:1.3.0"
|
||||
implementation "androidx.constraintlayout:constraintlayout:2.0.4"
|
||||
implementation "androidx.appcompat:appcompat:1.3.1"
|
||||
implementation "androidx.constraintlayout:constraintlayout:2.1.0"
|
||||
|
||||
implementation "androidx.sqlite:sqlite-ktx:2.1.0"
|
||||
implementation "androidx.preference:preference-ktx:1.1.1"
|
||||
@ -66,14 +66,14 @@ dependencies {
|
||||
implementation "com.github.bumptech.glide:glide:4.12.0"
|
||||
implementation "androidx.biometric:biometric:1.1.0"
|
||||
|
||||
def exoplayer_version = "2.14.1"
|
||||
def exoplayer_version = "2.15.0"
|
||||
implementation "com.google.android.exoplayer:exoplayer-core:$exoplayer_version"
|
||||
implementation "com.google.android.exoplayer:exoplayer-ui:$exoplayer_version"
|
||||
|
||||
def camerax_v1 = "1.1.0-alpha06"
|
||||
def camerax_v1 = "1.1.0-alpha08"
|
||||
implementation "androidx.camera:camera-camera2:$camerax_v1"
|
||||
implementation "androidx.camera:camera-lifecycle:$camerax_v1"
|
||||
def camerax_v2 = "1.0.0-alpha26"
|
||||
def camerax_v2 = "1.0.0-alpha28"
|
||||
implementation "androidx.camera:camera-view:$camerax_v2"
|
||||
implementation "androidx.camera:camera-extensions:$camerax_v2"
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ import android.hardware.camera2.CameraManager
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.text.InputType
|
||||
import android.util.DisplayMetrics
|
||||
import android.util.Size
|
||||
import android.view.MotionEvent
|
||||
import android.view.ScaleGestureDetector
|
||||
@ -23,7 +22,8 @@ import android.widget.RelativeLayout
|
||||
import android.widget.Toast
|
||||
import androidx.camera.camera2.interop.Camera2CameraInfo
|
||||
import androidx.camera.core.*
|
||||
import androidx.camera.extensions.HdrImageCaptureExtender
|
||||
import androidx.camera.extensions.ExtensionMode
|
||||
import androidx.camera.extensions.ExtensionsManager
|
||||
import androidx.camera.lifecycle.ProcessCameraProvider
|
||||
import androidx.core.content.ContextCompat
|
||||
import sushi.hardcore.droidfs.adapters.DialogSingleChoiceAdapter
|
||||
@ -35,8 +35,7 @@ import java.io.ByteArrayInputStream
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
import java.util.concurrent.ExecutorService
|
||||
import java.util.concurrent.Executors
|
||||
import java.util.concurrent.Executor
|
||||
|
||||
class CameraActivity : BaseActivity(), SensorOrientationListener.Listener {
|
||||
companion object {
|
||||
@ -64,10 +63,16 @@ class CameraActivity : BaseActivity(), SensorOrientationListener.Listener {
|
||||
private lateinit var outputDirectory: String
|
||||
private lateinit var fileName: String
|
||||
private var isFinishingIntentionally = false
|
||||
private lateinit var cameraExecutor: ExecutorService
|
||||
private var permissionsGranted = false
|
||||
private lateinit var executor: Executor
|
||||
private lateinit var cameraProvider: ProcessCameraProvider
|
||||
private lateinit var extensionsManager: ExtensionsManager
|
||||
private val cameraPreview = Preview.Builder().build()
|
||||
private var imageCapture: ImageCapture? = null
|
||||
private var resolutions: Array<Size>? = null
|
||||
private var camera: Camera? = null
|
||||
private var resolutions: List<Size>? = null
|
||||
private var currentResolutionIndex: Int = 0
|
||||
private var captureMode = ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY
|
||||
private var isBackCamera = true
|
||||
private lateinit var binding: ActivityCameraBinding
|
||||
|
||||
@ -81,21 +86,61 @@ class CameraActivity : BaseActivity(), SensorOrientationListener.Listener {
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED){
|
||||
setupCamera()
|
||||
permissionsGranted = true
|
||||
} else {
|
||||
requestPermissions(arrayOf(Manifest.permission.CAMERA), CAMERA_PERMISSION_REQUEST_CODE)
|
||||
}
|
||||
} else {
|
||||
setupCamera()
|
||||
permissionsGranted = true
|
||||
}
|
||||
|
||||
cameraExecutor = Executors.newSingleThreadExecutor()
|
||||
executor = ContextCompat.getMainExecutor(this)
|
||||
cameraPreview.setSurfaceProvider(binding.cameraPreview.surfaceProvider)
|
||||
ProcessCameraProvider.getInstance(this).apply {
|
||||
addListener({
|
||||
cameraProvider = get()
|
||||
setupCamera()
|
||||
}, executor)
|
||||
}
|
||||
ExtensionsManager.getInstance(this).apply {
|
||||
addListener({
|
||||
extensionsManager = get()
|
||||
setupCamera()
|
||||
}, executor)
|
||||
}
|
||||
|
||||
binding.imageCaptureMode.setOnClickListener {
|
||||
val currentIndex = if (captureMode == ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY) {
|
||||
0
|
||||
} else {
|
||||
1
|
||||
}
|
||||
ColoredAlertDialogBuilder(this)
|
||||
.setTitle(R.string.camera_optimization)
|
||||
.setSingleChoiceItems(DialogSingleChoiceAdapter(this, arrayOf(R.string.maximize_quality, R.string.minimize_latency).map { getString(it) }), currentIndex) { dialog, which ->
|
||||
val resId: Int
|
||||
val newCaptureMode = if (which == 0) {
|
||||
resId = R.drawable.icon_high_quality
|
||||
ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY
|
||||
} else {
|
||||
resId = R.drawable.icon_speed
|
||||
ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY
|
||||
}
|
||||
if (newCaptureMode != captureMode) {
|
||||
captureMode = newCaptureMode
|
||||
binding.imageCaptureMode.setImageResource(resId)
|
||||
setupCamera()
|
||||
}
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.show()
|
||||
}
|
||||
binding.imageRatio.setOnClickListener {
|
||||
resolutions?.let {
|
||||
ColoredAlertDialogBuilder(this)
|
||||
.setTitle(R.string.choose_resolution)
|
||||
.setSingleChoiceItems(DialogSingleChoiceAdapter(this, it.map { size -> size.toString() }.toTypedArray()), currentResolutionIndex) { dialog, which ->
|
||||
.setSingleChoiceItems(DialogSingleChoiceAdapter(this, it.map { size -> size.toString() }), currentResolutionIndex) { dialog, which ->
|
||||
setupCamera(resolutions!![which])
|
||||
dialog.dismiss()
|
||||
currentResolutionIndex = which
|
||||
@ -151,10 +196,10 @@ class CameraActivity : BaseActivity(), SensorOrientationListener.Listener {
|
||||
}
|
||||
binding.imageCameraSwitch.setOnClickListener {
|
||||
isBackCamera = if (isBackCamera) {
|
||||
binding.imageCameraSwitch.setImageResource(R.drawable.icon_camera_front)
|
||||
binding.imageCameraSwitch.setImageResource(R.drawable.icon_camera_back)
|
||||
false
|
||||
} else {
|
||||
binding.imageCameraSwitch.setImageResource(R.drawable.icon_camera_back)
|
||||
binding.imageCameraSwitch.setImageResource(R.drawable.icon_camera_front)
|
||||
true
|
||||
}
|
||||
setupCamera()
|
||||
@ -165,8 +210,8 @@ class CameraActivity : BaseActivity(), SensorOrientationListener.Listener {
|
||||
|
||||
val scaleGestureDetector = ScaleGestureDetector(this, object : ScaleGestureDetector.SimpleOnScaleGestureListener(){
|
||||
override fun onScale(detector: ScaleGestureDetector): Boolean {
|
||||
val currentZoomRatio = imageCapture?.camera?.cameraInfo?.zoomState?.value?.zoomRatio ?: 0F
|
||||
imageCapture?.camera?.cameraControl?.setZoomRatio(currentZoomRatio*detector.scaleFactor)
|
||||
val currentZoomRatio = camera?.cameraInfo?.zoomState?.value?.zoomRatio ?: 0F
|
||||
camera?.cameraControl?.setZoomRatio(currentZoomRatio*detector.scaleFactor)
|
||||
return true
|
||||
}
|
||||
})
|
||||
@ -178,7 +223,7 @@ class CameraActivity : BaseActivity(), SensorOrientationListener.Listener {
|
||||
val factory = binding.cameraPreview.meteringPointFactory
|
||||
val point = factory.createPoint(event.x, event.y)
|
||||
val action = FocusMeteringAction.Builder(point).build()
|
||||
imageCapture?.camera?.cameraControl?.startFocusAndMetering(action)
|
||||
camera?.cameraControl?.startFocusAndMetering(action)
|
||||
true
|
||||
}
|
||||
MotionEvent.ACTION_MOVE -> scaleGestureDetector.onTouchEvent(event)
|
||||
@ -191,7 +236,10 @@ class CameraActivity : BaseActivity(), SensorOrientationListener.Listener {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||
when (requestCode) {
|
||||
CAMERA_PERMISSION_REQUEST_CODE -> if (grantResults.size == 1) {
|
||||
if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
|
||||
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
permissionsGranted = true
|
||||
setupCamera()
|
||||
} else {
|
||||
ColoredAlertDialogBuilder(this)
|
||||
.setTitle(R.string.error)
|
||||
.setMessage(R.string.camera_perm_needed)
|
||||
@ -200,72 +248,62 @@ class CameraActivity : BaseActivity(), SensorOrientationListener.Listener {
|
||||
isFinishingIntentionally = true
|
||||
finish()
|
||||
}.show()
|
||||
} else {
|
||||
setupCamera()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun adaptPreviewSize(resolution: Size) {
|
||||
val metrics = DisplayMetrics()
|
||||
windowManager.defaultDisplay.getMetrics(metrics)
|
||||
//resolution.width and resolution.height seem to be inverted
|
||||
val width = resolution.height
|
||||
val height = resolution.width
|
||||
binding.cameraPreview.layoutParams = if (metrics.widthPixels < width){
|
||||
val screenWidth = resources.displayMetrics.widthPixels
|
||||
binding.cameraPreview.layoutParams = if (screenWidth < resolution.width) {
|
||||
RelativeLayout.LayoutParams(
|
||||
metrics.widthPixels,
|
||||
(height * (metrics.widthPixels.toFloat() / width)).toInt()
|
||||
screenWidth,
|
||||
(resolution.height * (screenWidth.toFloat() / resolution.width)).toInt()
|
||||
)
|
||||
} else {
|
||||
RelativeLayout.LayoutParams(width, height)
|
||||
RelativeLayout.LayoutParams(resolution.width, resolution.height)
|
||||
}
|
||||
(binding.cameraPreview.layoutParams as RelativeLayout.LayoutParams).addRule(RelativeLayout.CENTER_IN_PARENT)
|
||||
}
|
||||
|
||||
private fun setupCamera(resolution: Size? = null){
|
||||
val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
|
||||
cameraProviderFuture.addListener({
|
||||
val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()
|
||||
val preview = Preview.Builder()
|
||||
.build()
|
||||
.also {
|
||||
it.setSurfaceProvider(binding.cameraPreview.surfaceProvider)
|
||||
if (permissionsGranted && ::extensionsManager.isInitialized && ::cameraProvider.isInitialized) {
|
||||
imageCapture = ImageCapture.Builder()
|
||||
.setCaptureMode(captureMode)
|
||||
.setFlashMode(imageCapture?.flashMode ?: ImageCapture.FLASH_MODE_AUTO)
|
||||
.apply {
|
||||
resolution?.let {
|
||||
setTargetResolution(it)
|
||||
}
|
||||
}
|
||||
val builder = ImageCapture.Builder()
|
||||
.setFlashMode(ImageCapture.FLASH_MODE_AUTO)
|
||||
resolution?.let {
|
||||
builder.setTargetResolution(it)
|
||||
}
|
||||
val hdrImageCapture = HdrImageCaptureExtender.create(builder)
|
||||
val cameraSelector = if (isBackCamera){ CameraSelector.DEFAULT_BACK_CAMERA } else { CameraSelector.DEFAULT_FRONT_CAMERA }
|
||||
.build()
|
||||
|
||||
if (hdrImageCapture.isExtensionAvailable(cameraSelector)){
|
||||
hdrImageCapture.enableExtension(cameraSelector)
|
||||
var cameraSelector = if (isBackCamera){ CameraSelector.DEFAULT_BACK_CAMERA } else { CameraSelector.DEFAULT_FRONT_CAMERA }
|
||||
if (extensionsManager.isExtensionAvailable(cameraProvider, cameraSelector, ExtensionMode.HDR)) {
|
||||
cameraSelector = extensionsManager.getExtensionEnabledCameraSelector(cameraProvider, cameraSelector, ExtensionMode.HDR)
|
||||
}
|
||||
|
||||
imageCapture = builder.build()
|
||||
|
||||
cameraProvider.unbindAll()
|
||||
val camera = cameraProvider.bindToLifecycle(this, cameraSelector, preview, imageCapture)
|
||||
camera = cameraProvider.bindToLifecycle(this, cameraSelector, cameraPreview, imageCapture)
|
||||
|
||||
adaptPreviewSize(imageCapture!!.attachedSurfaceResolution!!)
|
||||
adaptPreviewSize(resolution ?: imageCapture!!.attachedSurfaceResolution!!.swap())
|
||||
|
||||
val info = Camera2CameraInfo.from(camera.cameraInfo)
|
||||
val cameraManager = getSystemService(Context.CAMERA_SERVICE) as CameraManager
|
||||
val characteristics = cameraManager.getCameraCharacteristics(info.cameraId)
|
||||
characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)?.let { streamConfigurationMap ->
|
||||
resolutions = streamConfigurationMap.getOutputSizes(imageCapture!!.imageFormat)
|
||||
if (resolutions == null) {
|
||||
val info = Camera2CameraInfo.from(camera!!.cameraInfo)
|
||||
val cameraManager = getSystemService(Context.CAMERA_SERVICE) as CameraManager
|
||||
val characteristics = cameraManager.getCameraCharacteristics(info.cameraId)
|
||||
characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)?.let { streamConfigurationMap ->
|
||||
resolutions = streamConfigurationMap.getOutputSizes(imageCapture!!.imageFormat).map { it.swap() }
|
||||
}
|
||||
}
|
||||
}, ContextCompat.getMainExecutor(this))
|
||||
}
|
||||
}
|
||||
|
||||
private fun takePhoto() {
|
||||
val imageCapture = imageCapture ?: return
|
||||
val outputBuff = ByteArrayOutputStream()
|
||||
val outputOptions = ImageCapture.OutputFileOptions.Builder(outputBuff).build()
|
||||
imageCapture.takePicture(outputOptions, ContextCompat.getMainExecutor(this), object : ImageCapture.OnImageSavedCallback {
|
||||
imageCapture.takePicture(outputOptions, executor, object : ImageCapture.OnImageSavedCallback {
|
||||
override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {
|
||||
binding.takePhotoButton.onPhotoTaken()
|
||||
if (gocryptfsVolume.importFile(ByteArrayInputStream(outputBuff.toByteArray()), PathUtils.pathJoin(outputDirectory, fileName))){
|
||||
@ -313,7 +351,6 @@ class CameraActivity : BaseActivity(), SensorOrientationListener.Listener {
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
cameraExecutor.shutdown()
|
||||
if (!isFinishingIntentionally) {
|
||||
gocryptfsVolume.close()
|
||||
RestrictedFileProvider.wipeAll(this)
|
||||
@ -366,3 +403,7 @@ class CameraActivity : BaseActivity(), SensorOrientationListener.Listener {
|
||||
previousOrientation = reversedOrientation
|
||||
}
|
||||
}
|
||||
|
||||
private fun Size.swap(): Size {
|
||||
return Size(height, width)
|
||||
}
|
@ -9,7 +9,7 @@ import android.widget.CheckedTextView
|
||||
import sushi.hardcore.droidfs.R
|
||||
import sushi.hardcore.droidfs.widgets.ThemeColor
|
||||
|
||||
class DialogSingleChoiceAdapter(private val context: Context, private val entries: Array<String>): BaseAdapter() {
|
||||
class DialogSingleChoiceAdapter(private val context: Context, private val entries: List<String>): BaseAdapter() {
|
||||
private val inflater: LayoutInflater = LayoutInflater.from(context)
|
||||
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
|
||||
val view: View = convertView ?: inflater.inflate(R.layout.adapter_colored_dialog_single_choice, parent, false)
|
||||
|
@ -486,7 +486,7 @@ open class BaseExplorerActivity : BaseActivity() {
|
||||
R.id.sort -> {
|
||||
ColoredAlertDialogBuilder(this)
|
||||
.setTitle(R.string.sort_order)
|
||||
.setSingleChoiceItems(DialogSingleChoiceAdapter(this, sortOrderEntries), currentSortOrderIndex) { dialog, which ->
|
||||
.setSingleChoiceItems(DialogSingleChoiceAdapter(this, sortOrderEntries.toList()), currentSortOrderIndex) { dialog, which ->
|
||||
currentSortOrderIndex = which
|
||||
setCurrentPath(currentDirectoryPath)
|
||||
dialog.dismiss()
|
||||
|
@ -1,10 +1,7 @@
|
||||
package sushi.hardcore.droidfs.file_viewers
|
||||
|
||||
import android.view.WindowManager
|
||||
import com.google.android.exoplayer2.ExoPlaybackException
|
||||
import com.google.android.exoplayer2.MediaItem
|
||||
import com.google.android.exoplayer2.Player
|
||||
import com.google.android.exoplayer2.SimpleExoPlayer
|
||||
import com.google.android.exoplayer2.*
|
||||
import com.google.android.exoplayer2.extractor.ExtractorsFactory
|
||||
import com.google.android.exoplayer2.extractor.flac.FlacExtractor
|
||||
import com.google.android.exoplayer2.extractor.mkv.MatroskaExtractor
|
||||
@ -58,15 +55,13 @@ abstract class MediaPlayer: FileViewerActivity() {
|
||||
onPlayerReady()
|
||||
}
|
||||
}
|
||||
override fun onPlayerError(error: ExoPlaybackException) {
|
||||
if (error.type == ExoPlaybackException.TYPE_SOURCE){
|
||||
ColoredAlertDialogBuilder(this@MediaPlayer)
|
||||
.setTitle(R.string.error)
|
||||
.setMessage(R.string.playing_failed)
|
||||
.setCancelable(false)
|
||||
.setPositiveButton(R.string.ok) { _, _ -> goBackToExplorer()}
|
||||
.show()
|
||||
}
|
||||
override fun onPlayerError(error: PlaybackException) {
|
||||
ColoredAlertDialogBuilder(this@MediaPlayer)
|
||||
.setTitle(R.string.error)
|
||||
.setMessage(getString(R.string.playing_failed, error.errorCodeName))
|
||||
.setCancelable(false)
|
||||
.setPositiveButton(R.string.ok) { _, _ -> goBackToExplorer()}
|
||||
.show()
|
||||
}
|
||||
override fun onIsPlayingChanged(isPlaying: Boolean) {
|
||||
if (isPlaying){
|
||||
|
@ -19,7 +19,7 @@ class ColoredListPreference: ListPreference {
|
||||
override fun onClick() {
|
||||
ColoredAlertDialogBuilder(context)
|
||||
.setTitle(title)
|
||||
.setSingleChoiceItems(DialogSingleChoiceAdapter(context, entries.map { s -> s.toString() }.toTypedArray()), entryValues.indexOf(getPersistedString(value))) { dialog, which ->
|
||||
.setSingleChoiceItems(DialogSingleChoiceAdapter(context, entries.map { s -> s.toString() }), entryValues.indexOf(getPersistedString(value))) { dialog, which ->
|
||||
dialog.dismiss()
|
||||
summary = entries[which].toString()
|
||||
persistString(entryValues[which].toString())
|
||||
|
5
app/src/main/res/drawable/icon_high_quality.xml
Normal file
5
app/src/main/res/drawable/icon_high_quality.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M19,4L5,4c-1.11,0 -2,0.9 -2,2v12c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2L21,6c0,-1.1 -0.9,-2 -2,-2zM11,15L9.5,15v-2h-2v2L6,15L6,9h1.5v2.5h2L9.5,9L11,9v6zM18,14c0,0.55 -0.45,1 -1,1h-0.75v1.5h-1.5L14.75,15L14,15c-0.55,0 -1,-0.45 -1,-1v-4c0,-0.55 0.45,-1 1,-1h3c0.55,0 1,0.45 1,1v4zM14.5,13.5h2v-3h-2v3z"/>
|
||||
</vector>
|
5
app/src/main/res/drawable/icon_speed.xml
Normal file
5
app/src/main/res/drawable/icon_speed.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M20.38,8.57l-1.23,1.85a8,8 0,0 1,-0.22 7.58L5.07,18A8,8 0,0 1,15.58 6.85l1.85,-1.23A10,10 0,0 0,3.35 19a2,2 0,0 0,1.72 1h13.85a2,2 0,0 0,1.74 -1,10 10,0 0,0 -0.27,-10.44zM10.59,15.41a2,2 0,0 0,2.83 0l5.66,-8.49 -8.49,5.66a2,2 0,0 0,0 2.83z"/>
|
||||
</vector>
|
@ -17,6 +17,16 @@
|
||||
android:layout_height="40dp"
|
||||
android:layout_marginTop="20dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image_capture_mode"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:src="@drawable/icon_high_quality"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/image_ratio"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image_ratio"
|
||||
android:layout_width="30dp"
|
||||
@ -24,7 +34,7 @@
|
||||
android:src="@drawable/icon_aspect_ratio"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/image_timer"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/image_capture_mode"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ImageView
|
||||
|
@ -116,7 +116,7 @@
|
||||
<string name="video">Vídeo</string>
|
||||
<string name="audio">Áudio</string>
|
||||
<string name="media_player_prepare_failed">Falha ao abrir o reprodutor de mídia.</string>
|
||||
<string name="playing_failed">Falha ao reproduzir este arquivo.</string>
|
||||
<string name="playing_failed">Falha ao reproduzir este arquivo: %s</string>
|
||||
<string name="text">Texto</string>
|
||||
<string name="save_failed">Falha ao salvar</string>
|
||||
<string name="file_saved">Arquivo salvo!</string>
|
||||
|
@ -117,7 +117,7 @@
|
||||
<string name="video">Видео</string>
|
||||
<string name="audio">Аудио</string>
|
||||
<string name="media_player_prepare_failed">Невозможно инициализировать медиапроигрыватель.</string>
|
||||
<string name="playing_failed">Невозможно воспроизвести файл.</string>
|
||||
<string name="playing_failed">Невозможно воспроизвести файл: %s</string>
|
||||
<string name="text">Текст</string>
|
||||
<string name="save_failed">Невозможно сохранить.</string>
|
||||
<string name="file_saved">Файл сохранён!</string>
|
||||
|
@ -118,7 +118,7 @@
|
||||
<string name="video">Video</string>
|
||||
<string name="audio">Audio</string>
|
||||
<string name="media_player_prepare_failed">Failed to initialize the media player.</string>
|
||||
<string name="playing_failed">Failed to play this file.</string>
|
||||
<string name="playing_failed">Failed to play this file: %s</string>
|
||||
<string name="text">Text</string>
|
||||
<string name="save_failed">Save failed</string>
|
||||
<string name="file_saved">File saved !</string>
|
||||
@ -202,4 +202,7 @@
|
||||
<string name="cut">Cut</string>
|
||||
<string name="map_folders">Map folders</string>
|
||||
<string name="map_folders_summary">Recursively map folders to calculate their sizes (you should disable this when opening large volumes)</string>
|
||||
<string name="camera_optimization">Camera optimization</string>
|
||||
<string name="maximize_quality">Maximize quality</string>
|
||||
<string name="minimize_latency">Minimize latency</string>
|
||||
</resources>
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
buildscript {
|
||||
ext.kotlin_version = "1.5.20"
|
||||
ext.kotlin_version = "1.5.30"
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
|
5
gradle/wrapper/gradle-wrapper.properties
vendored
5
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,5 +1,6 @@
|
||||
#Wed Sep 01 11:25:55 UTC 2021
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
Loading…
Reference in New Issue
Block a user