Error while using recycler view in fragments - android-studio

I am trying to use the recycler view in fragments.
But the app is crashing and showing this error.
The error shown is:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.mridul.expressions, PID: 7690
java.lang.RuntimeException: Cannot create an instance of class com.mridul.expressions.DiaryViewModel
at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:275)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:187)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:150)
at com.mridul.expressions.DiaryFragment.onViewCreated(DiaryFragment.kt:31)
at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:2987)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:546)
at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:282)
at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:2189)
at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:2106)
at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:2002)
at androidx.fragment.app.FragmentManager$5.run(FragmentManager.java:524)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7523)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:941)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Constructor.newInstance0(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:267)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:187) 
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:150) 
at com.mridul.expressions.DiaryFragment.onViewCreated(DiaryFragment.kt:31) 
at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:2987) 
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:546) 
at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:282) 
at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:2189) 
at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:2106) 
at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:2002) 
at androidx.fragment.app.FragmentManager$5.run(FragmentManager.java:524) 
at android.os.Handler.handleCallback(Handler.java:938) 
at android.os.Handler.dispatchMessage(Handler.java:99) 
at android.os.Looper.loop(Looper.java:223) 
at android.app.ActivityThread.main(ActivityThread.java:7523) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:941) 
Caused by: java.lang.RuntimeException: cannot find implementation for com.mridul.expressions.DiaryDatabase. DiaryDatabase_Impl does not exist
at androidx.room.Room.getGeneratedImplementation(Room.java:97)
at androidx.room.RoomDatabase$Builder.build(RoomDatabase.java:1358)
at com.mridul.expressions.DiaryDatabase$Companion.getDatabase(DiaryDatabase.kt:25)
at com.mridul.expressions.DiaryViewModel.<init>(DiaryViewModel.kt:14)
at java.lang.reflect.Constructor.newInstance0(Native Method) 
at java.lang.reflect.Constructor.newInstance(Constructor.java:343) 
at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:267) 
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:187) 
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:150) 
at com.mridul.expressions.DiaryFragment.onViewCreated(DiaryFragment.kt:31) 
at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:2987) 
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:546) 
at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:282) 
at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:2189) 
at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:2106) 
at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:2002) 
at androidx.fragment.app.FragmentManager$5.run(FragmentManager.java:524) 
at android.os.Handler.handleCallback(Handler.java:938) 
at android.os.Handler.dispatchMessage(Handler.java:99) 
at android.os.Looper.loop(Looper.java:223) 
at android.app.ActivityThread.main(ActivityThread.java:7523) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:941)
 
My Fragment.kt file:
package com.mridul.expressions
import android.app.Application
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import kotlinx.android.synthetic.main.fragment_diary.*
import kotlinx.android.synthetic.main.fragment_diary.view.*
import java.util.Calendar.getInstance
class DiaryFragment : Fragment(), IDiaryRVAdapter {
lateinit var viewModel: DiaryViewModel
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val adapter= this.context?.let { DiaryRVAdapter(it,this) }
diaryRecyclerView.adapter=adapter
diaryRecyclerView.layoutManager=LinearLayoutManager(
this.context)
val application: Application =requireActivity().application
viewModel=ViewModelProvider(this,
ViewModelProvider.AndroidViewModelFactory.getInstance(application)).get(DiaryViewModel::class.java)
viewModel.allDiary.observe(viewLifecycleOwner, Observer {list->
list?.let {
adapter?.updateList(it)
}
})
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view= inflater.inflate(R.layout.fragment_diary, container, false)
view.saveDiaryButton.setOnClickListener {
val diaryText=dateInDiary.text.toString()
if (diaryText.isNotEmpty()){
viewModel.insertNode(Diary(diaryText))
}
dateInDiary.text = null
}
return view
}
override fun onItemClicked(diary: Diary) {
viewModel.deleteNode(diary)
}
}
My Adapter is:
class DiaryRVAdapter(private val context: Context,
private val listner:IDiaryRVAdapter) : RecyclerView.Adapter<DiaryRVAdapter.DiaryViewHolder>()
{
val allNotes=ArrayList<Diary>()
inner class DiaryViewHolder(itemView:View) : RecyclerView.ViewHolder(itemView){
val textView=itemView.findViewById<TextView>(R.id.item)
val deletButton=itemView.findViewById<ImageView>(R.id.deleteButton)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DiaryViewHolder {
valviewHolder=DiaryViewHolder(LayoutInflater.from(context).inflate
(R.layout.item_diary,parent,false))
viewHolder.deletButton.setOnClickListener{
listner.onItemClicked(allNotes[viewHolder.adapterPosition])}
return viewHolder
}
override fun onBindViewHolder(holder: DiaryViewHolder, position: Int) {
val currentNotes=allNotes[position]
holder.textView.text = currentNotes.text
}
override fun getItemCount(): Int {
return allNotes.size
}
fun updateList(newList: List<Diary>){
allNotes.clear()
allNotes.addAll(newList)
notifyDataSetChanged()
}
}
interface IDiaryRVAdapter{
fun onItemClicked(diary: Diary)
}
And layout file of fragment is:
<TextView
android:id="#+id/dearDiaryTxt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:text="#string/dear_diary"
android:textSize="20sp"
android:textColor="#d500f9"
android:layout_margin="12dp"
/>
<EditText
android:id="#+id/dateInDiary"
android:layout_width="match_parent"
android:layout_height="300dp"
app:layout_constraintTop_toBottomOf="#id/dearDiaryTxt"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:hint="Date-\nHow was your day🤗🤗🤗"
android:gravity="top"
android:background="#drawable/edit_text_round_box"
android:layout_marginTop="20dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
/>
<Button
android:id="#+id/saveDiaryButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="#id/dateInDiary"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:text="Save"
android:textColor="#color/white"
android:layout_margin="5dp"
/>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/diaryRecyclerView"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="#id/saveDiaryButton"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="5dp"
tools:listitem="#layout/item_diary"
/>
And item is:
<TextView
android:id="#+id/item"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="#+id/deleteButton"
tools:text="Mridul"
android:textSize="16sp"
android:padding="12dp"
android:textColor="#3e2723"
/>
<ImageView
android:id="#+id/deleteButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="16dp"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="#id/item"
app:layout_constraintTop_toTopOf="#id/item"
android:src="#drawable/ic_baseline_delete_outline_24"
/>
Please Help anyone.

Related

I suddenly get an unresolved reference error in my adapter class for the RecyclerView

everyone. I suddenly get an Unresolved reference error displayed in my layouts in RecyclerView. I've already restarted Android Studio, rebuilt and cleaned the project. All without success.
AddNewHomeFragment.kt:
class AddNewHomeFragment : Fragment() {
listImg = ArrayList()
var rv_img:RecyclerView = view.findViewById(R.id.recyclerViewImgs)
rv_img.layoutManager = GridLayoutManager(requireContext(),3)
adapter = CustomerAdapter(requireContext(),listImg){
var intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
startActivityForResult(intent,IMAGE_REQUEST)
}
rv_img.adapter = adapter
...
}
My CustomAdapter for RecyclerView:
class CustomerAdapter(val context: Context,
private val listImg:ArrayList<Int>, private val onClickFunction: ((Any?) -> Unit)? = null):RecyclerView.Adapter<CustomerAdapter.MyCustomViewHolder>() {
class MyCustomViewHolder(view: View):RecyclerView.ViewHolder(view) {
//Unresolved reference: customImg
val customImg:ImageView = view.findViewById(R.id.customImg)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyCustomViewHolder {
//Unresolved reference: single_img
val inflate = LayoutInflater.from(context).inflate(R.layout.single_img,parent,false)
return MyCustomViewHolder(inflate)
}
override fun onBindViewHolder(holder: MyCustomViewHolder, position: Int) {
holder.customImg.setImageResource(listImg[position])
holder.customImg.setOnClickListener {
this#CustomerAdapter.onClickFunction?.invoke(listImg[position])
}
}
override fun getItemCount(): Int {
return listImg.size
}
}
fragment_add_new_home.xml:
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerViewImgs"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</androidx.recyclerview.widget.RecyclerView>
single_img.xml:
<?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"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:layout_marginEnd="5dp"
android:layout_marginBottom="8dp"
android:background="#drawable/layout_for_imgs"
android:id="#+id/customImg"
app:layout_constraintDimensionRatio="1"
android:layout_width="0dp"
android:layout_height="0dp"
android:scaleType="centerCrop"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:src="#drawable/ic_baseline_add_home_24">
</ImageView>
</androidx.constraintlayout.widget.ConstraintLayout>

How to show recyclerview in fragment after click on search field?

How to make my recicle view visible on search field click in fragment and how to set search in this View?
Logcat shows, that "No adapter attached; skipping layout"
Code of home_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
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"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_margin="8dp">
<LinearLayout
android:id="#+id/linearLayout"
android:layout_width="330dp"
android:layout_height="30dp"
android:gravity="center_vertical"
android:orientation="horizontal"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:layout_width="62dp"
android:layout_height="match_parent"
android:src="#drawable/ic_baseline_search_24" />
<EditText
android:id="#+id/searchField"
android:layout_width="270dp"
android:layout_height="60dp"
android:ems="10"
android:hint="Поиск"
android:inputType="textPersonName"
tools:ignore="SpeakableTextPresentCheck" />
<ListView
android:id="#+id/listSearch"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="30dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:listitem="#layout/list_item" />
</androidx.constraintlayout.widget.ConstraintLayout>
Code of HomeFragment
package com.example.booksh
import android.os.Bundle
import android.view.View
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.booksh.databinding.FragmentHomeBinding
class HomeFragment: Fragment(R.layout.fragment_home) {
private lateinit var binding: FragmentHomeBinding
private lateinit var newRecyclerView: RecyclerView
private lateinit var newArrayList: ArrayList<Books>
lateinit var imageId: Array<Int>
lateinit var heading: Array<String>
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
binding = FragmentHomeBinding.inflate(layoutInflater)
super.onViewCreated(binding.root, savedInstanceState)
// Поисковой список
imageId = arrayOf(
R.drawable.a,
R.drawable.b,
R.drawable.c,
R.drawable.d,
R.drawable.e,
R.drawable.f,
R.drawable.h,
R.drawable.i,
R.drawable.j
)
heading = arrayOf(
"Война и мир",
"Капитанская дочка",
"Раковый корпус",
"Мастер и маргарита",
"Муму",
"О дивный новый мир",
"Скотный двор",
"Портрет Дориана Грея",
"Отель с привидениями"
)
//Переменные для выпадающего списка на главной странице - поиск книг
newRecyclerView = binding.recyclerView
newRecyclerView.layoutManager = LinearLayoutManager(this.context)
newRecyclerView.setHasFixedSize(true)
newArrayList = arrayListOf()
getUserData()
}
//Заносим в список данные о книгах
private fun getUserData() {
for (i in imageId.indices){
val book = Books(imageId[i], heading[i])
newArrayList.add(book)
}
newRecyclerView.adapter = MyAdapter(newArrayList)
}
}
Code of adapter
package com.example.booksh
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.imageview.ShapeableImageView
class MyAdapter(private var booksList: ArrayList<Books>) : RecyclerView.Adapter<MyAdapter.MyViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val itemView = LayoutInflater.from(parent.context).inflate(R.layout.list_item,
parent, false)
return MyViewHolder(itemView)
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val currentItem = booksList[position]
holder.titleImage.setImageResource(currentItem.titleImage)
holder.tvHeading.text = currentItem.heading
}
override fun getItemCount(): Int {
return booksList.size
}
class MyViewHolder(itemView: View): RecyclerView.ViewHolder(itemView){
val titleImage : ShapeableImageView = itemView.findViewById(R.id.list_item_icon)
val tvHeading: TextView = itemView.findViewById(R.id.list_item_text)
}
}
I made a ricycle view for main activity without visibility change, but it was shown in every fragment of my app. Then I copied all code connected with recyclerView to fragment home (xml, kt), but it became invisible whether I click on the search field or not.

I have implemented the ability for my app to take a picture. Why is the file path null when I try to save the image locally?

This is my very first simple and almost-complete Android application.
My Goal
I want to take a picture with the device's built-in camera, display it on the ImageButton in that same Fragment, and have it save to the device locally so that I can reference its file path and add it to my custom SQLite Database to display in my RecyclerView on a different Fragment.
Background Info
My app is built on top of a custom SQLite Database backend containing two tables, users and their associated books that they've added to the app to be displayed in a RecyclerView.
The app is built entirely with Kotlin. Navigation is done using Android Jetpack's Navigation with a navigation graph (currently not using SafeArgs), and the entire app is run from a single MainActivity that holds multiple Fragments. I have a Fragment containing a RecyclerView, and this RecyclerView contains an ImageView where I hope to display the thumbnail of the picture that the user took with their device. To display images, I am using the 3rd-party Picasso library. The minimum API that my app is targeting is API 23. I am using the deprecated Camera API because Camera2 and CameraX had pretty much no improvement of my issue, so I fell back on this and it's not helping either.
My manifest contains these bits of code for Write access and Camera access permissions:
<uses-feature android:name="android.hardware.camera"
android:required="false"
/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.CAMERA"/>
My file provider is set up as follows:
<provider
android:authorities="<my_package_authority>.fileprovider"
android:name="androidx.core.content.FileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths"
/>
</provider>
My file_paths.xml file is here:
<?xml version="1.0" encoding="utf-8" ?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-files-path
name="my_images"
path="Android/data/<my_package_authority>/files/Pictures">
</external-files-path>
<external-files-path
name="my_debug_images"
path="/storage/emulated/0/Android/data/<my_package_authority>/files/Pictures">
</external-files-path>
<external-files-path
name="my_root_images"
path="/">
</external-files-path>
</paths>
Here is my MainActivity.kt, which I use basically to store the request codes as well as the userID and bookID of the users and their books to upload to my database (patch-up solution to be better implemented later):
class MainActivity : AppCompatActivity() {
companion object {
val REQUEST_CAMERA_PERMISSIONS_CODE = 1
val REQUEST_CAMERA_USAGE = 2
var userID: Int? = null
var bookID: Int? = null
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
The .xml is completely unchanged and default.
Below is the .xml and .kt files for CreateBookFragment, the Fragment on which the user is going to add a book to their personal library.
fragment_create_book.xml (I am aware some of the bottom buttons clip out of the screen, depending on screen size. I plan to fix after the camera functionality is implemented)
<?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:id="#+id/clCreateBookRoot"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/grey"
tools:context=".CreateBookFragment">
<TextView
android:id="#+id/tvCreateBookTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:fontFamily="cursive"
android:shadowColor="#color/deep_red"
android:shadowDx="1.5"
android:shadowDy="1.5"
android:shadowRadius="1.5"
android:text="#string/add_book"
android:textColor="#color/deep_red"
android:textSize="55sp"
android:textStyle="bold"
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.024" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/tvCreateBookTitle">
<ImageButton
android:id="#+id/ibCreateBookImage"
android:layout_width="75dp"
android:layout_height="75dp"
android:layout_gravity="center"
android:backgroundTint="#color/deep_red"
android:contentDescription="#string/add_a_picture_to_the_book"
android:src="#android:drawable/ic_menu_camera" />
<EditText
android:id="#+id/etCreateBookTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="50dp"
android:layout_marginTop="3dp"
android:layout_marginEnd="50dp"
android:layout_marginBottom="5dp"
android:ems="10"
android:hint="#string/title"
android:importantForAutofill="no"
android:inputType="textPersonName"
android:minHeight="48dp"
android:textColorHint="#color/black"
tools:ignore="TextContrastCheck" />
<EditText
android:id="#+id/etCreateBookAuthor"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="50dp"
android:layout_marginTop="3dp"
android:layout_marginEnd="50dp"
android:layout_marginBottom="5dp"
android:ems="10"
android:hint="#string/author"
android:importantForAutofill="no"
android:inputType="textPersonName"
android:minHeight="48dp"
android:textColorHint="#color/black"
tools:ignore="TextContrastCheck" />
<EditText
android:id="#+id/etCreateBookPages"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="50dp"
android:layout_marginTop="3dp"
android:layout_marginEnd="50dp"
android:layout_marginBottom="5dp"
android:ems="10"
android:hint="#string/total_pages"
android:importantForAutofill="no"
android:inputType="number"
android:minHeight="48dp"
android:textColorHint="#color/black"
tools:ignore="TextContrastCheck" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="50dp"
android:layout_marginTop="3dp"
android:layout_marginEnd="50dp"
android:layout_marginBottom="5dp"
android:orientation="horizontal">
<TextView
android:id="#+id/tvCreateBookGenre"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="4dp"
android:layout_marginEnd="10dp"
android:text="#string/genre"
android:textColor="#color/black"
android:textSize="18sp" />
<Spinner
android:id="#+id/spinCreateBookGenre"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="#string/genre"
android:importantForAutofill="no"
android:inputType="textPersonName"
android:minHeight="48dp"
android:textColorHint="#color/black"
tools:ignore="TextContrastCheck,SpeakableTextPresentCheck" />
</LinearLayout>
<EditText
android:id="#+id/etCreateBookPublisher"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="50dp"
android:layout_marginTop="3dp"
android:layout_marginEnd="50dp"
android:layout_marginBottom="5dp"
android:ems="10"
android:hint="#string/publisher"
android:importantForAutofill="no"
android:inputType="textPersonName"
android:minHeight="48dp"
android:textColorHint="#color/black"
tools:ignore="TextContrastCheck" />
<EditText
android:id="#+id/etCreateBookYearPublished"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="50dp"
android:layout_marginTop="3dp"
android:layout_marginEnd="50dp"
android:layout_marginBottom="5dp"
android:ems="10"
android:hint="#string/year_published"
android:importantForAutofill="no"
android:inputType="number"
android:minHeight="48dp"
android:textColorHint="#color/black"
tools:ignore="TextContrastCheck" />
<EditText
android:id="#+id/etCreateBookISBN"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="50dp"
android:layout_marginTop="3dp"
android:layout_marginEnd="50dp"
android:layout_marginBottom="5dp"
android:ems="10"
android:hint="#string/isbn_code"
android:importantForAutofill="no"
android:inputType="textPersonName"
android:minHeight="48dp"
android:textColorHint="#color/black" />
<EditText
android:id="#+id/etCreateBookStarRating"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="50dp"
android:layout_marginTop="3dp"
android:layout_marginEnd="50dp"
android:layout_marginBottom="5dp"
android:ems="10"
android:hint="#string/star_rating_1_5"
android:importantForAutofill="no"
android:inputType="number"
android:minHeight="48dp"
android:textColorHint="#color/black"
tools:ignore="TextContrastCheck" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="3dp"
android:gravity="center"
android:orientation="horizontal">
<Button
android:id="#+id/btnCancelCreateBook"
style="#style/cancel_button_style"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#android:string/cancel" />
<Button
android:id="#+id/btnSaveCreateBook"
style="#style/save_button_style"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/add" />
</LinearLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
CreateBookFragment.kt
import android.app.Activity
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Bundle
import android.os.Environment
import android.provider.MediaStore
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.*
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.core.content.FileProvider
import androidx.navigation.NavController
import androidx.navigation.Navigation
import com.squareup.picasso.MemoryPolicy
import com.squareup.picasso.NetworkPolicy
import com.squareup.picasso.Picasso
import java.io.File
import java.io.IOException
import java.text.SimpleDateFormat
import java.util.*
class CreateBookFragment : Fragment(), View.OnClickListener, AdapterView.OnItemSelectedListener {
private var photoFilePath: String? = "" // This is returning null!
private var navigationController: NavController? = null
private lateinit var etCreateBookTitle: EditText
private lateinit var etCreateBookAuthor: EditText
private lateinit var etCreateBookPages: EditText
private lateinit var spinCreateBookGenre: Spinner
private lateinit var etCreateBookPublisher: EditText
private lateinit var etCreateBookYearPublished: EditText
private lateinit var etCreateBookISBN: EditText
private lateinit var etCreateBookStarRating: EditText
private lateinit var ibCreateBookImage: ImageButton
private lateinit var btnCancelCreateBook: Button
private lateinit var btnSaveCreateBook: Button
private lateinit var genres: Array<out String>
private lateinit var spinnerText: String
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_create_book, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
navigationController = Navigation.findNavController(view)
initialiseUIElements(view)
setUpButtonClickListeners()
setUpGenreSpinner()
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == MainActivity.REQUEST_CAMERA_USAGE && resultCode == Activity.RESULT_OK) {
val photoUri: Uri = Uri.parse(photoFilePath)
Picasso.with(requireContext())
.load(photoUri)
.memoryPolicy(MemoryPolicy.NO_CACHE)
.networkPolicy(NetworkPolicy.NO_CACHE)
.error(R.drawable.ic_custom_bookshelf)
.fit()
.centerInside()
.noFade()
.into(ibCreateBookImage)
}
}
private fun initialiseUIElements(view: View) {
etCreateBookTitle = view.findViewById(R.id.etCreateBookTitle)
etCreateBookAuthor = view.findViewById(R.id.etCreateBookAuthor)
etCreateBookPages = view.findViewById(R.id.etCreateBookPages)
spinCreateBookGenre = view.findViewById(R.id.spinCreateBookGenre)
etCreateBookPublisher = view.findViewById(R.id.etCreateBookPublisher)
etCreateBookYearPublished = view.findViewById(R.id.etCreateBookYearPublished)
etCreateBookISBN = view.findViewById(R.id.etCreateBookISBN)
etCreateBookStarRating = view.findViewById(R.id.etCreateBookStarRating)
ibCreateBookImage = view.findViewById(R.id.ibCreateBookImage)
btnCancelCreateBook = view.findViewById(R.id.btnCancelCreateBook)
btnSaveCreateBook = view.findViewById(R.id.btnSaveCreateBook)
}
private fun setUpButtonClickListeners() {
ibCreateBookImage.setOnClickListener(this)
btnCancelCreateBook.setOnClickListener(this)
btnSaveCreateBook.setOnClickListener(this)
}
private fun setUpGenreSpinner() {
genres = resources.getStringArray(R.array.book_genres)
val spinnerAdapter: ArrayAdapter<CharSequence> = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_item, genres)
spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
spinCreateBookGenre.adapter = spinnerAdapter
spinCreateBookGenre.onItemSelectedListener = this
}
private fun addBook(view: View) {
if (checkEmpty(etCreateBookTitle) || checkEmpty(etCreateBookAuthor) ||
(checkEmpty(etCreateBookPages) || !isNumeric(etCreateBookPages.text.toString().trim())) ||
spinnerText.isEmpty() || checkEmpty(etCreateBookPublisher) ||
(checkEmpty(etCreateBookYearPublished) || !isNumeric(etCreateBookYearPublished.text.toString().trim())) ||
checkEmpty(etCreateBookISBN) ||
(checkEmpty(etCreateBookStarRating) || !isNumeric(etCreateBookStarRating.text.toString().trim()))) {
Toast.makeText(requireContext(), "Fields cannot be blank", Toast.LENGTH_SHORT).show()
}
else {
val bookTitle: String = etCreateBookTitle.text.toString().trim()
val bookAuthor: String = etCreateBookAuthor.text.toString().trim()
val bookPages: Int = etCreateBookPages.text.toString().trim().toInt()
val bookGenre: String = spinnerText
val bookPublisher: String = etCreateBookPublisher.text.toString().trim()
val bookYearPublished: Int = etCreateBookYearPublished.text.toString().trim().toInt()
val ISBN: String = etCreateBookISBN.text.toString().trim()
val bookStarRating: Float = etCreateBookStarRating.text.toString().trim().toFloat()
val bookImage: String? = if (photoFilePath != "")
photoFilePath
else
null
val dbHandler: DBHandler = DBHandler(requireContext())
val status = dbHandler.addBook(BookModelClass(null, bookTitle, bookAuthor, bookPages,
bookGenre, bookPublisher, bookYearPublished, ISBN, bookStarRating, 0, bookImage, MainActivity.userID!!))
if (status > -1) {
Toast.makeText(requireContext(), "Successfully added book to list", Toast.LENGTH_SHORT).show()
etCreateBookTitle.text.clear()
etCreateBookAuthor.text.clear()
etCreateBookPages.text.clear()
etCreateBookPublisher.text.clear()
etCreateBookYearPublished.text.clear()
etCreateBookISBN.text.clear()
etCreateBookStarRating.text.clear()
}
}
}
private fun checkEmpty(editText: EditText): Boolean {
if (editText.text.toString().trim() == "") {
return true
}
return false
}
override fun onClick(p0: View?) {
when (p0) {
ibCreateBookImage -> {
if (ContextCompat.checkSelfPermission(requireContext(), android.Manifest.permission.CAMERA)
== PackageManager.PERMISSION_GRANTED)
startCamera()
else {
ActivityCompat.requestPermissions(requireActivity(), arrayOf(android.Manifest.permission.CAMERA),
MainActivity.REQUEST_CAMERA_PERMISSIONS_CODE)
}
}
btnCancelCreateBook -> {
navigationController!!.navigate(R.id.action_createBookFragment_to_bookListFragment)
Toast.makeText(requireContext(), "Changes discarded", Toast.LENGTH_SHORT).show()
}
btnSaveCreateBook -> {
addBook(p0)
navigationController!!.navigate(R.id.action_createBookFragment_to_bookListFragment)
}
}
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == MainActivity.REQUEST_CAMERA_USAGE) {
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)
startCamera()
else {
Toast.makeText(requireContext(), "Oops! Camera permission denied", Toast.LENGTH_SHORT).show()
return
}
}
}
private fun startCamera() {
val cameraIntent: Intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
var photoFile: File? = null
try {
photoFile = createPictureFile()
} catch (exception: IOException) {
Toast.makeText(requireContext(), "Error: Cannot save photo", Toast.LENGTH_SHORT).show()
return
}
if (photoFile != null) {
val photoUri = FileProvider.getUriForFile(requireContext(), requireActivity().packageName + ".fileprovider", photoFile)
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri)
startActivityForResult(cameraIntent, MainActivity.REQUEST_CAMERA_USAGE)
}
}
private fun createPictureFile(): File {
val timeStamp: String = SimpleDateFormat("ddMMyyyy_HHmmss", Locale.UK).format(Date().time)
val photoFileName: String = "IMG_" + timeStamp + "_"
val storageDirectory: File = requireContext().getExternalFilesDir(Environment.DIRECTORY_PICTURES)!!
return File.createTempFile(photoFileName, ".jpg", storageDirectory).apply {
photoFilePath = absolutePath
}
}
private fun isNumeric(string: String): Boolean {
return string.all { char -> char.isDigit() }
}
override fun onItemSelected(p0: AdapterView<*>?, p1: View?, p2: Int, p3: Long) {
spinnerText = genres[p2].toString()
}
override fun onNothingSelected(p0: AdapterView<*>?) {
spinnerText = ""
}
}
The Issue
In reality, when trying to save the picture to the device, Android Studio registers the picture/path as "null", and I used to get a NullPointerException when trying to load the pictures on the RecyclerView before I started using Picasso, even when I can see the picture was indeed saved to local storage on the emulator (API 30) and on a physical device (API 24) with the path set to: "/storage/emulated/0/Android/data/<my_package_authority>/files/Pictures/IMG_01062022_164449_8511882897552656984.jpg" for the emulator and a similar path for the physical device (file_paths.xml included below). I got this path by using an application called DBBrowser for Sqlite, which I used to confirm that my database is indeed getting the path.
Picasso is only displaying the error image that I have set for the thumbnail, despite trying so many different sources such as the official Android docs and some other forums, videos and other StackOverflow questions/answers of a similar topic. When the user tries to add a picture to their book when creating it at first, it doesn't even actually show the picture after they've taken a camera picture. What appears to happen is that the file is never "officially" created, but the file does exist at the specified location on device memory. I am currently using the deprecated startActivityForResult() function for testing purposes and trying to set things in onActivityResult() inside the Fragment, but it's not working. I am using the deprecated function because the newer functions that replace it aren't helping either, so it was kind of a last-resort thing. An answer on StackOverflow suggested that the startActivityForResult() function is actually sending the data to the MainActivity instead of localising that data in the Fragment, which has pretty much caused the biggest headaches. It's been days, if not an entire week with this issue, send help...
I do not need any help with trying to display images or even trying to get the image path from my database, I only need help figuring out how to stop the file path from returning null so that Picasso can display the image preview when the user first adds the image on CreateBookFragment. If the file path can stop returning null, I can get this entire functionality going. I debated putting my database here with the two model classes, but it's like 1 000 lines of code and StackOverflow doesn't allow more than 40 000 characters.
A Few Sources (definitely not all of them)
https://developer.android.com/training/camera/photobasics
onActivityResult is not being called in Fragment
One of the MANY Youtube videos I've watched: https://www.google.com/search?q=how+to+save+an+image+from+camera+onto+device+android+studio&rlz=1C1CHBF_enZA979ZA979&oq=how+to+save+an+image+from+camera+onto+device+android+studio&aqs=chrome..69i57j0i22i30l2j0i390.10856j0j7&sourceid=chrome&ie=UTF-8#kpvalbx=_fW2YYqCeCJq6gAbewp2gCA22
Edit:
As a quick and dirty solution, I ended up saving the captured images as blobs in my SQLite database and converting them to bitmaps when it came time to displaying them on my ImageViews. I am still looking for a more efficient way to do this, as storing images as blobs in SQLite database isn't best practice.

Kotlin "D/skia: --- Failed to create image decoder with message 'unimplemented'" Error preventing functionality of button at login/registration screen

Hello I am currently facing an issue with my Kotlin code in Android SDK. For the purposes of a small personal project I am trying to get a simple change password functionality working with a nodeJS file and mongoDB. However I've run into the issue while writting up some code to this end. It seems that my change_password function doesn't want to launch the sequence to input the new password due to the following error "D/skia: --- Failed to create image decoder with message 'unimplemented'" which is only visible in the debug mode. I am not even certain where to start debugging this issue, so I'm hoping someone here might be able to help. Bellow I have provided my MainActivity file where the change_password function is present. Additionally I have provided the xml layout files involved in these operations.
MainActivity File
import android.Manifest
import android.app.Activity
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothDevice
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.widget.AdapterView
import android.widget.ArrayAdapter
import android.widget.Button
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import com.afollestad.materialdialogs.MaterialDialog
import com.example.accentus_login.R.id.*
import com.example.accentus_login.Retrofit.INodeJS
import com.example.accentus_login.Retrofit.RetrofitClient
import com.github.javiersantos.materialstyleddialogs.MaterialStyledDialog
import com.rengwuxian.materialedittext.MaterialEditText
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.schedulers.Schedulers
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.home_page.*
import org.jetbrains.anko.toast
class MainActivity : AppCompatActivity() {
lateinit var myAPI: INodeJS
var compositeDisposable = CompositeDisposable()
var m_bluetoothAdapter: BluetoothAdapter? = null
lateinit var m_pairedDevices: Set<BluetoothDevice>
val REQUEST_ENABLE_BLUETOOTH=1
internal lateinit var change_pass_confirm_button: Button
companion object{
val EXTRA_ADDRESS: String = "Device_address"
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//Init API
val retrofit = RetrofitClient.instance
myAPI = retrofit.create(INodeJS::class.java)
//m_bluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
//if (m_bluetoothAdapter==null){
// toast("this device doesn't support bluetooth")
// return
//}
//if(!m_bluetoothAdapter!!.isEnabled) {
// val enableBluetoothIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
// if (ActivityCompat.checkSelfPermission(
// this,
// Manifest.permission.BLUETOOTH_CONNECT
// ) != PackageManager.PERMISSION_GRANTED
// ) {
// ActivityCompat.requestPermissions(
// this#MainActivity,
// arrayOf(Manifest.permission.BLUETOOTH, Manifest.permission.BLUETOOTH_ADMIN),REQUEST_ENABLE_BLUETOOTH)
// }
// startActivityForResult(enableBluetoothIntent, REQUEST_ENABLE_BLUETOOTH)
//}
//select_device_refresh.setOnClickListener{ pairedDeviceList() }
//change_pass_confirm_button = findViewById(R.id.change_pass_confirm_button);
login_button.setOnClickListener{
login(edt_email.text.toString(),edt_password.text.toString())
}
register_button.setOnClickListener{
register(edt_email.text.toString(),edt_password.text.toString())
}
change_pass_button.setOnClickListener{
change_password(edt_email.text.toString())
}
}
private fun login(email: String, password: String) {
compositeDisposable.add(myAPI.loginUser(email, password)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe{ message ->
if (message.contains("encrypted_password"))
Toast.makeText(this#MainActivity,"Login Successful",Toast.LENGTH_SHORT).show()
else
Toast.makeText(this#MainActivity,message,Toast.LENGTH_SHORT).show()
setContentView(R.layout.home_page);
})
}
private fun change_password(email: String) {
val change_pass_view = LayoutInflater.from(this#MainActivity)
.inflate(R.layout.change_pass, null)
MaterialStyledDialog.Builder(this#MainActivity)
.setTitle("Change Password")
.setDescription("Enter New Password")
.setCustomView(change_pass_view)
.setNegativeText("Cancel")
.onNegative { materialDialog: MaterialDialog -> materialDialog.dismiss() }
.setPositiveText("Confirm")
.onPositive { materialDialog: MaterialDialog ->
val password = change_pass_view.findViewById(R.id.new_pass) as MaterialEditText
//val con_password = change_pass_view.findViewById(R.id.con_new_pass) as MaterialEditText
if (password != password)
Toast.makeText(this#MainActivity, "Password Doesn't Match", Toast.LENGTH_SHORT)
.show()
else
compositeDisposable.add(myAPI.ChangePass(email, password)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe { message ->
Toast.makeText(this#MainActivity, message, Toast.LENGTH_SHORT).show()
})
}
}
private fun register(email: String, password: String) {
val enter_name_view = LayoutInflater.from(this#MainActivity)
.inflate(R.layout.enter_name_layout,null)
MaterialStyledDialog.Builder(this#MainActivity)
.setTitle("Register")
.setDescription("Last Step: Enter your Name")
.setCustomView(enter_name_view)
.setIcon(R.drawable.ic_user)
.setNegativeText("Cancel")
.onNegative{ materialDialog: MaterialDialog-> materialDialog.dismiss() }
.setPositiveText("Register")
.onPositive { materialDialog: MaterialDialog ->
val edt_name = enter_name_view.findViewById<View>(edt_name) as MaterialEditText
compositeDisposable.add(myAPI.registerUser(email,edt_name.text.toString(), password)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe{ message ->
Toast.makeText(this#MainActivity,message,Toast.LENGTH_SHORT).show()
})
}.show()
}
private fun pairedDeviceList(){
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.BLUETOOTH_CONNECT
) != PackageManager.PERMISSION_GRANTED
) {
ActivityCompat.requestPermissions(
this#MainActivity,
arrayOf(Manifest.permission.BLUETOOTH, Manifest.permission.BLUETOOTH_ADMIN),REQUEST_ENABLE_BLUETOOTH)
}
m_pairedDevices = m_bluetoothAdapter!!.bondedDevices
val list : ArrayList<BluetoothDevice> = ArrayList()
if(m_pairedDevices.isNotEmpty()) {
for(device : BluetoothDevice in m_pairedDevices) {
list.add(device)
Log.i("device", ""+device) // device logged as string
}
} else {
toast("no paired bluetooth devices found")
}
val adapter = ArrayAdapter(this,android.R.layout.simple_list_item_1,list)
select_device_list.adapter=adapter
select_device_list.onItemClickListener= AdapterView.OnItemClickListener{ _, _, position, _ ->
val device: BluetoothDevice= list[position]
val address: String = device.address
val intent = Intent(this, ControlActivity::class.java)
intent.putExtra(EXTRA_ADDRESS,address)
startActivity(intent)
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode==REQUEST_ENABLE_BLUETOOTH){
if(resultCode== Activity.RESULT_OK) {
if (m_bluetoothAdapter!!.isEnabled) {
toast("Bluetooth has been enabled")
} else {
toast("Bluetooth has been disabled")
}
} else if (resultCode == Activity.RESULT_CANCELED)
toast("Bluetooth enabling has been canceled")
}
}
override fun onStop() {
compositeDisposable.clear()
super.onStop()
}
override fun onDestroy() {
compositeDisposable.clear()
super.onDestroy()
}
XML Login Page
<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"
android:background="#drawable/gradient_bg"
tools:context=".MainActivity">
<LinearLayout
android:layout_margin="16dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" >
<TextView
android:text="#string/accentus"
android:textSize="30sp"
android:textColor="#android:color/white"
android:layout_gravity="center_horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<com.rengwuxian.materialedittext.MaterialEditText
android:id="#+id/edt_email"
android:hint="#string/email"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textEmailAddress"
app:met_iconLeft="#drawable/ic_user"
app:met_baseColor="#android:color/white"
app:met_textColorHint="#android:color/white"
app:met_primaryColor="#android:color/white"
app:met_iconPadding="0dp"/>
<com.rengwuxian.materialedittext.MaterialEditText
android:id="#+id/edt_password"
android:hint="#string/password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPassword"
app:met_iconLeft="#drawable/ic_lock"
app:met_baseColor="#android:color/white"
app:met_textColorHint="#android:color/white"
app:met_primaryColor="#android:color/white"
app:met_iconPadding="0dp"/>
<LinearLayout
android:orientation="horizontal"
android:weightSum="2"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.button.MaterialButton
android:id="#+id/register_button"
android:text="#string/register_account"
android:layout_marginEnd="8dp"
android:textSize="11sp"
style="#style/Widget.MaterialComponents.Button"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content">
</com.google.android.material.button.MaterialButton>
<com.google.android.material.button.MaterialButton
android:id="#+id/login_button"
android:text="#string/login"
android:layout_marginStart="8dp"
android:textSize="11sp"
style="#style/Widget.MaterialComponents.Button.UnelevatedButton"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content">
</com.google.android.material.button.MaterialButton>
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:weightSum="2"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.button.MaterialButton
android:id="#+id/change_pass_button"
android:text="#string/forgot_password"
android:layout_marginStart="125dp"
android:textSize="11sp"
style="#style/Widget.MaterialComponents.Button.UnelevatedButton"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content">
</com.google.android.material.button.MaterialButton>
</LinearLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
XML Change Password Page
<?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"
android:background="#drawable/gradient_bg"
tools:context=".MainActivity">
<LinearLayout
android:layout_margin="16dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" >
<TextView
android:text="#string/change_password"
android:textSize="30sp"
android:textColor="#android:color/white"
android:layout_gravity="center_horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<com.rengwuxian.materialedittext.MaterialEditText
android:id="#+id/login_email"
android:hint="#string/email"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textEmailAddress"
app:met_baseColor="#android:color/white"
app:met_textColorHint="#android:color/white"
app:met_primaryColor="#android:color/white"
app:met_iconPadding="0dp"/>
<com.rengwuxian.materialedittext.MaterialEditText
android:id="#+id/new_pass"
android:hint="#string/new_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPassword"
app:met_baseColor="#android:color/white"
app:met_textColorHint="#android:color/white"
app:met_primaryColor="#android:color/white"
app:met_iconPadding="0dp"/>
<com.rengwuxian.materialedittext.MaterialEditText
android:id="#+id/con_new_pass"
android:hint="#string/confirm_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPassword"
app:met_iconLeft="#drawable/ic_lock"
app:met_baseColor="#android:color/white"
app:met_textColorHint="#android:color/white"
app:met_primaryColor="#android:color/white"
app:met_iconPadding="0dp"/>
<LinearLayout
android:orientation="horizontal"
android:weightSum="2"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</LinearLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Please let me know if you think there is any other information necessary to understand why this is going on.

No adapter attached; skipping layout error in logcat windowin android studio

i have been facing this issue from 3-4 days and i still can't resolve this error. i have also gone through this a solution of the same problem
but i didn't understand enough. i got that, that this error occurs when we didn't attach our adapter but i have attached.
below i have attached my fragment file, adapter file and RecyclerView file-
this is a code where i declared my adapter
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.example.chumonsuru.R
import com.example.chumonsuru.model.Resturant
import com.squareup.picasso.Picasso
class DashboardRecyclerAdapter(val context : Context , val resturantInfoList : ArrayList<Resturant>) : RecyclerView.Adapter<DashboardRecyclerAdapter.DashboardViewHolder>(){
class DashboardViewHolder(view:View): RecyclerView.ViewHolder(view){
val txtResturantid : TextView = view.findViewById(R.id.txtResturantid)
val txtResturantName : TextView = view.findViewById(R.id.txtResturantName)
val txtPerPrice : TextView = view.findViewById(R.id.txtPerPrice)
val txtResturantRating : TextView = view.findViewById(R.id.txtResturantRating)
val imgResturantImage : ImageView = view.findViewById(R.id.imgResturantImage)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DashboardViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.recycler_dashboard_row_one , parent , false)
return DashboardViewHolder(view)
}
override fun getItemCount(): Int {
return resturantInfoList.count()
}
override fun onBindViewHolder(holder: DashboardViewHolder, position: Int) {
val resturant = resturantInfoList[position]
holder.txtResturantid.text = resturant.id
holder.txtResturantName.text = resturant.name
holder.txtPerPrice.text = resturant.cost_for_one
holder.txtResturantRating.text = resturant.rating
Picasso.get().load(resturant.image_url).into(holder.imgResturantImage)
}
}
and here is my dashboard fragment file-
import android.content.Context
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.android.volley.Request
import com.android.volley.Response
import com.android.volley.toolbox.JsonObjectRequest
import com.android.volley.toolbox.Volley
import com.example.chumonsuru.R
import com.example.chumonsuru.adapter.DashboardRecyclerAdapter
import com.example.chumonsuru.model.Resturant
import kotlin.collections.HashMap
class DashFrag : Fragment() {
lateinit var recyclerView: RecyclerView
lateinit var linearLayoutManager: LinearLayoutManager
lateinit var recyclerAdapter: DashboardRecyclerAdapter
val resturantInfoList = arrayListOf<Resturant>()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
val view = inflater.inflate(R.layout.dash_frag, container, false)
linearLayoutManager = LinearLayoutManager(activity)
recyclerView = view.findViewById(R.id.recyclerView)
val queue = Volley.newRequestQueue(activity as Context)
val url = "http://13.235.250.119/v1/book/fetch_books/"
val jsonObjectRequest = object : JsonObjectRequest(Request.Method.GET, url, null, Response.Listener {
val success = it.getBoolean("success")
if (success != null) {
val data = it.getJSONArray("data")
for (i in 0 until data.length()) {
val resturantJsonObject = data.getJSONObject(i)
val resturantObject = Resturant(
resturantJsonObject.getString("id"),
resturantJsonObject.getString("name"),
resturantJsonObject.getString("rating"),
resturantJsonObject.getString("cost_for_one"),
resturantJsonObject.getString("image_url")
)
resturantInfoList.add(resturantObject)
recyclerAdapter = DashboardRecyclerAdapter(activity as Context, resturantInfoList)
recyclerView.adapter = recyclerAdapter
recyclerView.layoutManager = linearLayoutManager
recyclerView.addItemDecoration(DividerItemDecoration(recyclerView.context,
(linearLayoutManager)
.orientation))
}
}
},
Response.ErrorListener {
/////ERROR/////
}) {
override fun getHeaders(): MutableMap<String, String> {
val headers = HashMap<String, String>()
headers["Content-type"] = "application/json"
headers["token"] = "xyz"
return headers
}
}
queue.add(jsonObjectRequest)
return view
}
}
and
my restaurant class-
data class Resturant(
val id: String,
val name: String,
val rating: String,
val cost_for_one : String,
val image_url: String
)
my dashboard fragment xml file-
<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"
tools:context=".fragments.DashFrag">
<!-- TODO: Update blank fragment layout -->
<TextView
android:id="#+id/txtHelloFrag"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/hello_blank_fragment"
android:textSize="50sp"
android:textColor="#color/colorAccent"
android:padding="20dp"
android:background="#drawable/gradient"/>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/txtHelloFrag"
android:layout_margin="10dp"
android:padding="5dp"
/>
</RelativeLayout>
and the layout of the row of the recycler view
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="140dp"
android:orientation="horizontal"
android:background="#ffffff"
android:weightSum="6">
<ImageView
android:layout_weight="1.5"
android:id="#+id/imgResturantImage"
android:layout_width="0dp"
android:layout_height="110dp"
android:src="#mipmap/ic_launcher1"
android:padding="5dp"/>
<RelativeLayout
android:layout_weight="3.3"
android:layout_width="0dp"
android:layout_height="match_parent">
<TextView
android:padding="8dp"
android:id="#+id/txtResturantid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="id"
android:layout_toLeftOf="#id/txtResturantName"
android:textSize = "18sp"
/>
<TextView
android:id="#+id/txtResturantName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Name of the Resturant"
android:paddingTop="8dp"
android:textSize="18sp"
android:textColor="#000000"/>
<TextView
android:id="#+id/txtBookAuthor"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/txtResturantName"
android:text="Name of the Author"
android:padding="8dp"
android:textSize="15sp"/>
<TextView
android:id="#+id/txtPerPrice"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:text="Rs. 299"
android:paddingTop="8dp"
android:paddingLeft="8dp"
android:layout_below="#id/txtBookAuthor"
android:textSize="15sp"
android:textStyle="bold"
android:textColor="#357a38"/>
<TextView
android:id="#+id/txtPerPerson"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="/person"
android:layout_toRightOf="#id/txtPerPrice"
android:textSize="15sp"
android:layout_below="#id/txtBookAuthor"
android:textColor="#357a38"
android:paddingTop="8dp"
android:textStyle="bold"/>
</RelativeLayout>
<TextView
android:id="#+id/txtResturantRating"
android:layout_weight="1.2"
android:layout_width="0dp"
android:padding="6dp"
android:layout_height="wrap_content"
android:drawableLeft="#drawable/star_foreground"
android:textColor="#ffca28"
android:text="4.5"
android:textSize="15sp"
android:textStyle="bold">
</TextView>
</LinearLayout>
i think i have already attached the adapter to my recycler view. if i didn't please help me to do this.
Please help me to get rid of this problem
I think something that you need to check.
return view
Instead of this, you have to use
return view;
second,
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/txtHelloFrag"
android:layout_margin="10dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
android:padding="5dp"
/>
You try to put app:layoutManager into that.
or
val layoutManager = LinearLayoutManager(this)
recyclerView_main.setLayoutManager(layoutManager)
As above, LayoutManager is set in the setLayoutManager and it processes as code.
LinearLayoutManager manager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(manager);
this is related above, you have set the layout manager for RecyclerView
I hope that It will be work.

Resources