how to play audio offline by url? - kotlin

i want to if i press play - the audio start playing, but if I will turn off the internet after some time, I can still listen to the audio to the end, how can i do this using andoid-mediaPlayer?
in kotlin
class MusicService:Service(),MediaPlayer.OnPreparedListener,MediaPlayer.OnCompletionListener,MediaPlayer.OnErrorListener {
override fun onBind(intent: Intent?): IBinder? {
return musicBind
}
override fun onCreate() {
super.onCreate()
player= MediaPlayer()
}
fun initMusic(){
player.setWakeMode(applicationContext,PowerManager.PARTIAL_WAKE_LOCK)
player.setAudioStreamType(AudioManager.STREAM_MUSIC)
player.setOnPreparedListener(this)
player.setOnCompletionListener(this)
player.setOnErrorListener(this)
}
override fun onUnbind(intent: Intent?): Boolean {
player.stop()
player.reset()
player.release()
return false
}
inner class MusicBinder:Binder(){
val service: MusicService
get() = this#MusicService
}
companion object{
const val STOPPED = 0
const val PAUSED =1
const val PLAYING = 2
}
override fun onPrepared(mp: MediaPlayer?) {
mp!!.start()
val duration=mp.duration
seekBar.max=duration
seekBar.postDelayed(progressRunner,instentval.toLong())
end_point.text= String.format("%d:%02d",TimeUnit.MILLISECONDS.toMinutes(duration.toLong()),
TimeUnit.MILLISECONDS.toSeconds(duration.toLong())-
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(duration.toLong())))
}
private fun playSong(){
try {
player.reset()
val playSong=songs
val uri = playSong.link
player=MediaPlayer.create(this, Uri.parse(uri))
try {
player.start()
progressRunner.run()
}catch (e:HttpException){
Toast.makeText(this,"Http went wrong!",Toast.LENGTH_SHORT).show()
}
} catch (e:Exception){
Toast.makeText(this,"something went wrong!",Toast.LENGTH_SHORT).show()
}
}
fun setUI(seekBar: SeekBar,start_int:TextView,end_int:TextView){
this.seekBar=seekBar
start_point=start_int
end_point=end_int
seekBar.setOnSeekBarChangeListener(object :SeekBar.OnSeekBarChangeListener
{
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
if (fromUser){
player.seekTo(progress)
}
start_point.text = String.format(
"%d:%02d",TimeUnit.MILLISECONDS.toMinutes(progress.toLong()),
TimeUnit.MILLISECONDS.toSeconds(progress.toLong())-
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(progress.toLong())))
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {
TODO("Not yet implemented")
}
override fun onStopTrackingTouch(seekBar: SeekBar?) {
TODO("Not yet implemented")
}
}
)
}
private var progressRunner:Runnable = object :Runnable {
override fun run() {
if (seekBar!=null){
seekBar.progress=player.currentPosition
if (player.isPlaying){
seekBar.postDelayed(this,instentval.toLong())
}
}
}
}
fun setSong(result: Result){
songs=result
playerState= PLAYING
playSong()
}
fun setSongmp3(mp3: Mp3){
songsmp3=mp3
playerState= PLAYING
playSongmp3()
}
public fun puseSong()
{
player.pause()
playerState = PAUSED
}
public fun resumeSong(){
player.start()
playerState= PLAYING
}
override fun onCompletion(mp: MediaPlayer?) {
}
override fun onError(mp: MediaPlayer?, what: Int, extra: Int): Boolean {
return false
}
}

Related

I want to use recyclerView, but the view doesn't have any values. kotlin

class SummonerInfoActivity: AppCompatActivity() {
private lateinit var participantAdapter: ParticipantAdapter
private val recycler: RecyclerView by lazy {
findViewById(R.id.RecyclerView)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val Summoner = intent.getParcelableExtra<SummonerDTO>("SummonerDTO")
Log.e("Info","${Summoner}")
val retrofit2 = Retrofit.Builder()
.baseUrl("https://asia.api.riotgames.com")
.addConverterFactory(GsonConverterFactory.create())
.build()
lolAPIForMatch = retrofit2.create(lolAPIService::class.java)
setContentView(R.layout.activity_summoner_info)
participantAdapter = ParticipantAdapter()
recycler.adapter = participantAdapter
recycler.layoutManager = LinearLayoutManager(this#SummonerInfoActivity)
getMatchIdBypuuid(Summoner?.puuId.orEmpty(),Summoner?.summonerName.orEmpty())
}
private fun getMatchIdBypuuid(puuid: String,summonerName: String){
lolAPIForMatch.getMatchIdBypuuid(puuid, 0,20, API_KEY)
.enqueue(object : Callback<List<String>> {
override fun onResponse(
call: Call<List<String>>,
response: Response<List<String>>
) {
if(response.isSuccessful.not()){
return
}
response.body()?.let {
it.forEach {
searchMatchInfoByMatchID(it,summonerName)
}
}
}
override fun onFailure(call: Call<List<String>>, t: Throwable) {
}
})
}
private fun searchMatchInfoByMatchID(matchId: String,summonerName: String){
lolAPIForMatch.getMatchInfoByMatchID(matchId, API_KEY)
.enqueue(object : Callback<MatchDTO>{
override fun onResponse(call: Call<MatchDTO>, response: Response<MatchDTO>) {
if(response.isSuccessful.not()){
return
}
response.body()?.let {
it.info.participants.filter {
it.summonerName == "${summonerName}"
}.forEach {
participantAdapter.participants.add(it)
}
}
}
override fun onFailure(call: Call<MatchDTO>, t: Throwable) {
}
})
}
}
class ParticipantAdapter: RecyclerView.Adapter<ParticipantAdapter.ViewHolder>() {
var participants = mutableListOf<ParticipantDTO>()
inner class ViewHolder(itemView: View): RecyclerView.ViewHolder(itemView){
fun bind(participant: ParticipantDTO){
itemView.findViewById<TextView>(R.id.kill).text = participant.kills.toString()
itemView.findViewById<TextView>(R.id.death).text = participant.deaths.toString()
itemView.findViewById<TextView>(R.id.assist).text = participant.assists.toString()
}
}
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): ParticipantAdapter.ViewHolder {
val inflater = LayoutInflater.from(parent.context)
return ViewHolder(inflater.inflate(R.layout.item_match, parent, false))
}
override fun onBindViewHolder(holder: ParticipantAdapter.ViewHolder, position: Int) {
holder.bind(participants[position])
}
override fun getItemCount(): Int {
return participants.size
}
}
participantAdapter.participants.add(it)
The command is searchMatchInfoByMatchID
In the function, you can check that the value is entered correctly, but
If you check in the onCreate function, the value is not assigned.
I want to use the recycler view by properly assigning a value
I tried to solve this problem, but my skills were not enough.
I desperately need the advice of seniors.
I would really appreciate it if you could show me a code sample if possible

How to retrun a String in Kotlin Initialization

I have the following Firebase Initialization, how can I make it return snapshot so that when I call it I get the val snapshot?
var homeRef_Host_Name: Unit = FirebaseDatabase.getInstance().getReference().child("users").child(firebaseAuth.currentUser.uid)
.child("name")
.addListenerForSingleValueEvent(object: ValueEventListener{
override fun onDataChange(snapshot: DataSnapshot) {
val snapshot = snapshot.value.toString()
}
override fun onCancelled(error: DatabaseError) {
}
})
fun getValue(callback:(String)->Unit){
FirebaseDatabase.getInstance().getReference().child("users").child(firebaseAuth.currentUser.uid)
.child("name")
.addListenerForSingleValueEvent(object: ValueEventListener{
override fun onDataChange(snapshot: DataSnapshot) {
callback(snapshot.value.toString())
}
override fun onCancelled(error: DatabaseError) {
}
})
}
fun main(){
getValue {
var yourvariable = it
//place your further code here
}
}
you cant directly assign it to variable because it async operation

Why there is red line on myPhone.something1.something() ? -something1-

fun main() {
val myPhone = Myphone()
myPhone.phoneOn()
myPhone.onClick()
myPhone.onTouch()
myPhone.openApp()
myPhone.closeApp()
myPhone.brightMax()
myPhone.Something1.something()
}
interface Application {
var appName: String
var x1: Int
fun something()
fun brightMax() {
println("Brightness level is on Max!")
}
fun openApp() {
println("$appName is opening!")
}
fun phoneOn() {
println("The phone is ON")
}
fun onClick() {
println("App is running")
}
fun closeApp() {
println("${Myphone.Something1.appName} App is closed!")
}
}
interface Button {
val x: Int
var helloMessage: String
fun brightMax() {
println("Brightness is on $x")
}
fun phoneOn() {
println("Power on button was pressed!")
}
fun onClick()
fun onTouch() {
println("The screen was touched!")
}
}
class Myphone: Button, Application {
override fun something() {
println("Doing something")
}
object Something1 : Application {
override var x1: Int = 100
override var appName: String = "Instagram"
override fun something() {
println("He wants to die!")
}
}
override var x1: Int = 12
override var appName: String = "Facebook"
override var x: Int = 100
override fun phoneOn() {
super<Application>.phoneOn()
}
override fun brightMax() {
super<Application>.brightMax()
super<Button>.brightMax()
}
override var helloMessage: String = "Hello"
override fun onClick() {
super.onClick()
}
}
I created object inside the class and I can't "call" it back in main function.
Once I did and I can't remember how to solve it again.
Don't blame me because of code. I made it for presentation.
on the 9th line, there is error, why? the something1 has red line in kotlin.
something1.appName - is working perfectly?
You get the error because it's not recommended to access nested objects via instance references. Use Myphone.Something1.something() instead of myPhone.Something1.something().

Kotlin Coroutine Unit Test Flow collection with viewModelScope

I want to test a method of my ViewModel that collects a Flow. Inside the collector a LiveData object is mutated, which I want to check in the end. This is roughly how the setup looks:
//Outside viewmodel
val f = flow { emit("Test") }.flowOn(Dispatchers.IO)
//Inside viewmodel
val liveData = MutableLiveData<String>()
fun action() {
viewModelScope.launch { privateAction() }
}
suspend fun privateAction() {
f.collect {
liveData.value = it
}
}
When I now call the action() method in my unit test, the test finishes before the flow is collected. This is how the test might look:
#Test
fun example() = runBlockingTest {
viewModel.action()
assertEquals(viewModel.liveData.value, "Test")
}
I am using the TestCoroutineDispatcher via this Junit5 extension and also the instant executor extension for LiveData:
class TestCoroutineDispatcherExtension : BeforeEachCallback, AfterEachCallback, ParameterResolver {
#SuppressLint("NewApi") // Only used in unit tests
override fun supportsParameter(parameterContext: ParameterContext?, extensionContext: ExtensionContext?): Boolean {
return parameterContext?.parameter?.type === testDispatcher.javaClass
}
override fun resolveParameter(parameterContext: ParameterContext?, extensionContext: ExtensionContext?): Any {
return testDispatcher
}
private val testDispatcher = TestCoroutineDispatcher()
override fun beforeEach(context: ExtensionContext?) {
Dispatchers.setMain(testDispatcher)
}
override fun afterEach(context: ExtensionContext?) {
Dispatchers.resetMain()
testDispatcher.cleanupTestCoroutines()
}
}
class InstantExecutorExtension : BeforeEachCallback, AfterEachCallback {
override fun beforeEach(context: ExtensionContext?) {
ArchTaskExecutor.getInstance()
.setDelegate(object : TaskExecutor() {
override fun executeOnDiskIO(runnable: Runnable) = runnable.run()
override fun postToMainThread(runnable: Runnable) = runnable.run()
override fun isMainThread(): Boolean = true
})
}
override fun afterEach(context: ExtensionContext?) {
ArchTaskExecutor.getInstance().setDelegate(null)
}
}
You can try either,
fun action() = viewModelScope.launch { privateAction() }
suspend fun privateAction() {
f.collect {
liveData.value = it
}
}
#Test
fun example() = runBlockingTest {
viewModel.action().join()
assertEquals(viewModel.liveData.value, "Test")
}
or
fun action() {
viewModelScope.launch { privateAction()
}
suspend fun privateAction() {
f.collect {
liveData.value = it
}
}
#Test
fun example() = runBlockingTest {
viewModel.action()
viewModel.viewModelScope.coroutineContext[Job]!!.join()
assertEquals(viewModel.liveData.value, "Test")
}
You could also try this,
suspend fun <T> LiveData<T>.awaitValue(): T? {
return suspendCoroutine { cont ->
val observer = object : Observer<T> {
override fun onChanged(t: T?) {
removeObserver(this)
cont.resume(t)
}
}
observeForever(observer)
}
}
#Test
fun example() = runBlockingTest {
viewModel.action()
assertEquals(viewModel.liveData.awaitValue(), "Test")
}
So what I ended up doing is just passing the Dispatcher to the viewmodel constructor:
class MyViewModel(..., private val dispatcher = Dispatchers.Main)
and then using it like this:
viewModelScope.launch(dispatcher) {}
So now I can override this when I instantiate the ViewModel in my test with a TestCoroutineDispatcher and then advance the time, use testCoroutineDispatcher.runBlockingTest {}, etc.

Capture and show image from camera2 API, Android Studio, Kotlin

I have been following a tutorial on how to get a camera preview on a fragment to show on my app, I am new to kotlin but have been programming in Swift for 2 years. Is there a way to get an image from the preview and show it in another image view.
I created an image view called imageGotCont and this is where I want to place the images I have a button in my main activity so when I press it I need a function that gets an image fromt the preview and places it in the image view.
Below is the fragment.
class FragmentCameraPreview : Fragment() {
private val MAX_DISPLAY_WIDTH = 1280
private val MAX_DISPLAY_HEIGHT = 720
private lateinit var captureSession: CameraCaptureSession
private lateinit var captureRequestBuilder: CaptureRequest.Builder
private lateinit var imageSize: Size
private lateinit var cameraDevice: CameraDevice
private val deviceStateCallback = object : CameraDevice.StateCallback() {
override fun onOpened(camera: CameraDevice?) {
Log.d(TAG, "camera device opened")
if (camera != null) {
cameraDevice = camera
previewSession()
}
}
override fun onDisconnected(camera: CameraDevice?) {
Log.d(TAG, "camera device disconnected")
camera?.close()
}
override fun onError(camera: CameraDevice?, error: Int) {
Log.d(TAG, "camera device error")
this#FragmentCameraPreview.activity?.finish()
}
}
private lateinit var backgroundThread: HandlerThread
private lateinit var backgroundHandler: Handler
private val cameraManager by lazy {
activity?.getSystemService(Context.CAMERA_SERVICE) as CameraManager
}
companion object {
private val TAG = FragmentCameraPreview::class.qualifiedName
const val REQUEST_CAMERA_PERMISSION = 100
#JvmStatic
fun newInstance() = FragmentCameraPreview()
}
private val surfaceListner = object : TextureView.SurfaceTextureListener {
override fun onSurfaceTextureSizeChanged(surface: SurfaceTexture?, width: Int, height: Int) {
}
override fun onSurfaceTextureUpdated(surface: SurfaceTexture?) = Unit
override fun onSurfaceTextureDestroyed(surface: SurfaceTexture?): Boolean = true
override fun onSurfaceTextureAvailable(surface: SurfaceTexture?, width: Int, height: Int) {
Log.d(TAG, "Tony texture surface width: $width height: $height")
openCamera()
}
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults)
}
#AfterPermissionGranted(REQUEST_CAMERA_PERMISSION)
private fun checkCameraPermission() {
if (EasyPermissions.hasPermissions(activity!!, android.Manifest.permission.CAMERA)) {
Log.d(TAG, "APP has camera permission")
connectCamera()
} else {
EasyPermissions.requestPermissions(
activity!!,
getString(R.string.camera_request_rationale),
REQUEST_CAMERA_PERMISSION,
android.Manifest.permission.CAMERA
)
}
}
override fun onResume() {
super.onResume()
startBackgroundThread()
if (previewTextureView.isAvailable)
openCamera()
else
previewTextureView.surfaceTextureListener = surfaceListner
}
override fun onPause() {
closeCamera()
stopBackgroundThread()
super.onPause()
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val myInflatedView = inflater.inflate(R.layout.fragment_camera_preview, container, false)
return myInflatedView
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
activity?.window?.decorView?.systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN or
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY or View.SYSTEM_UI_FLAG_FULLSCREEN or
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
}
private fun openCamera() {
checkCameraPermission()
}
private fun <T> cameraCharacteristics(cameraId: String, key: CameraCharacteristics.Key<T>): T {
val characteristics = cameraManager.getCameraCharacteristics(cameraId)
return when (key) {
CameraCharacteristics.LENS_FACING -> characteristics.get(key)
CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP -> characteristics.get(key)
else -> throw IllegalArgumentException("Key not recognized")
}
}
private fun cameraId(lens: Int): String {
var deviceId = listOf<String>()
try {
val cameraIdList = cameraManager.cameraIdList
deviceId = cameraIdList.filter { lens == cameraCharacteristics(it, CameraCharacteristics.LENS_FACING) }
} catch (e: CameraAccessException) {
Log.e(TAG, e.toString())
}
return deviceId[0]
}
private fun connectCamera() {
val deviceID = cameraId(CameraCharacteristics.LENS_FACING_BACK)
Log.d(TAG, "deviceID: $deviceID")
try {
cameraManager.openCamera(deviceID, deviceStateCallback, backgroundHandler)
} catch (e: CameraAccessException) {
Log.e(TAG, e.toString())
} catch (e: InterruptedException) {
Log.e(TAG, "Open camera device interrupted while opening")
}
}
private fun startBackgroundThread() {
backgroundThread = HandlerThread("CameraKotlin").also { it.start() }
backgroundHandler = Handler(backgroundThread.looper)
}
private fun stopBackgroundThread() {
backgroundThread.quitSafely()
try {
backgroundThread.join()
} catch (e: InterruptedException) {
Log.e(TAG, e.toString())
}
}
private fun previewSession() {
val surfaceTexture = previewTextureView.surfaceTexture
surfaceTexture.setDefaultBufferSize(MAX_DISPLAY_WIDTH, MAX_DISPLAY_HEIGHT)
val surface = Surface(surfaceTexture)
captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE)
captureRequestBuilder.addTarget(surface)
cameraDevice.createCaptureSession(
Arrays.asList(surface),
object : CameraCaptureSession.StateCallback() {
override fun onConfigureFailed(session: CameraCaptureSession?) {
Log.e(TAG, "creating capture session failed")
}
override fun onConfigured(session: CameraCaptureSession?) {
if (session != null) {
captureSession = session
captureRequestBuilder.set(
CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE
)
captureSession.setRepeatingRequest(captureRequestBuilder.build(), null, null)
}
}
}, null
)
}
private fun closeCamera() {
if (this::captureSession.isInitialized)
captureSession.close()
if (this::cameraDevice.isInitialized)
cameraDevice.close()
}
}