// 2023-07-01: Amazon addition. package com.camerakit.amazonivs.sample // End of Amazon addition. import android.Manifest import android.graphics.Bitmap import android.graphics.Rect import android.os.Build import android.os.Bundle import android.util.Log import android.view.GestureDetector import android.view.MotionEvent import android.view.View import android.view.ViewGroup import android.widget.ImageButton import android.widget.Button import android.widget.ImageView import android.widget.LinearLayout import android.widget.TextView import android.widget.Toast import androidx.annotation.RequiresApi import androidx.appcompat.app.AppCompatActivity import androidx.constraintlayout.motion.widget.MotionLayout import androidx.constraintlayout.motion.widget.TransitionAdapter import androidx.core.view.doOnLayout import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.RecyclerView // 2023-03-27: Amazon addition. import com.amazonaws.ivs.broadcast.* // End of Amazon addition. import com.bumptech.glide.Glide import com.snap.camerakit.common.Consumer import com.snap.camerakit.lenses.LensesComponent import com.snap.camerakit.lenses.whenHasSome import com.snap.camerakit.support.camera.AllowsSnapshotCapture import com.snap.camerakit.support.camera.AllowsVideoCapture import com.snap.camerakit.support.camerax.CameraXImageProcessorSource import com.snap.camerakit.support.permissions.HeadlessFragmentPermissionRequester import com.snap.camerakit.support.widget.SnapButtonView import java.io.Closeable import java.io.File import java.lang.ref.WeakReference import java.util.concurrent.Executors import com.snap.camerakit.* // 2023-03-27: Amazon addition. private const val TAG = "AmazonIVS" // End of Amazon addition. /** * A simple activity which demonstrates how to use Camera Kit with custom layout for preview as well as custom lenses carousel. */ class MainActivity : AppCompatActivity(R.layout.activity_main) { private lateinit var cameraKitSession: Session private lateinit var imageProcessorSource: CameraXImageProcessorSource private lateinit var rootContainer: MotionLayout private lateinit var liveCameraContainer: ViewGroup private lateinit var previewGestureHandler: View private lateinit var selectedLensContainer: ViewGroup private lateinit var selectedLensNameView: TextView private lateinit var selectedLensIcon: ImageView private lateinit var lensesAdapter: LensesAdapter private lateinit var lensesListContainer: LinearLayout private var isCameraFacingFront = true private val processorExecutor = Executors.newSingleThreadExecutor() private var permissionRequest: Closeable? = null private var videoRecording: Closeable? = null private var lensRepositorySubscription: Closeable? = null // 2023-03-27: Amazon addition. var broadcastSession: BroadcastSession? = null // End of Amazon addition. private var imagePreviewView: ImagePreviewView? = null // 2023-03-27: Amazon addition. private var broadcastListener: BroadcastSession.Listener = object : BroadcastSession.Listener() { override fun onStateChanged(state: BroadcastSession.State) { } override fun onError(exception: BroadcastException) { } override fun onAnalyticsEvent(name: String, properties: String) { } override fun onDeviceAdded(descriptor: Device.Descriptor) { } override fun onDeviceRemoved(descriptor: Device.Descriptor) { } override fun onAudioStats(peak: Double, rms: Double) { } override fun onTransmissionStatsChanged(statistics: TransmissionStats?) { } } // End of Amazon addition. @RequiresApi(Build.VERSION_CODES.M) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // viewModel = // ViewModelProvider(this).get(CustomSourceViewModel::class.java) // Checking if Camera Kit is supported on this device or not. if (!supported(this)) { Toast.makeText(this, getString(R.string.camera_kit_not_supported), Toast.LENGTH_SHORT).show() finish() return } liveCameraContainer = findViewById(R.id.camera_preview_container) selectedLensContainer = findViewById(R.id.selected_lens_container) selectedLensIcon = findViewById(R.id.selected_lens_icon) selectedLensNameView = findViewById(R.id.selected_lens_name) rootContainer = findViewById(R.id.root_container).apply { doOnLayout { view -> val dimensionRatio = "W,${view.width}:${view.height}" rootContainer.getConstraintSet(R.id.lenses_selector_collapsed).apply { setDimensionRatio(R.id.camera_preview_container, dimensionRatio) } rootContainer.getConstraintSet(R.id.lenses_selector_expanded).apply { setDimensionRatio(R.id.camera_preview_container, dimensionRatio) } } } lensesListContainer = findViewById(R.id.lenses_list_container) val tapGestureDetector = GestureDetector( this, object : GestureDetector.SimpleOnGestureListener() { override fun onDoubleTap(event: MotionEvent): Boolean { flipCamera() return super.onDoubleTap(event) } override fun onSingleTapConfirmed(e: MotionEvent): Boolean { rootContainer.transitionToStart() return super.onSingleTapConfirmed(e) } } ) previewGestureHandler = findViewById(R.id.preview_gesture_handler).apply { setOnTouchListener { _, event -> tapGestureDetector.onTouchEvent(event) when (event.action) { MotionEvent.ACTION_UP -> performClick() } true } } // App can either use Camera Kit's CameraXImageProcessorSource (which is part of the :support-camerax // dependency) or their own input/output and later attach it to the Camera Kit session. imageProcessorSource = CameraXImageProcessorSource( context = this, lifecycleOwner = this, executorService = processorExecutor, videoOutputDirectory = cacheDir ) // App can either use Camera Kit's CameraLayout for easy integration or define a custom // layout like in this case. For custom layout, app needs to just attach the view to Camera // Kit Session. Also, App Id and API token can be passed dynamically through Session APIs like in this // case (recommended) or it can be hardcoded in AndroidManifest.xml file. cameraKitSession = Session(this) { apiToken(BuildConfig.CAMERA_KIT_API_TOKEN) applicationId(BuildConfig.APPLICATION_ID) imageProcessorSource(imageProcessorSource) attachTo(findViewById(R.id.camera_kit_stub)) safeRenderAreaProcessorSource(SafeRenderAreaProcessorSource(this@MainActivity)) configureLenses { lb -> // When CameraKit is configured to manage its own views by providing a view stub, // lenses touch handling might consume all events due to the fact that it needs to perform gesture // detection internally. If application needs to handle gestures on top of it then LensesComponent // provides a way to dispatch all touch events unhandled by active lens back. lb.dispatchTouchEventsTo(previewGestureHandler) } } getOsPermissions() // This block demonstrates how to query the repository to get all Lenses from a Camera Kit // group. You can query from multiple groups or pre-fetch all Lenses before even user opens // the Camera Kit integration. Camera Kit APIs are thread safe - so it's safe to call them // from here. lensRepositorySubscription = cameraKitSession.lenses.repository.observe( LensesComponent.Repository.QueryCriteria.Available(setOf(BuildConfig.LENS_GROUP_ID_TEST)) ) { result -> result.whenHasSome { lenses -> runOnUiThread { lensesAdapter.submitList(lenses) } applyLens(lenses.elementAt(14)) } } findViewById(R.id.capture_button).apply { addPreviewFeature() } findViewById(R.id.camera_flip_button).apply { setOnClickListener { flipCamera() } } findViewById(R.id.button_cancel_effect).apply { setOnClickListener { clearLenses() } } findViewById(R.id.lenses_list).apply { lensesAdapter = LensesAdapter { selectedLens -> applyLens(selectedLens) } layoutManager = GridLayoutManager(this@MainActivity, 3) adapter = lensesAdapter } findViewById