RecyclerView and OnItemClick: No value passed for parameter 'click' in Fragment - kotlin

I'm trying to implement an OnClick listener for specific items in a recyclerview. I've done it before with activities, but now I want to do this in a fragment and I've run into a problem. I'm getting the error No value passed for parameter 'click'. This is the line of code that gives that error:
recyclerAdapterAbstract = abstractList.let {AbstractAdapter(requireActivity(),it)}
This the only error Android Studio is currently showing me. The logcat doesn't show any error. Only the Build Output shows what's wrong and it's exactly what I said earlier
Fragment Class
#Suppress("UNREACHABLE_CODE")
class AbstractWallpapers: Fragment(), PurchasesUpdatedListener, AbstractAdapter.OnItemClickListenerAbstract {
private lateinit var subscribeAbstract: Button
private var billingClient: BillingClient? = null
lateinit var recyclerView: RecyclerView
lateinit var abstractList: ArrayList<Abstract>
private var recyclerAdapterAbstract: AbstractAdapter? = null
private var myRef3: DatabaseReference? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_abstract_wallpaper, container, false)
recyclerView = requireActivity().findViewById(R.id.abstract_recyclerView)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
recyclerView = view.findViewById(R.id.abstract_recyclerView)
val layoutManager = GridLayoutManager(requireContext(), 2)
recyclerView.layoutManager = layoutManager
recyclerView.setHasFixedSize(true)
myRef3 = FirebaseDatabase.getInstance().reference
abstractList = ArrayList()
ClearAll()
GetDataFromFirebase()
subscribeAbstract = view.findViewById(R.id.abstract_subscribe_btn)
subscribeAbstract.setOnClickListener {
subscribeAbstract()
}
//Establish connection to billing client
//check subscription status from google play store cache
//to check if item is already Subscribed or subscription is not renewed and cancelled
billingClient = BillingClient.newBuilder(requireActivity()).enablePendingPurchases().setListener(this).build()
billingClient!!.startConnection(object : BillingClientStateListener {
override fun onBillingSetupFinished(billingResult: BillingResult) {
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
val queryPurchase = billingClient!!.queryPurchases(BillingClient.SkuType.SUBS)
val queryPurchases = queryPurchase.purchasesList
if (queryPurchases != null && queryPurchases.size > 0) {
handlePurchases(queryPurchases)
} else {
saveSubscribeValueToPref(false)
}
}
}
override fun onBillingServiceDisconnected() {
Toast.makeText(requireActivity(), "Service Disconnected", Toast.LENGTH_SHORT).show()
}
})
//item subscribed
if (subscribeValueFromPref) {
subscribeAbstract.visibility = View.GONE
} else {
subscribeAbstract.visibility = View.VISIBLE
}
}
// Code relating to my Firebase storage
#SuppressLint("NotifyDataSetChanged")
private fun GetDataFromFirebase() {
val query: Query = myRef3!!.child("Abstract")
query.addListenerForSingleValueEvent(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
for (dataSnapshot: DataSnapshot in snapshot.children) {
val abstract = Abstract()
abstract.abstract = dataSnapshot.child("abstract").value.toString()
abstractList.add(abstract)}
recyclerAdapterAbstract = abstractList.let {AbstractAdapter(requireActivity(),it)}
recyclerView.adapter = recyclerAdapterAbstract
recyclerAdapterAbstract!!.notifyDataSetChanged()
}
override fun onCancelled(error: DatabaseError) {}
})
if (recyclerAdapterAbstract != null) recyclerAdapterAbstract!!.notifyDataSetChanged()
}
private fun ClearAll() {
abstractList.clear()
abstractList = ArrayList()
}
private val preferenceObject: SharedPreferences
get() = requireActivity().getSharedPreferences(PREF_FILE, 0)
private val preferenceEditObject: SharedPreferences.Editor
get() {
val pref = requireActivity().getSharedPreferences(PREF_FILE, 0)
return pref.edit()
}
private val subscribeValueFromPref: Boolean
get() = preferenceObject.getBoolean(SUBSCRIBE_KEY, false)
private fun saveSubscribeValueToPref(value: Boolean) {
preferenceEditObject.putBoolean(SUBSCRIBE_KEY, value).commit()
}
//initiate purchase on button click
fun subscribeAbstract() {
//check if service is already connected
if (billingClient!!.isReady) {
initiatePurchase()
} else {
billingClient = BillingClient.newBuilder(requireActivity()).enablePendingPurchases().setListener(this).build()
billingClient!!.startConnection(object : BillingClientStateListener {
override fun onBillingSetupFinished(billingResult: BillingResult) {
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
initiatePurchase()
} else {
Toast.makeText(requireActivity(), "Error " + billingResult.debugMessage, Toast.LENGTH_SHORT).show()
}
}
override fun onBillingServiceDisconnected() {
Toast.makeText(requireActivity(), "Service Disconnected ", Toast.LENGTH_SHORT).show()
}
})
}
}
private fun initiatePurchase() {
val skuList: MutableList<String> = ArrayList()
skuList.add(ITEM_SKU_SUBSCRIBE)
val params = SkuDetailsParams.newBuilder()
params.setSkusList(skuList).setType(BillingClient.SkuType.SUBS)
val billingResult = billingClient!!.isFeatureSupported(BillingClient.FeatureType.SUBSCRIPTIONS)
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
billingClient!!.querySkuDetailsAsync(params.build()
) { billingResult, skuDetailsList ->
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
if (skuDetailsList != null && skuDetailsList.size > 0) {
val flowParams = BillingFlowParams.newBuilder()
.setSkuDetails(skuDetailsList[0])
.build()
billingClient!!.launchBillingFlow(requireActivity(), flowParams)
} else {
//try to add subscription item "sub_example" in google play console
Toast.makeText(requireActivity(), "Item not Found", Toast.LENGTH_SHORT).show()
}
} else {
Toast.makeText(requireActivity(),
" Error " + billingResult.debugMessage, Toast.LENGTH_SHORT).show()
}
}
} else {
Toast.makeText(requireActivity(),
"Sorry Subscription not Supported. Please Update Play Store", Toast.LENGTH_SHORT).show()
}
}
override fun onPurchasesUpdated(billingResult: BillingResult, purchases: List<Purchase>?) {
//if item subscribed
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK && purchases != null) {
handlePurchases(purchases)
}
else if (billingResult.responseCode == BillingClient.BillingResponseCode.ITEM_ALREADY_OWNED) {
val queryAlreadyPurchasesResult = billingClient!!.queryPurchases(BillingClient.SkuType.SUBS)
val alreadyPurchases = queryAlreadyPurchasesResult.purchasesList
alreadyPurchases?.let { handlePurchases(it) }
}
else if (billingResult.responseCode == BillingClient.BillingResponseCode.USER_CANCELED) {
Toast.makeText(requireActivity(), "Purchase Canceled", Toast.LENGTH_SHORT).show()
}
else {
Toast.makeText(requireActivity(), "Error " + billingResult.debugMessage, Toast.LENGTH_SHORT).show()
}
}
fun handlePurchases(purchases: List<Purchase>) {
for (purchase in purchases) {
//if item is purchased
if (ITEM_SKU_SUBSCRIBE == purchase.sku && purchase.purchaseState == Purchase.PurchaseState.PURCHASED) {
if (!verifyValidSignature(purchase.originalJson, purchase.signature)) {
// Invalid purchase
// show error to user
Toast.makeText(requireActivity(), "Error : invalid Purchase", Toast.LENGTH_SHORT).show()
return
}
// else purchase is valid
//if item is purchased and not acknowledged
if (!purchase.isAcknowledged) {
val acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder()
.setPurchaseToken(purchase.purchaseToken)
.build()
billingClient!!.acknowledgePurchase(acknowledgePurchaseParams, ackPurchase)
} else {
// Grant entitlement to the user on item purchase
// restart activity
if (!subscribeValueFromPref) {
saveSubscribeValueToPref(true)
Toast.makeText(requireActivity(), "Item Purchased", Toast.LENGTH_SHORT).show()
recreate(requireActivity())
}
}
} else if (ITEM_SKU_SUBSCRIBE == purchase.sku && purchase.purchaseState == Purchase.PurchaseState.PENDING) {
Toast.makeText(requireActivity(),
"Purchase is Pending. Please complete Transaction", Toast.LENGTH_SHORT).show()
} else if (ITEM_SKU_SUBSCRIBE == purchase.sku && purchase.purchaseState == Purchase.PurchaseState.UNSPECIFIED_STATE) {
saveSubscribeValueToPref(false)
subscribeAbstract.visibility = View.VISIBLE
Toast.makeText(requireActivity(), "Purchase Status Unknown", Toast.LENGTH_SHORT).show()
}
}
}
var ackPurchase = AcknowledgePurchaseResponseListener { billingResult ->
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
//if purchase is acknowledged
// Grant entitlement to the user. and restart activity
saveSubscribeValueToPref(true)
recreate(requireActivity())
}
}
/**
* Verifies that the purchase was signed correctly for this developer's public key.
*
* Note: It's strongly recommended to perform such check on your backend since hackers can
* replace this method with "constant true" if they decompile/rebuild your app.
*
*/
private fun verifyValidSignature(signedData: String, signature: String): Boolean {
return try {
// To get key go to Developer Console > Select your app > Development Tools > Services & APIs.
val base64Key = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhBlajrk5nNjpRTPJjDtGxgtgAeKijz3Wc0KrRKKSCxxsViHl7DhsI+sUZfk4Y1jxSg4/3W1uRo/0UASM77XfJIq34bK9KYgoSAGYSuH8Z+4fK/MrPz7dHhsljkAi4GZkv8x9VhZdDdpn2GSHVFaxs8c+HBOFp9aWAErHrQhi9/7fYf39pQSTC3WkVcy9xNDZxiiKTfDN3dyEvS0XQ617ZJwqDuRdkU5Aw9+R8r+oXyURV/ekgCQkWfCUaTp/jWdySOIcR87Bde24lQAXbvJaL5uAYI4zPwO4sIP1AbXLuDtv3N2rFVmP/1cML/NHDcfI5FOoStz88jzJU26Ngpqu1QIDAQAB"
Security.verifyPurchase(base64Key, signedData, signature)
} catch (e: IOException) {
false
}
}
override fun onDestroy() {
super.onDestroy()
if (billingClient != null) {
billingClient!!.endConnection()
}
}
companion object {
const val PREF_FILE = "MyPref"
const val SUBSCRIBE_KEY = "subscribe"
const val ITEM_SKU_SUBSCRIBE = "abstract_wallpapers"
}
override fun onItemClick(item: String) {
}
}
Adapter class
class AbstractAdapter(private val mContext: Context, private val abstractList: ArrayList<Abstract>, private val click: OnItemClickListenerAbstract ) :
RecyclerView.Adapter<AbstractAdapter.ViewHolder>() {
interface OnItemClickListenerAbstract{
fun onItemClick(item:String)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.abstract_image_view, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
Glide.with(mContext)
.load(abstractList[position].abstract)
.into(holder.imageView)
holder.imageView.setOnClickListener {
val intent = Intent(mContext, AbstractPreview::class.java)
intent.putExtra("abstract", abstractList[position].abstract.toString())
Toast.makeText(mContext, "Fullscreen view", Toast.LENGTH_SHORT).show()
mContext.startActivity(intent)
}
holder.downloadBtn.setOnClickListener {
abstractList.get(position).abstract?.let { it1 -> click.onItemClick(it1) }
}
}
override fun getItemCount(): Int {
return abstractList.size
}
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val imageView: ImageView = itemView.findViewById(R.id.abstractImageView)
val downloadBtn: Button = itemView.findViewById(R.id.abstractDownloadBtn)
}
companion object
}

You have 3 parameters for the class AbstractAdapter
class AbstractAdapter(private val mContext: Context, private val abstractList: ArrayList<Abstract>, private val click: OnItemClickListenerAbstract )
but you are instantiating the object with only two parameters
AbstractAdapter(requireActivity(),it)
It's expecting the third parameter for the clickListener
AbstractAdapter(requireActivity(),it,this)
(send the Fragment as the third param)

Related

Observing live data from an API is not updating ui when data changes

I am trying to develop a football app demo. Data comes from an API from the api
It loads data as expected when app started, but when score of match changes, ui is not updating for scores by itself. I am using DiffUtil getChangePayload() to detect changes in score and status fields of Match objects which comes from the response. But it is not triggering when live match data changes. What am i missing?
P.S. I put layout in SwipeRefreshLayout and when i refresh, it gets scores and update the ui. But i want to see the match status and scores updating by itself.
Here is my code:
class MatchesViewModel(
app: Application,
private val repository: MatchesRepository
): AndroidViewModel(app) {
val matchesToday: MutableLiveData<List<Matche>> = MutableLiveData()
init {
getMatchesToday()
}
fun getMatchesToday() = viewModelScope.launch {
safeMatchesToday()
}
private suspend fun safeMatchesToday() {
if (Constants.checkConnection(this)) {
val response = repository.getMatchesToday()
if (response.isSuccessful) {
response.body()?.let {
matchesToday.postValue(it.matches)
}
}
}
}
}
class MatchesTodayFragment : Fragment() {
private var _binding: FragmentMatchesTodayBinding? =null
private val binding get() = _binding!!
private lateinit var mMatchesAdapter: MatchesAdapter
private val viewModel: MatchesViewModel by viewModels {
MatchesViewModelFactory(requireActivity().application, (requireActivity().application as MatchesApplication).repository)
}
#RequiresApi(Build.VERSION_CODES.N)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setupRecyclerView()
viewModel.matchesToday.observe(viewLifecycleOwner) { matches ->
mMatchesAdapter.differ.submitList(matches)
}
binding.srlMatchesToday.setOnRefreshListener {
viewModel.getMatchesToday()
binding.srlMatchesToday.isRefreshing = false
}
}
}
class MatchesAdapter(val fragment: Fragment): RecyclerView.Adapter<MatchesAdapter.ViewHolder>() {
private val differCallback = object: DiffUtil.ItemCallback<Matche>() {
override fun areItemsTheSame(oldItem: Matche, newItem: Matche): Boolean {
return oldItem.id == newItem.id
}
override fun areContentsTheSame(oldItem: Matche, newItem: Matche): Boolean {
return oldItem.status == newItem.status &&
oldItem.score.fullTime.home == newItem.score.fullTime.home &&
oldItem.score.fullTime.away == newItem.score.fullTime.away &&
oldItem == newItem
}
override fun getChangePayload(oldItem: Matche, newItem: Matche): Any? {
val bundle: Bundle = bundleOf()
if (oldItem.status != newItem.status) {
bundle.apply {
putString(Constants.MATCH_STATUS, newItem.status)
}
}
if (oldItem.score.fullTime.home != newItem.score.fullTime.home) {
bundle.apply {
putInt(Constants.HOME_SCORE, newItem.score.fullTime.home)
}
}
if (oldItem.score.fullTime.away != newItem.score.fullTime.away) {
bundle.apply {
putInt(Constants.AWAY_SCORE, newItem.score.fullTime.away)
}
}
if (bundle.size() == 0) {
return null
}
return bundle
}
}
val differ = AsyncListDiffer(this, differCallback)
#SuppressLint("UseCompatLoadingForDrawables")
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val match = differ.currentList[position]
holder.apply {
Glide.with(fragment)
.load(match.homeTeam.crest)
.placeholder(fragment.resources.getDrawable(R.drawable.ic_ball))
.into(ivHomeTeamImage)
Glide.with(fragment)
.load(match.awayTeam.crest)
.placeholder(fragment.resources.getDrawable(R.drawable.ic_ball))
.into(ivAwayTeamImage)
tvHomeTeamName.text = match.homeTeam.name
tvAwayTeamName.text = match.awayTeam.name
when (match.status) {
Constants.TIMED -> {
tvMatchTime.text = Constants.toTimeForTR(match.utcDate)
tvHomeTeamScore.text = "-"
tvAwayTeamScore.text = "-"
}
Constants.PAUSED -> {
tvMatchTime.text = Constants.FIRST_HALF
tvHomeTeamScore.text = match.score.fullTime.home.toString()
tvAwayTeamScore.text = match.score.fullTime.away.toString()
}
Constants.FINISHED -> {
tvMatchTime.text = Constants.FINISHED
tvHomeTeamScore.text = match.score.fullTime.home.toString()
tvAwayTeamScore.text = match.score.fullTime.away.toString()
}
else -> {
tvMatchTime.text = Constants.IN_PLAY
tvHomeTeamScore.text = match.score.fullTime.home.toString()
tvAwayTeamScore.text = match.score.fullTime.away.toString()
}
}
}
}
override fun onBindViewHolder(holder: ViewHolder, position: Int, payloads: MutableList<Any>) {
if (payloads.isNotEmpty()) {
val item = payloads[0] as Bundle
val status = item.getString(Constants.MATCH_STATUS)
val homeScore = item.getInt(Constants.HOME_SCORE)
val awayScore = item.getInt(Constants.AWAY_SCORE)
holder.apply {
tvMatchTime.text = status
tvHomeTeamScore.text = homeScore.toString()
tvAwayTeamScore.text = awayScore.toString()
Log.e("fuck", status.toString())
}
}
super.onBindViewHolder(holder, position, payloads)
}
override fun getItemCount(): Int {
return differ.currentList.size
}
}
LiveData only pushes new values if you command it to. Since you want to do it repeatedly, you need to create a loop. This is very easy to do using the liveData coroutine builder.
class MatchesViewModel(
app: Application,
private val repository: MatchesRepository
): AndroidViewModel(app) {
val matchesToday = liveData {
while (true) {
if (Constants.checkConnection(this)) {
val response = repository.getMatchesToday()
if (response.isSuccessful) {
response.body()?.let {
emit(it.matches)
}
}
}
delay(5000) // however many ms you want between fetches
}
}
}
If this is a Retrofit response, I think checking isSuccessful is redundant because body() will be non-null if and only if isSuccessful is true. So it could be simplified a bit from what you have:
class MatchesViewModel(
app: Application,
private val repository: MatchesRepository
): AndroidViewModel(app) {
val matchesToday = liveData {
while (true) {
if (Constants.checkConnection(this)) {
repository.getMatchesToday()?.body()?.matches?.let(::emit)
}
delay(5000) // however many ms you want between fetches
}
}
}

Recyclerview keep being reset

I'm facing a problem with my recycler view, I'd wanted to refresh it every second, for that I use a timer which creates new request, but I think that my recyclerview is destroyed and directly recreated, when I'm scrolling it keep always returning to the top every second. Here is my fragment, I heard about layoutmanager but don't really know how to use it, is it linked?
class DlFragment (private val context: MainActivity): Fragment(){
private var myTimer: Timer? = null
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_dl,container, false)
val dlRecyclerView = view?.findViewById<RecyclerView>(R.id.dl_list_recycle_view)
myTimer = Timer()
myTimer!!.schedule(object : TimerTask() {
override fun run() {
getDlList(dlRecyclerView)
}
}, 0, 1000)
val comfirmButton= view.findViewById<Button>(R.id.input_post_dl_button)
comfirmButton.setOnClickListener { postDl(view) }
return view
}
private fun getDlList(dlRecyclerView: RecyclerView?) {
GlobalScope.launch(Dispatchers.Main) {
try {
val response = ApiClientQnap.apiServiceQnap.getQuery(0,20,"all","all",ApiClientQnap.sid)
if (response.isSuccessful && response.body() != null) {
val content = response.body()
if (content != null) {
//println(content)
//val dlRecyclerView = view?.findViewById<RecyclerView>(R.id.dl_list_recycle_view)
dlRecyclerView?.adapter = DlAdapter(context,content.data)
}
} else { println("Error Occurred: ${response.message()}") }
} catch (e: Exception) {println("Error Occurred: ${e.message}") }
}
}
private fun postDl(view: View){
val url_Dl = view.findViewById<EditText>(R.id.input_post_dl_text)
GlobalScope.launch(Dispatchers.Main) {
try {
val response = ApiClientQnap.apiServiceQnap.postDL("Films","Films",
url_Dl.text.toString(),ApiClientQnap.sid)
if (response.isSuccessful && response.body() != null) {
val content = response.body()
println(response.body())
if (content != null) {
if(content.error == 0) {
Toast.makeText(context, "yeee", Toast.LENGTH_LONG).show()
url_Dl.text.clear()
}
else
Toast.makeText(context, "no", Toast.LENGTH_LONG).show()
}
} else { println("Error Occurred: ${response.message()}") }
} catch (e: Exception) {println("Error Occurred: ${e.message}") }
}
}
Edit: Here's my DlAdapter
class DlAdapter(
val context: MainActivity,
private var dlList: ArrayList<Data>
) : RecyclerView.Adapter<DlAdapter.ViewHolder>() {
class ViewHolder(view : View): RecyclerView.ViewHolder(view){
val dl_title = view.findViewById<TextView>(R.id.dl_title)
val dl_progress = view.findViewById<TextView>(R.id.dl_progress)
val dl_speed = view.findViewById<TextView>(R.id.dl_speed)
val progressBar = view.findViewById<ProgressBar>(R.id.progressBar)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater
.from(parent.context)
.inflate(R.layout.fragment_dl_list,parent,false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val currentDl = dlList[position]
holder.dl_title.text = currentDl.source_name
holder.progressBar.progress = (currentDl.progress!!)
when (currentDl.state) {
5 -> holder.dl_progress.text = ("Terminé")
2 -> holder.dl_progress.text = ("Arrété")
4 -> holder.dl_progress.text = ("Echec")
1 -> holder.dl_progress.text = (currentDl.progress.toString() + " % En pause")
104 -> {
holder.dl_progress.text = (currentDl.progress.toString() + " %")
var toFloat = currentDl.down_rate?.toFloat()
toFloat = toFloat?.div(1000000)
holder.dl_speed.text = (toFloat.toString()+" Mo")
}
}
}
override fun getItemCount(): Int = dlList.size
fun updateData(newData: ArrayList<Data>) {
dlList.clear()
dlList.addAll(newData)
notifyDataSetChanged()
}
}
As #hardartcore suggested, you can try to convert the RecyclerView.Adapter to a ListAdapter and use a DiffUtil.ItemCallback class.
Try to convert your adapter like this:
class DlAdapter : ListAdapter<Data, DlAdapter.ViewHolder>(DlDiffCallback()) {
class ViewHolder(view : View): RecyclerView.ViewHolder(view){
val dl_title = view.findViewById<TextView>(R.id.dl_title)
val dl_progress = view.findViewById<TextView>(R.id.dl_progress)
val dl_speed = view.findViewById<TextView>(R.id.dl_speed)
val progressBar = view.findViewById<ProgressBar>(R.id.progressBar)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater
.from(parent.context)
.inflate(R.layout.fragment_dl_list,parent,false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
// Use the getItem method to retrieve a specific item
val currentDl = getItem(position)
holder.dl_title.text = currentDl.source_name
holder.progressBar.progress = (currentDl.progress!!)
when (currentDl.state) {
5 -> holder.dl_progress.text = ("Terminé")
2 -> holder.dl_progress.text = ("Arrété")
4 -> holder.dl_progress.text = ("Echec")
1 -> holder.dl_progress.text = (currentDl.progress.toString() + " % En pause")
104 -> {
holder.dl_progress.text = (currentDl.progress.toString() + " %")
var toFloat = currentDl.down_rate?.toFloat()
toFloat = toFloat?.div(1000000)
holder.dl_speed.text = (toFloat.toString()+" Mo")
}
}
}
}
class DlDiffCallback : DiffUtil.ItemCallback<Data>() {
// Change this method comparisons based on your equality conditions
override fun areItemsTheSame(oldItem: DataItem, newItem: DataItem): Boolean = oldItem.id == newItem.id
override fun areContentsTheSame(oldItem: DataItem, newItem: DataItem): Boolean = oldItem == newItem
}
You can then update your RecyclerView adapter by using the submitList method:
val adapter = DlAdapter()
adapter.submitList(content.data)

recyclerview not showing under navigation drawer

I am trying to create a browser having a navigation drawer and a recyclerView holding Tabs for new website. Navigation drawer pops out but recyclerview not showing.
here's my adapter code:
class NavigationTabAdapter (context: Context, contentData:ArrayList<Tab>) :
RecyclerView.Adapter<NavigationTabAdapter.NavigationViewHolder>() {
var mcontext:Context?=null
var contentList:ArrayList<Tab>?=null
var tabInterface:TabInterface?=null
init {
mcontext=context
contentList=contentData
tabInterface=context as TabInterface
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NavigationViewHolder {
val itemView=LayoutInflater.from(parent.context).inflate(R.layout.row_custom_recycler_tab, parent, true)
return NavigationViewHolder(itemView)
}
override fun onBindViewHolder(holder: NavigationViewHolder, position: Int) {
holder.row_text?.setText(contentList?.get(position)?.url)
holder.row_img_remove?.setOnClickListener {
if (contentList!!.size>1)
{
tabInterface?.deleteItem(contentList?.get(position)?.id!!,position)
}
}
here's my mainActivity xml:
enter code //Navigation drawer
var drawerLayout:DrawerLayout?=null
var tabsDatabase:TabsDatabase?=null
var navigationRecyclerView:RecyclerView?=null
var navigationTabAdapter:NavigationTabAdapter?=null
var listWebLinks:ArrayList<Tab>?=null
var itemClickedPosition:Int=-1
var idForClickedPosition:Int=-1
var url:String?=null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val toolbar=findViewById<Toolbar>(R.id.appBar)
setSupportActionBar(toolbar)
drawerLayout=findViewById(R.id.drawer_layout)
val toggle=ActionBarDrawerToggle(this#MainActivity,drawerLayout,toolbar,
R.string.navigation_drawer_open,R.string.navigation_drawer_close)
drawerLayout?.addDrawerListener(toggle)
toggle.syncState()
tabsDatabase= TabsDatabase(this)
navigationRecyclerView=findViewById(R.id.nav_recycler_view)
navigationRecyclerView?.layoutManager=LinearLayoutManager(this)
navigationRecyclerView?.itemAnimator=DefaultItemAnimator()
listWebLinks= ArrayList()
searchView = findViewById(R.id.search_View)
webview = findViewById(R.id.webImage)
progressBar = findViewById(R.id.progressBar)
inputMethodManager=getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
mainScreen=findViewById(R.id.mainScreen)
webview!!.settings.javaScriptEnabled = true
webview!!.webViewClient = object :WebViewClient() {
override fun shouldOverrideUrlLoading(view: WebView?,
url:String
): Boolean {
view!!.loadUrl(url)
return true
}
override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
super.onPageStarted(view, url, favicon)
if (url.equals("about:blank"))
{
mainScreen?.visibility=View.VISIBLE
webview?.visibility
return
}
if (!(progressBar!!.isShown))
{
progressBar?.visibility = View.VISIBLE
view!!.visibility=View.GONE
}
searchView!!.onActionViewExpanded()
searchView!!.setQuery(webview!!.url,false)
searchView!!.clearFocus()
}
override fun onPageFinished(view: WebView?, url: String?) {
super.onPageFinished(view, url)
if (progressBar!!.isShown)
{
progressBar!!.visibility = View.GONE
view!!.visibility=View.VISIBLE
}
findViewById<ImageView>(R.id.backwardImage)!!.isEnabled=true
findViewById<ImageView>(R.id.backwardImage)!!.setImageResource(R.drawable.undo_blue)
if (!(webview!!.canGoForward()))
{
findViewById<ImageView>(R.id.forwardImage)?.isEnabled=false
findViewById<ImageView>(R.id.forwardImage)?.setImageResource(R.drawable.redo_blue)
}
findViewById<ImageView>(R.id.homeImage)?.isEnabled=true
findViewById<ImageView>(R.id.homeImage)?.setImageResource(R.drawable.home_orange)
if (itemClickedPosition!=-1)
{
updateItem(idForClickedPosition,url)
}
}
}
searchView?.setOnQueryTextListener(object :SearchView.OnQueryTextListener{
override fun onQueryTextSubmit(query: String): Boolean {
try {
val bool:Boolean=URLUtil.isValidUrl(query)
if (bool)
{
webview!!.loadUrl(query)
}
else
{
webview!!.loadUrl("https://"+query.replace("",""))
findViewById<LinearLayout>(R.id.mainScreen).visibility = View.GONE
}
findViewById<ImageView>(R.id.backwardImage).isEnabled=true
findViewById<ImageView>(R.id.backwardImage).setImageResource(R.drawable.undo_orange)
findViewById<ImageView>(R.id.homeImage)?.isEnabled=true
findViewById<ImageView>(R.id.homeImage).setImageResource(R.drawable.home_orange)
inputMethodManager!!.hideSoftInputFromWindow(currentFocus?.windowToken,0)
}
catch (e:Exception)
{
Toast.makeText(this#MainActivity,""+e.printStackTrace(),Toast.LENGTH_SHORT).show()
}
return true
}
override fun onQueryTextChange(newText: String?): Boolean {
return false
}
})
try {
listWebLinks = tabsDatabase?.readData()
if (listWebLinks!!.size == 0)
{
tabsDatabase?.insertData("Home Page")
listWebLinks = tabsDatabase?.readData()
itemClickedPosition = 0
} else {
itemClickedPosition = listWebLinks!!.size - 1
}
navigationTabAdapter = NavigationTabAdapter(this, listWebLinks!!)
navigationRecyclerView?.adapter = navigationTabAdapter
navigationTabAdapter?.notifyDataSetChanged()
navigationRecyclerView?.setHasFixedSize(true)
} catch (e: Exception) {
e.printStackTrace()
}
database file
class TabsDatabase:SQLiteOpenHelper {
constructor(context: Context) : super(context, DB_NAME, null, DB_VERSION)
override fun onCreate(sqLiteDatabase: SQLiteDatabase?) {
sqLiteDatabase?.execSQL("CREATE TABLE" + TABLE_NAME + "(" + COL_ID +
" INTEGER PRIMARY KEY," + COL_URL + "TEXT);")
}
override fun onUpgrade(sqLiteDatabase: SQLiteDatabase?, p1: Int, p2: Int) {
sqLiteDatabase?.execSQL("Drop table IF EXISTS" + TABLE_NAME)
}
fun insertData(url:String):Boolean?{
var result = true
try{
val db= this.writableDatabase
var cv=ContentValues()
cv.put(COL_URL,url)
db.insert(TABLE_NAME,null,cv)>0
db.close()
}catch (e:Exception) {
result = false
}
return result
}
fun updateData(id:Int,url:String):Boolean?{
var result = true
try{
val db= this.writableDatabase
var cv=ContentValues()
cv.put(COL_URL,url)
db.update(TABLE_NAME,cv, "id=?", arrayOf(id.toString())) >0
db.close()
}catch (e:Exception)
{
result= false
}
return true
}
fun readData():ArrayList<Tab>{
var list=ArrayList<Tab>()
var db=this.readableDatabase
val query="select * from" + TABLE_NAME + "ORDER BY id ASC"
val result=db.rawQuery(query,null)
if(result.moveToFirst())
{
do{
var tab = Tab()
tab.id=result.getInt(result.getColumnIndex(COL_ID).toInt())
tab.url=result.getString(result.getColumnIndex(COL_URL))
list.add(tab)
}while (result.moveToNext())
}
result.close()
db.close()
return list
}
fun deleteData(id:Int) {
val db=this.writableDatabase
db.delete(TABLE_NAME, COL_ID + "=" +id,null)
db.close()
}

Item on recycler-view disappear after changing to a different activity and back again

A very newbie programmer here and not a good English typer. Im trying to create a checker for purchase that already made previous using the PurchaseHistoryResponseListener. And When a checker found something, it will add to a list and then feed the recyclerview_MYBook with that data. The issue is that when launching the app, the data is flow through the recyclerview_MYBook perfectly, but when moving to different activity and going back to the previous activity through a different method (button click) the data on the recyclerview_MYBook doesn't show up, only through a conventional back button, the data on the recyclerview show up. Below here is my noob code
class MainActivity : AppCompatActivity(), PurchasesUpdatedListener {
private lateinit var billingClient: BillingClient
private lateinit var blogadapternew: BlogRecyclerAdapterNew
private lateinit var blogadapterpremium: BlogRecyclerAdapterPremium
private lateinit var blogadapterfree: BlogRecyclerAdapterFree
private lateinit var blogadaptermybook: BlogRecyclerAdapterMyBook
private lateinit var auth: FirebaseAuth
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
auth = FirebaseAuth.getInstance()
//FirebaseAuth.getInstance().signOut()
window.setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE)
window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN)
setContentView(R.layout.activity_main)
recycler_viewNew.layoutManager = LinearLayoutManager(this, RecyclerView.HORIZONTAL,false)
recycler_viewNew.adapter= BlogRecyclerAdapterNew()
recycler_viewPremium.layoutManager = LinearLayoutManager(this,RecyclerView.HORIZONTAL,false)
recycler_viewPremium.adapter= BlogRecyclerAdapterPremium()
recycler_viewFree.layoutManager = LinearLayoutManager(this,RecyclerView.HORIZONTAL,false)
recycler_viewFree.adapter= BlogRecyclerAdapterFree()
recycler_viewMyBook.layoutManager = LinearLayoutManager(this,RecyclerView.HORIZONTAL,false)
recycler_viewMyBook.adapter= BlogRecyclerAdapterMyBook()
if (supportActionBar != null)
supportActionBar?.hide()
setupBillingClient()
initrecyclerView()
initrecyclerViewPremium()
initrecyclerViewFree()
initrecyclerViewMyBook()
addDataSetNew()
addDataSetPremium()
addDataSetFree()
Logo.setOnClickListener{
val intent = Intent(MonstaLogo.context, MainActivity::class.java)
MonstaLogo.context.startActivity(intent)
}
MainFeaturedButton.setOnClickListener {
val intent = Intent(MainFeaturedButton.context, MainActivity::class.java)
MainFeaturedButton.context.startActivity(intent)
}
MainNewButton.setOnClickListener {
val intent = Intent(MainNewButton.context, NewActivity::class.java)
MainNewButton.context.startActivity(intent)
}
NewMore.setOnClickListener{
val intent = Intent(NewMore.context, NewActivity::class.java)
NewMore.context.startActivity(intent)
}
MainPremiumButton.setOnClickListener {
val intent = Intent(MainPremiumButton.context, PremiumActivity::class.java)
MainPremiumButton.context.startActivity(intent)
}
PremiumMore.setOnClickListener{
val intent = Intent(PremiumMore.context, PremiumActivity::class.java)
PremiumMore.context.startActivity(intent)
}
MainFreeButton.setOnClickListener {
val intent = Intent(MainFreeButton.context, FreeActivity::class.java)
MainFreeButton.context.startActivity(intent)
}
FreeMore.setOnClickListener {
val intent = Intent(FreeMore.context, FreeActivity::class.java)
FreeMore.context.startActivity(intent)
}
MainMyBookButton.setOnClickListener {
val intent = Intent(MainMyBookButton.context, MyBookActivity::class.java)
MainMyBookButton.context.startActivity(intent)
}
MyBookMore.setOnClickListener {
val intent = Intent(MyBookMore.context, MyBookActivity::class.java)
MyBookMore.context.startActivity(intent)
}
}
private fun setupBillingClient() {
billingClient = BillingClient.newBuilder(this)
.enablePendingPurchases()
.setListener(this)
.build()
billingClient.startConnection(object : BillingClientStateListener {
override fun onBillingSetupFinished(billingResult: BillingResult) {
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
// The BillingClient is ready. You can query purchases here.
println("Setup Billing Done")
PurchaseHistoryResponseListener()
}
}
override fun onBillingServiceDisconnected() {
// Try to restart the connection on the next request to
// Google Play by calling the startConnection() method.
println("Failed")
setupBillingClient()
println("Restart Connection")
}
})
}
override fun onPurchasesUpdated(
billingResult: BillingResult?,
purchases: MutableList<Purchase>?
) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
private fun PurchaseHistoryResponseListener (){
billingClient.queryPurchaseHistoryAsync(BillingClient.SkuType.INAPP) {
responseCode, result ->
// println("queryPurchasesAsync INAPP results: ${result?.size}")
// println("Getting Purchase History")
println("$result")
val dataMyBook1 = DataSourceMyBook.createDataSet()
if ("testcode1" in result.toString()) {
println("found it 1")
dataMyBook1.add((BlogPost( "BookName","Link","No")))
}
if ("testcode2" in result.toString()) {
println("found it 2")
dataMyBook1.add((BlogPost( "BookName","Link","No")))
}
if ("testcode3" in result.toString()) {
println("found it 3")
dataMyBook1.add((BlogPost( "BookName","Link","No")))
}
blogadaptermybook.submitList(dataMyBook1)
println(dataMyBook1)
}
}
private fun addDataSetNew(){
val dataNew = DataSourceNew.createDataSet()
blogadapternew.submitList(dataNew)
}
private fun addDataSetPremium(){
val dataPremium = DataSourcePremium.createDataSet()
blogadapterpremium.submitList(dataPremium)
}
private fun addDataSetFree(){
val dataFree = DataSourceFree.createDataSet()
blogadapterfree.submitList(dataFree)
}
/*private fun addDataSetMyBook(){
val dataMyBook1 = DataSourceMyBook.createDataSet()
blogadaptermybook.submitList(dataMyBook1)
}*/
/*private fun addDataSetMyBook(){
val dataMyBook1 = DataSourceMyBook.createDataSet()
billingClient.queryPurchaseHistoryAsync(BillingClient.SkuType.INAPP) {
responseCode, result ->
println("$result")
if ("bbbg_s2_c1_testcode1" in result.toString()){
dataMyBook1.add((BlogPost( "Mini Comic 1","Link","No")))
}
if ("bbbg_s2_c1_testcode2" in result.toString()){
dataMyBook1.add((BlogPost( "Mini Comic 2","Link","No")))
}
if ("bbbg_s2_c1_testcode3" in result.toString()){
dataMyBook1.add((BlogPost( "Mini Comic 3","Link","No")))
}
blogadaptermybook.submitList(dataMyBook1)
}}*/
/*dataMyBook.add((BlogPost( "Mini Comic 1","Link","No")))
dataMyBook.add((BlogPost( "Mini Comic 1","Link","No")))
dataMyBook.add((BlogPost( "Mini Comic 1","Link","No")))*/
private fun initrecyclerView(){
recycler_viewNew.apply {
layoutManager = LinearLayoutManager(this#MainActivity,RecyclerView.HORIZONTAL,false)
val topSpacingItemDecoration = TopSpacingItemDecoration(padding = 30)
addItemDecoration(topSpacingItemDecoration)
blogadapternew = BlogRecyclerAdapterNew()
adapter = blogadapternew
}
}
private fun initrecyclerViewPremium(){
recycler_viewPremium.apply {
layoutManager = LinearLayoutManager(this#MainActivity,RecyclerView.HORIZONTAL,false)
val topSpacingItemDecoration = TopSpacingItemDecoration(padding = 30)
addItemDecoration(topSpacingItemDecoration)
blogadapterpremium = BlogRecyclerAdapterPremium()
adapter = blogadapterpremium
}
}
private fun initrecyclerViewFree(){
recycler_viewFree.apply {
layoutManager = LinearLayoutManager(this#MainActivity,RecyclerView.HORIZONTAL,false)
val topSpacingItemDecoration = TopSpacingItemDecoration(padding = 30)
addItemDecoration(topSpacingItemDecoration)
blogadapterfree = BlogRecyclerAdapterFree()
adapter = blogadapterfree
}
}
private fun initrecyclerViewMyBook(){
recycler_viewMyBook.apply {
layoutManager =
LinearLayoutManager(this#MainActivity, RecyclerView.HORIZONTAL, false)
val topSpacingItemDecoration = TopSpacingItemDecoration(padding = 30)
addItemDecoration(topSpacingItemDecoration)
blogadaptermybook = BlogRecyclerAdapterMyBook()
adapter = blogadaptermybook
}
}
public override fun onStart() {
super.onStart()
val currentUser = auth.currentUser
updateUI(currentUser)
}
private fun updateUI(currentUser: FirebaseUser?) {
if (currentUser != null) {
AccountSettingButton.setImageResource(R.drawable.profileicon)
}
}
}
Here is adapter
class BlogRecyclerAdapterMyBook : RecyclerView.Adapter() {
private var items: List<BlogPost> = ArrayList()
private var items2: List<BlogPost> = ArrayList()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return BlogViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.layout_blog_list_item_mybook,
parent,
false
)
)
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when (holder) {
is BlogViewHolder -> {
holder.bind(items.get(position))
holder.bind(items2.get(position))
}
}
}
override fun getItemCount(): Int {
return items.size
}
fun submitList(bloglist: List<BlogPost>) {
items = bloglist
items2 = bloglist
}
class BlogViewHolder constructor(itemView: View) : RecyclerView.ViewHolder(itemView) {
val blogImage: ImageButton = itemView.blog_imagemybook
val blogTitle: TextView = itemView.blog_titlemybook
val premiumImage: ImageView = itemView.premiumicon
fun bind(blogPost: BlogPost) {
blogTitle.setText(blogPost.title)
val requestOptions = RequestOptions()
.placeholder(R.drawable.mocksplash)
.error(R.drawable.disconnect)
Glide.with(itemView.blog_imagemybook)
.applyDefaultRequestOptions(requestOptions)
.load(blogPost.image)
.into(blogImage)
blogImage.setOnClickListener {
Toast.makeText(blogImage.context, "<<Swipe left<<", Toast.LENGTH_SHORT).show()
val intent = Intent(blogTitle.context, ComicReadingActivity::class.java)
var KomikName = blogTitle.text.toString()
intent.putExtra("KomikName",Name)
blogImage.context.startActivity(intent)
}
}
}
}
and here the data source file where that will store the data for the adapter
class DataSourceMyBook{
companion object{
fun createDataSet(): ArrayList<BlogPost> {
val dataMyBook1 = ArrayList<BlogPost>()
return dataMyBook1
}
}
}

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()
}
}