viewmodelscope.launch not getting called inside lambda kotlin android

30 views Asked by At

I want to insert the VideoUrls object into the database through callback while enqueuing a network request through the volley library in Android just after I obtain the title from the response. Here is my code:

YoutubeDownloaderViewModel:

@HiltViewModel
class YoutubeDownloaderViewModel @Inject constructor(
    private val videoUrlsDBRepository: VideoUrlsDBRepository,
    private val videoUrlsNetworkRepository: VideoUrlsNetworkRepository
) : ViewModel() {
    // LiveData for observing URLs from the database
    val urls: LiveData<List<VideoUrls>> = videoUrlsDBRepository.getUrls().asLiveData()
    private var downloadUrl: String = ""
    private var deleteUrl: String = ""
    private val outputUrls: MutableList<VideoItem> = mutableListOf()
    var downloadId: Long = 0
    private val _downloadCompleted = MutableLiveData<Boolean>()
    val downloadCompleted: LiveData<Boolean>
        get() = _downloadCompleted
    private val _thumbnail = MutableLiveData<String>()
    val thumbnail: LiveData<String>
        get() = _thumbnail
    private val _title = MutableLiveData<String>()
    val title: LiveData<String>
        get() = _title

    init {
        // Initializing LiveData values
        _downloadCompleted.value = false
        _thumbnail.value = ""
        _title.value = ""
    }

    @SuppressLint("SimpleDateFormat")
    fun insertUrl(url: String) {
        // Deleting previous URL if any and inserting the new URL into the database
        val temp = deleteUrl
        deleteUrl = url
        deleteUrl()
        deleteUrl = temp
        val sdf = SimpleDateFormat("dd/MM/yyyy")
        val date = sdf.format(Date()).toString()
        val time = Calendar.getInstance().time.toString()
        var title=""
        videoUrlsNetworkRepository.insertUrlRequestIntoQueue(
            getYoutubeID(url),
            updateTitle = {
                title = it
                Log.d("title update inside","title=${title} time=${System.currentTimeMillis()}")
                viewModelScope.launch {
                    videoUrlsDBRepository.insertUrl(
                        VideoUrls(
                            videoUrl = url,
                            title = title,
                            date = date,
                            time = time
                        )
                    )
                }
            })
    }

    fun deleteUrl() {
        // Deleting URL from the database
        viewModelScope.launch {
            videoUrlsDBRepository.deleteUrl(deleteUrl)
        }
        resetAll()
    }

    fun assignUrls(url: String) {
        // Assigning download URL and delete URL and fetching thumbnail and title
        downloadUrl = url
        deleteUrl = url
        thumbUrlAndTitle()
    }

    fun outPutVideos(pos: Int) {
        // Processing video download request
        outputUrls.addAll(videoUrlsNetworkRepository.outputVideosRequestIntoQueue(pos,getYoutubeID(downloadUrl), updateDownloadId = {
            downloadId=it
        }, updateDownloadLiveData = {
            if(downloadId==it)  _downloadCompleted.value=true
        }))
    }

    fun resetAll() {
        // Resetting all values to default
        _downloadCompleted.value = false
        outputUrls.clear()
        _thumbnail.value = ""
        _title.value = ""
    }

    fun isYoutubeUrl(youTubeURl: String): Boolean {
        // Checking if URL is a valid YouTube URL
        val pattern = Pattern.compile("^(http(s)?:\\/\\/)?((w){3}.)?youtu(be|.be)?(\\.com)?\\/.+")
        val matcher = pattern.matcher(youTubeURl)
        return matcher.matches()
    }

    private fun thumbUrlAndTitle() {
        // Fetching thumbnail and title from API
        videoUrlsNetworkRepository.insertThumbUrlAndTitleRequestIntoQueue(getYoutubeID(downloadUrl), updateThumbAndTitle = {
            s1,s2->
            _thumbnail.value=s1
            _title.value=s2
        })
    }

    private fun getYoutubeID(youtubeUrl: String): String? {
        // Extracting YouTube video ID from the URL
        if (TextUtils.isEmpty(youtubeUrl)) {
            return ""
        }
        var  video_id: String? = ""
        val expression =
            "^.*((youtu.be" + "\\/)" + "|(v\\/)|(\\/u\\/w\\/)|(embed\\/)|(watch\\?))\\??v?=?([^#\\&\\?]*).*" // var regExp = /^.*((youtu.be\/)|(v\/)|(\/u\/\w\/)|(embed\/)|(watch\?))\??v?=?([^#\&\?]*).*/;
        val input: CharSequence = youtubeUrl
        val pattern = Pattern.compile(expression, Pattern.CASE_INSENSITIVE)
        val matcher = pattern.matcher(input)
        if (matcher.matches()) {
            val groupIndex1 = matcher.group(7)
            if (groupIndex1 != null && groupIndex1.length == 11) video_id = groupIndex1
        }
        if (TextUtils.isEmpty(video_id)) {
            if (youtubeUrl.contains("youtu.be/")) {
                val spl = youtubeUrl.split("youtu.be/".toRegex()).toTypedArray()[1]
                video_id = if (spl.contains("\\?")) {
                    spl.split("\\?".toRegex()).toTypedArray()[0]
                } else {
                    spl
                }
            }
        }
        return video_id
    }
}

VideoUrlsNetworkRepository:

class VideoUrlsNetworkRepository @Inject constructor(private val queue: RequestQueue,@ApplicationContext private val context: Context) {

    fun insertUrlRequestIntoQueue(youtubeId:String?,updateTitle:(String)->Unit={}) {
        val currUrl = "https://ytstream-download-youtube-videos.p.rapidapi.com/dl?id=${youtubeId}&rapidapi-key=1e59c5254cmsh65f87366aa4844fp138d18jsn4df36025d134"
        val jsonObjectRequest = JsonObjectRequest(
            Request.Method.GET, currUrl, null, { response ->
                updateTitle(response.getString("title"))
            },
            { error ->
                Log.d("insertion error", error.toString())
            }
        )
        queue.add(jsonObjectRequest)
    }

    fun insertThumbUrlAndTitleRequestIntoQueue(youtubeId:String?,updateThumbAndTitle:(String,String)->Unit={
        s1,s2->
    }){
        val currUrl =
            "https://ytstream-download-youtube-videos.p.rapidapi.com/dl?id=${youtubeId}&rapidapi-key=1e59c5254cmsh65f87366aa4844fp138d18jsn4df36025d134"
        val thumbAndTitle= mutableListOf<String>()
        val jsonObjectRequest = JsonObjectRequest(
            Request.Method.GET, currUrl, null,
            { response ->
                updateThumbAndTitle(
                response.getString("thumb"),
                response.getString("title")
                )
            },
            { error ->
                Log.d("problem", error.toString())
            }
        )
        queue.add(jsonObjectRequest)
    }

    fun outputVideosRequestIntoQueue(
        pos:Int,
        youtubeId: String?,
        updateDownloadId:(Long)->Unit={},
        updateDownloadLiveData:(Long?)->Unit={}
    ):List<VideoItem> {
        val outputUrls:MutableList<VideoItem> = mutableListOf()
        val currUrl =
            "https://ytstream-download-youtube-videos.p.rapidapi.com/dl?id=${youtubeId}&rapidapi-key=1e59c5254cmsh65f87366aa4844fp138d18jsn4df36025d134"
        val jsonObjectRequest = JsonObjectRequest(
            Request.Method.GET, currUrl, null,
            { response ->
                val obj = response.getJSONObject("link")
                outputUrls.add(VideoItem(obj.getJSONArray("18").getString(0)))
                outputUrls.add(VideoItem(obj.getJSONArray("22").getString(0)))
                val DIRECTORY = "/YoutubeVideos/"
                val DIRECTORY_FOLDER =
                    File("${Environment.getExternalStorageDirectory()}/Download/${DIRECTORY}")
                if (!DIRECTORY_FOLDER.exists()) {
                    DIRECTORY_FOLDER.mkdirs()
                }
                val request = DownloadManager.Request(Uri.parse(outputUrls[pos].url))
                    .setTitle("YoutubeVideo_" + System.currentTimeMillis().toString() + ".mp4")
                    .setDescription("Downloading Video")
                    .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE)
                    .setAllowedOverMetered(true)
                    .setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI or DownloadManager.Request.NETWORK_MOBILE)
                    .setDestinationInExternalPublicDir(
                        Environment.DIRECTORY_DOWNLOADS,
                        DIRECTORY + "YoutubeVideo_" + System.currentTimeMillis().toString() + ".mp4"
                    )
                val dm: DownloadManager = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
                updateDownloadId(dm.enqueue(request))
                MediaScannerConnection.scanFile(
                    context,
                    arrayOf(
                        File(
                            Environment.DIRECTORY_DOWNLOADS + "/" + DIRECTORY + "YoutubeVideo_" + System.currentTimeMillis()
                                .toString() + ".mp4"
                        ).absolutePath
                    ),
                    null
                )
                { _, _ ->
                }
                val br = object : BroadcastReceiver() {
                    override fun onReceive(p0: Context?, p1: Intent?) {
                        val id = p1?.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1)
                        updateDownloadLiveData(id)
                    }
                }
                context.registerReceiver(br, (IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)))
            },
            { error ->
                Log.d("problem", error.toString())
            }
        )
        queue.add(jsonObjectRequest)
        return outputUrls
    }

}

VideoUrlsDBRepository:

class VideoUrlsDBRepository @Inject constructor(private val videoUrlDao: VideoUrlDao) {

    fun getUrls()=videoUrlDao.getUrls()

    suspend fun insertUrl(videoUrl: VideoUrls){
        Log.d("title update inside fun","title=${videoUrl.title} time=${System.currentTimeMillis()}")
        videoUrlDao.insertUrl(videoUrl)
    }

    suspend fun deleteUrl(url:String)=videoUrlDao.deleteUrl(url)
}

Viewmodelscope.launch is not getting called inside lambda in YoutubeDownloaderViewModel and the title also is not getting updated.

0

There are 0 answers