i make program for record audio for android but i find MediaRecorder() Deprecated
kotlin code
package noteapp.notesnotesnotescairo.mynoteapp
import android.Manifest
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.content.pm.PackageManager
import android.icu.text.SimpleDateFormat
import android.media.MediaRecorder
import android.os.Build
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.Looper
import android.os.Looper.prepare
import androidx.annotation.RequiresApi
import androidx.core.app.ActivityCompat
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.coroutines.NonCancellable.start
import java.io.IOException
import java.util.*
const val REQUEST_CODE=200
private var permission = arrayOf(Manifest.permission.RECORD_AUDIO)
private var permissionGranted=false
private lateinit var recorder : MediaRecorder
private var dirPath=""
private var filename=""
private var isRecording=false
private var isPaused=false
class MainActivity : AppCompatActivity(){
#RequiresApi(Build.VERSION_CODES.S)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
permissionGranted=ActivityCompat.checkSelfPermission(this, permission[0])==PackageManager.PERMISSION_GRANTED
if(!permissionGranted)
ActivityCompat.requestPermissions(this, permission, REQUEST_CODE)
btnRecord.setOnClickListener{
when{
isPaused->resumeRecorder()
isRecording->pauseRecorder()
else->startRecording()
}
}
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if(requestCode== REQUEST_CODE)
permissionGranted=grantResults[0]==PackageManager.PERMISSION_GRANTED
}
private fun pauseRecorder(){
recorder.pause()
isPaused=true
btnRecord.setImageResource(R.drawable.ic_record)
}
private fun resumeRecorder(){
recorder.resume()
isPaused=false
btnRecord.setImageResource(R.drawable.ic_pause)
}
#RequiresApi(Build.VERSION_CODES.S)
private fun startRecording(){
if(!permissionGranted){
ActivityCompat.requestPermissions(this, permission, REQUEST_CODE)
return
}
recorder = MediaRecorder( this)
dirPath="${externalCacheDir?.absolutePath}/"
var simpleDateFormat= SimpleDateFormat("yyyy.mm.dd.hh.mm.ss")
var date :String=simpleDateFormat.format(Date())
filename="audio_record_$date"
recorder.apply {
setAudioSource(MediaRecorder.AudioSource.MIC)
setOutputFormat(MediaRecorder.OutputFormat.MPEG_4)
setAudioEncoder(MediaRecorder.AudioEncoder.AAC)
setOutputFile("$dirPath$filename.mp3")
try{
prepare()
}catch (e:IOException){}
start()
}
btnRecord.setImageResource(R.drawable.ic_pause)
isRecording=true
isPaused=false
}
}
xml code
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="#+id/tvTimer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="00:00:00"
android:textSize="56sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal"
android:layout_marginBottom="80dp"
app:layout_constraintBottom_toBottomOf="parent"
>
<ImageButton
android:id="#+id/btnDelete"
android:layout_width="#dimen/btn_size"
android:src="#drawable/ic_delete_disable"
android:layout_height="#dimen/btn_size"
android:background="#drawable/ic_ripple"/>
<ImageButton
android:id="#+id/btnRecord"
android:layout_width="66dp"
android:layout_marginStart="30dp"
android:layout_marginEnd="30dp"
android:layout_height="66dp"
android:background="#drawable/ic_record"/>
<ImageButton
android:id="#+id/btnList"
android:layout_width="#dimen/btn_size"
android:src="#drawable/ic_list"
android:layout_height="#dimen/btn_size"
android:background="#drawable/ic_ripple"/>
<ImageButton
android:id="#+id/btnDone"
android:layout_width="#dimen/btn_size"
android:src="#drawable/ic_done"
android:visibility="gone"
android:layout_height="#dimen/btn_size"
android:background="#drawable/ic_ripple"/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
what is new defind for MediaRecorder() not Deprecated ?
give me error
java.lang.NoSuchMethodError: No direct method (Landroid/content/Context;)V in class Landroid/media/MediaRecorder; or its super classes (declaration of 'android.media.MediaRecorder' appears in /system/framework/framework.jar!classes2.dex)
Use an if/else to set the property using the supported constructor:
recorder = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) MediaRecorder(this) else MediaRecorder()
Down the road it is possible Jetpack will add a helper function that would do this for you, something like MediaRecorderCompat.newInstance(this). However, it has been so long I think we can assume they will probably not be adding it.
I used the following script in an app published on the Playstore
fun prepare_audio_and_directories(v : View) {
var tempDir : File
// current_filename = (v.findViewById(R.id.audio_filename_xml) as TextView).text.toString()
current_dir = main?.dir!!
tempDir = current_dir
main?.filenameCompletePath = tempDir?.toPath().toString() + "/" +current_filename + "."+ main?.ext
main?.filename_text = current_filename
Log.d("$TAG:prepare_audio_and_directories:main?.filenameCompletePath=", main?.filenameCompletePath!!
)
Log.d("$TAG:prepare_audio_and_directories:main?.filename_text=", main?.filename_text!!)
Log.d("NoiseSuppressor.isAvailable()=", NoiseSuppressor.isAvailable().toString() )
mediaRecorder = MediaRecorder()
mediaRecorder?.setAudioSource(MediaRecorder.AudioSource.MIC)
mediaRecorder?.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4)
mediaRecorder?.setAudioEncoder(MediaRecorder.AudioEncoder.AAC)
mediaRecorder?.setAudioEncodingBitRate(128000)
mediaRecorder?.setAudioSamplingRate(96000);
mediaRecorder?.setOutputFile(main?.filenameCompletePath)
}
The versions I tested it with are API 28,29,30 and 31.
Related
I'm new to Android development using Kotlin. I'm trying to practice uploading image from a mobile phone to my app using some methods as codes in the code below. everything works just fine with some processes such as I can select on the imageview then screen popup that can let me select image in my phone. unfortunately, after selecting the image, It shows empty/blank, shows nothing in the app. I've tried to search for help but It didn't work out. Hopefully, I can get a hand here. thanks in advance!
Activity code
package student
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.BitmapFactory
import android.os.Build
import android.os.Bundle
import android.provider.MediaStore
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import com.example.amazontutoringcenter.databinding.ActivityMainBinding
import com.example.amazontutoringcenter.databinding.ActivityStudentClassroomBinding
import com.squareup.picasso.Picasso
class StudentClassroomActivity: AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
binding.imageView.setOnClickListener {
checkPermission()
}
}
val READ_IMAGE:Int=338
private fun checkPermission() {
if (Build.VERSION.SDK_INT >= 23) {
if (ActivityCompat.checkSelfPermission(this,
android.Manifest.permission.READ_EXTERNAL_STORAGE)!=
PackageManager.PERMISSION_GRANTED) {
requestPermissions(arrayOf( android.Manifest.permission.READ_EXTERNAL_STORAGE),READ_IMAGE)
return
}
}
loadImage()
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
when(requestCode) {
READ_IMAGE->{
if(grantResults[0]==PackageManager.PERMISSION_GRANTED){
loadImage()
}else{
Toast.makeText(applicationContext,"Cannot access your images",Toast.LENGTH_LONG).show()
}
}
else-> super.onRequestPermissionsResult(requestCode, permissions, grantResults)
}
}
val PICK_IMAGE_CODE=123
private fun loadImage(){
var intent=Intent(Intent.ACTION_PICK,
MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
startActivityForResult(intent,PICK_IMAGE_CODE)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if(requestCode==PICK_IMAGE_CODE && data!=null && resultCode == RESULT_OK){
val selectedImage=data.data
val filePathColum= arrayOf(MediaStore.Images.Media.DATA)
val cursor= contentResolver.query(selectedImage!!,filePathColum,null,null,null)
cursor!!.moveToFirst()
val columnIndex=cursor!!.getColumnIndex(filePathColum[0])
val picturePath=cursor!!.getString(columnIndex)
cursor!!.close()
//.load(picturePath).into(binding.imageStudentProfile)
//Picasso.get().load(picturePath).fit().into(binding.imageStudentProfile)
binding.imageView.setImageBitmap(BitmapFactory.decodeFile(picturePath))
}
}
}
XML File
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="#+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Test Layout"
android:layout_marginTop="50dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="#+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/textView2"
android:src="#drawable/ic_attendant"/>
</androidx.constraintlayout.widget.ConstraintLayout>
ImageView has a member to load an image from an uri.
And you have an uri data.data.
So use it.
We have looked at a number of posts and tried a few with no results.
Here is the Github link for full code.
Here is the code for the activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".activity.MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/todoRv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/AddTask"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
app:srcCompat="#android:drawable/ic_input_add"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_margin="25dp"
android:onClick="openNewTask"
/>
</RelativeLayout>
Here is the code for the activity_task.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
tools:context=".activity.TaskActivity">
<TextView
android:id="#+id/txtTaskName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Task Name"
android:layout_margin="14dp"
android:textSize="33sp"/>
<EditText
android:id="#+id/etTaskName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ems="10"
android:hint="Please Enter Task Name"
android:layout_margin="14dp"
android:textSize="20sp"
android:inputType="textPersonName"
/>
<Button
android:id="#+id/saveTask"
android:layout_width="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="34dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="saveTask"
android:text="Save Task" />
</LinearLayout>
Here is the code for the item_todo.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/txtShowTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="25dp"
android:layout_marginLeft="15dp"
android:textSize="35sp"
android:text="Task Title Name" />
</LinearLayout>
Here is the code for the MainActivity.kt
package abc.com.onetaskadd.activity
import abc.com.onetaskadd.R
import abc.com.onetaskadd.adapter.TodoAdapter
import abc.com.onetaskadd.database.TodoDatabase
import abc.com.onetaskadd.model.TodoModel
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Adapter
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
class MainActivity : AppCompatActivity() {
val todoList = arrayListOf<TodoModel>()
var recyclerAdapter= TodoAdapter(todoList)
lateinit var layoutmanger: RecyclerView.LayoutManager
lateinit var todoRv: RecyclerView
val db by lazy {
TodoDatabase.getDatabase(this)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
todoRv= findViewById(R.id.todoRv)
todoRv.apply {
layoutmanger= LinearLayoutManager(this#MainActivity)
adapter=this#MainActivity.recyclerAdapter
}
db.todoDao().getAllTask().observe(this, Observer {
if (!it.isNullOrEmpty()) {
todoList.clear()
todoList.addAll(it)
recyclerAdapter.notifyDataSetChanged()
}
})
}
fun openNewTask(view: View) {
startActivity(Intent(this, TaskActivity::class.java))
}
}
Here is the code for the TaskActivity.kt
package abc.com.onetaskadd.activity
import abc.com.onetaskadd.R
import abc.com.onetaskadd.database.TodoDatabase
import abc.com.onetaskadd.model.TodoModel
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.provider.SyncStateContract.Helpers.insert
import android.view.View
import android.widget.Button
import android.widget.EditText
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
const val DB_NAME = "todo.db"
class TaskActivity : AppCompatActivity() {
lateinit var etTaskName: EditText
lateinit var saveTask: Button
val db by lazy {
TodoDatabase.getDatabase(this)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_task)
etTaskName = findViewById(R.id.etTaskName)
saveTask= findViewById(R.id.saveTask)
}
fun saveTask(view: View) {
val taskName = etTaskName.editableText.toString()
GlobalScope.launch(Dispatchers.Main) {
val id = withContext(Dispatchers.IO) {
return#withContext db.todoDao ().insertTask(
TodoModel(
taskName
)
)
}
finish()
}
}
}
Here is the code for the TodoAdapter.kt
package abc.com.onetaskadd.adapter
import abc.com.onetaskadd.R
import abc.com.onetaskadd.model.TodoModel
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
class TodoAdapter (val todoList: List<TodoModel>) :RecyclerView.Adapter<TodoAdapter.TodoViewHolder>(){
class TodoViewHolder(view: View):RecyclerView.ViewHolder(view)
{
fun bind(todoModel: TodoModel) {
with(itemView){
val txtShowTitle: TextView= findViewById(R.id.txtShowTitle)
txtShowTitle.text=todoModel.taskName
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TodoViewHolder {
val view= LayoutInflater.from(parent.context).inflate(R.layout.item_todo, parent, false)
return TodoViewHolder(view)
}
override fun onBindViewHolder(holder: TodoViewHolder, position: Int) {
holder.bind(todoList[position])
}
override fun getItemCount(): Int {
return todoList.size
}
}
Here is the code for the TodoDao.kt
package abc.com.onetaskadd.database
import abc.com.onetaskadd.model.TodoModel
import androidx.lifecycle.LiveData
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.Query
#Dao
interface TodoDao {
#Insert()
suspend fun insertTask(todoModel: TodoModel):Long
#Query("Select * From TodoModel where isFinished != -1 ")
fun getAllTask():LiveData<List<TodoModel>>
}
Here is the code for the TaskDatabase.kt
package abc.com.onetaskadd.database
import abc.com.onetaskadd.activity.DB_NAME
import abc.com.onetaskadd.model.TodoModel
import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
#Database(entities = [TodoModel::class],version = 1)
abstract class TodoDatabase: RoomDatabase() {
abstract fun todoDao(): TodoDao
companion object{
#Volatile
private var INSTANCE: TodoDatabase? =null
fun getDatabase(context: Context): TodoDatabase {
val tempInsance = INSTANCE
if (tempInsance != null) {
return tempInsance
}
synchronized(this){
val instance= Room.databaseBuilder(
context.applicationContext,
TodoDatabase:: class.java,
DB_NAME
).build()
INSTANCE= instance
return instance
}
}
}
}
Here is the code for the TodoModel.kt
package abc.com.onetaskadd.model
import androidx.room.Entity
import androidx.room.PrimaryKey
#Entity
data class TodoModel(
val taskName: String,
var isFinished: Int =-1,
#PrimaryKey
var id:Long=0
)
You should replace this code in TaskDatabase.kt file
synchronized(this){
val instance= Room.databaseBuilder(
context.applicationContext,
TodoDatabase:: class.java,
DB_NAME
).fallbackToDestructiveMigration().build()
It will Solve the debug problem.
I want to display a text view in the preview view of camera. It will appear like a label on the camera preview. It should not affect the image. Just appear like a label on preview view. I tried using frame layout but the text view disappears on the preview view
Here's my layout
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000000"
android:fitsSystemWindows="true"
tools:context=".MainActivity">
<Button
android:id="#+id/camera_capture_button"
android:layout_width="60dp"
android:layout_height="60dp"
android:background="#drawable/ic_baseline_camera_24"
android:elevation="2dp"
android:layout_marginBottom="20dp"
android:scaleType="fitCenter"
android:layout_gravity="bottom|center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.926" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Hello"
android:textSize="25dp" />
<androidx.camera.view.PreviewView
android:id="#+id/viewFinder"
android:layout_width="379dp"
android:layout_height="576dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="20dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent">
</androidx.camera.view.PreviewView>
</FrameLayout>
Main Activity
Here's the main logic->
package com.arpit.cameraxdemo
import android.Manifest
import android.content.pm.PackageManager
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.camera.core.CameraSelector
import androidx.camera.core.ImageCapture
import androidx.camera.core.Preview
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import kotlinx.android.synthetic.main.activity_main.*
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
class MainActivity : AppCompatActivity() {
private var imageCapture: ImageCapture? = null
private lateinit var cameraExecutor: ExecutorService
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
supportActionBar?.hide()
if (allPermissionsGranted()) {
startCamera()
} else {
ActivityCompat.requestPermissions(this, REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS)
}
camera_capture_button.setOnClickListener {
takePhoto()
}
cameraExecutor = Executors.newSingleThreadExecutor()
}
private fun takePhoto() {
}
private fun startCamera() {
val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
cameraProviderFuture.addListener({
val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()
val preview = Preview.Builder()
.build()
.also {
it.setSurfaceProvider(viewFinder.surfaceProvider)
}
imageCapture = ImageCapture.Builder().build()
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
try {
cameraProvider.unbindAll()
cameraProvider.bindToLifecycle(
this, cameraSelector, preview, imageCapture
)
} catch (exc: Exception) {
Log.e(TAG, "Use case binding failed", exc)
}
}, ContextCompat.getMainExecutor(this))
}
private fun allPermissionsGranted() = REQUIRED_PERMISSIONS.all {
ContextCompat.checkSelfPermission(baseContext, it) == PackageManager.PERMISSION_GRANTED
}
// checks the camera permission
override fun onRequestPermissionsResult(
requestCode: Int, permissions: Array<String>, grantResults:
IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == REQUEST_CODE_PERMISSIONS) {
if (allPermissionsGranted()) {
startCamera()
} else {
Toast.makeText(this, "Permissions not granted by the user.", Toast.LENGTH_SHORT).show()
finish()
}
}
}
companion object {
private const val TAG = "CameraXGFG"
private const val REQUEST_CODE_PERMISSIONS = 20
private val REQUIRED_PERMISSIONS = arrayOf(Manifest.permission.CAMERA)
}
override fun onDestroy() {
super.onDestroy()
cameraExecutor.shutdown()
}
}
Try below code with RelativeLayout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.camera.view.PreviewView
android:id="#+id/previewView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:gravity="center"
android:text="CameraX" />
<Button
android:id="#+id/imageCaptureBtn"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_margin="10dp"
android:gravity="center"
android:text="Click Image" />
</RelativeLayout>
Thanks for your help everyone. I have found the answer to my question. Actually what I was looking for is called overlay
viewFinder.overlay.add(tvText)
use the element "elevation" with 2dp
package com.example.va_embedding
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.MediaController
import android.widget.ProgressBar
import android.widget.SeekBar
import android.widget.VideoView
import android.widget.SeekBar.OnSeekBarChangeListener
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val venom = findViewById<VideoView>(R.id.venomvideo)
venom.setVideoPath("android.resource://" + packageName + "/" + R.raw.venom)
val mediaC = MediaController(this)
mediaC.setAnchorView(venom)
venom.setMediaController(mediaC)
val vc = findViewById<SeekBar>(R.id.seekBar2)
vc.setOnSeekBarChangeListener(SeekBar.OnSeekBarChangeListener(){
#Override
onProgressChanged(SeekBar seekBar2, Int: i, boolean : b)
Log.i(:"Seekbar changed", i = Integer.toString())
})
venom.start()
}
}
XML Layout
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<VideoView
android:id="#+id/venomvideo"
android:layout_width="333dp"
android:layout_height="568dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0" />
<SeekBar
android:id="#+id/seekBar2"
android:layout_width="249dp"
android:layout_height="73dp"
android:layout_marginStart="70dp"
android:layout_marginEnd="70dp"
android:layout_marginBottom="50dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Objective: To get an Audio SeekBar in the app
Issue: I am getting an error saying Interface do not have constructors. I am also facing an issue when I am trying to add OnSeekBarChangeListener() method.
I am using Android Studio 3.6.1.
My SDK version is 28
Kindly help
SeekBar.OnSeekBarChangeListener is an interface not a class, you can not call the constructor SeekBar.OnSeekBarChangeListener().
So instead use the below code:
vc.setOnSeekBarChangeListener(object: SeekBar.OnSeekBarChangeListener{
#Override
override fun onProgressChanged(
seekBar: SeekBar?, progress: Int,
fromUser: Boolean
){
Log.i(:"Seekbar changed", i = Integer.toString())
}
})
I am using YoutubeplayerApi in my android app
what I have done is that there is a youtubeplayerView and a recycler view below the player
I want to implement the functionality that once a user click on the item view of recycler view the youtubeplayer should play that particular video but I am not able to implement that
any help would be appreciated
activity_music.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".UI.MusicActivity">
<com.google.android.youtube.player.YouTubePlayerView
android:layout_width="450dp"
android:layout_height="384dp"
android:id="#+id/youtube_player"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="24dp"
/>
<android.support.v7.widget.RecyclerView
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:id="#+id/songs_recycler_view"
app:layout_constraintTop_toBottomOf="#+id/youtube_player"/>
</android.support.constraint.ConstraintLayout>
MusicActivity.kt
package com.example.ashish.batmn.UI
import android.content.Intent
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView
import android.widget.Toast
import com.example.ashish.batmn.Adapters.SongsAdapter
import com.example.ashish.batmn.Config
import com.example.ashish.batmn.Models.Songs
import com.example.ashish.batmn.R
import com.google.android.youtube.player.YouTubeBaseActivity
import com.google.android.youtube.player.YouTubeInitializationResult
import com.google.android.youtube.player.YouTubePlayer
import com.google.android.youtube.player.YouTubeStandalonePlayer
import kotlinx.android.synthetic.main.activity_music.*
class MusicActivity : YouTubeBaseActivity(), YouTubePlayer.OnInitializedListener {
val songsList = listOf<Songs>(
Songs("Girls Like You","cBVGlBWQzuc","${Config.IMAGE_BASE_URL}cBVGlBWQzuc${Config.IMAGE_PIC_END}"),
Songs("The National - Fake Empire","KehwyWmXr3U","${Config.IMAGE_BASE_URL}KehwyWmXr3U${Config.IMAGE_PIC_END}"),
Songs("Halka Halka","nZhLM-FeV9A","${Config.IMAGE_BASE_URL}nZhLM-FeV9A${Config.IMAGE_PIC_END}"),
Songs("Camila Cabello - Real Friends","66rxB7_zzs8","${Config.IMAGE_BASE_URL}66rxB7_zzs8${Config.IMAGE_PIC_END}"),
Songs("Darya","wHHCO29mqiA","${Config.IMAGE_BASE_URL}wHHCO29mqiA${Config.IMAGE_PIC_END}"),
Songs("Naina Da Kya Kasoor","BJWTzYPWINw","${Config.IMAGE_BASE_URL}BJWTzYPWINw${Config.IMAGE_PIC_END}")
)
override fun onInitializationSuccess(provider: YouTubePlayer.Provider?, player: YouTubePlayer?, wasRestored: Boolean) {
if (!wasRestored){
player!!.cueVideo(Config.VIDEO_CODE)
player.setPlayerStyle(YouTubePlayer.PlayerStyle.DEFAULT)
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if(requestCode == 1){
getYoutubePlayerProvider().initialize(Config.VIDEO_CODE,this)
}
}
override fun onInitializationFailure(p0: YouTubePlayer.Provider?, errorResult: YouTubeInitializationResult?) {
if (errorResult!!.isUserRecoverableError){
errorResult.getErrorDialog(this,1).show()
}
else{
Toast.makeText(this,"Some unforseen error has occured",Toast.LENGTH_SHORT).show()
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_music)
youtube_player.initialize(Config.API_KEY,this)
val songAdapter = SongsAdapter(songsList,this){
// what should be added in here?
}
songs_recycler_view.layoutManager = LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false)
songs_recycler_view.adapter = songAdapter
}
fun getYoutubePlayerProvider():YouTubePlayer.Provider{
return youtube_player
}
}
Songs.kt // Model class
package com.example.ashish.batmn.Models
class Songs(val mSongName:String, val mVideoCode:String,val mSongPic:String) {
}
First of all in onInitializationSuccess set player instance to a global field. Then Add a onClickListener to listview. After that in onClick method call player.setCue() method with the video id that you want to play. And at the last play the video with player.play().