androidkotlinandroid-imageviewandroid-popupwindowregisterforactivityresult

How to add onClickListener which opens gallery inside popupWindow


so i want to add video, and image selection inside a popupWindow and later add all of this inside recyclerView. But when i try to open my popupWindow app crashes, i checked my logcat and i understand why my app don't work (I think) but i don't know how to solve this inside my code.

here is an preview of what it looks like without any functionality

i wanted to do this with 'startActivityForResult' but this method is depreciated and way more complicated for me

MainActivity.kt

class MainActivity : AppCompatActivity() {

private val home = HomeFragment()
private val player = PlayerFragment()
private val profile = ProfileFragment()
private val settings = SettingsFragment()


override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    val popupButton: FloatingActionButton = findViewById(R.id.fab)
    val bottomNav: BottomNavigationView = findViewById(R.id.bottomNavigationView)

    bottomNav.background = null
    bottomNav.menu.findItem(R.id.placeholder).isEnabled = false
    replaceFragment(home)

    bottomNav.setOnItemSelectedListener {
        when (it.itemId) {
            R.id.home -> replaceFragment(home)
            R.id.player -> replaceFragment(player)
            R.id.profile -> replaceFragment(profile)
            R.id.settings -> replaceFragment(settings)
        }
        true
    }
    popupButton.setOnClickListener {
        showDialog()
    }

}
private fun replaceFragment(fragment: Fragment) {
    val transaction = supportFragmentManager.beginTransaction()
    transaction.replace(R.id.fragment_container, fragment)
    transaction.commit()
}

private fun showDialog() {

    val title = RecyclerAdapter().titles
    val description = RecyclerAdapter().details
    val video = RecyclerAdapter().videos

    val dialog = Dialog(this)
    val dialogView: View = layoutInflater.inflate(R.layout.popup, null)

    val imageView = dialogView.findViewById<ImageView>(R.id.imageChange)
    val videoView = dialogView.findViewById<ImageView>(R.id.VideoSelect)

    val titleEditText = dialogView.findViewById<EditText>(R.id.titleEdit) //popUp edit field title
    val descEditText = dialogView.findViewById<EditText>(R.id.description) //popUp pole edit field description

    val getPreviewImage = registerForActivityResult(ActivityResultContracts.GetContent(), ActivityResultCallback {
        imageView.setImageURI(it)
    })
    val getPreviewVideo = registerForActivityResult(ActivityResultContracts.GetContent(), ActivityResultCallback {
        videoView.setImageURI(it)
    })


    dialogView.addImage?.setOnClickListener {
        getPreviewImage.launch("image/*")
    }

    dialogView.addVideo?.setOnClickListener {
        getPreviewVideo.launch("video/*")
    }

    dialogView.addButton?.setOnClickListener {
        if (titleEditText.text.isEmpty()){
            Toast.makeText(applicationContext, "add required data", Toast.LENGTH_SHORT).show()
        }else{
            Toast.makeText(applicationContext, "Added", Toast.LENGTH_SHORT).show()
        }
    }
    dialog.setContentView(dialogView)
    dialog.show()
 }
}

debug console

E/AndroidRuntime: FATAL EXCEPTION: main
Process: eu.tuto.youtubeproject, PID: 15323
java.lang.IllegalStateException: LifecycleOwner eu.tuto.youtubeproject.MainActivity@4f4d646 is attempting to register while current state is RESUMED. LifecycleOwners must call register before they are STARTED.
    at androidx.activity.result.ActivityResultRegistry.register(ActivityResultRegistry.java:123)
    at androidx.activity.ComponentActivity.registerForActivityResult(ComponentActivity.java:682)
    at androidx.activity.ComponentActivity.registerForActivityResult(ComponentActivity.java:691)
    at eu.tuto.youtubeproject.MainActivity.showDialog(MainActivity.kt:85)
    at eu.tuto.youtubeproject.MainActivity.onCreate$lambda-1(MainActivity.kt:60)
    at eu.tuto.youtubeproject.MainActivity.$r8$lambda$pybEQF7uXWpGKgIZJas8o7AXY1Q(Unknown Source:0)
    at eu.tuto.youtubeproject.MainActivity$$ExternalSyntheticLambda3.onClick(Unknown Source:2)
    at android.view.View.performClick(View.java:7191)
    at android.view.View.performClickInternal(View.java:7164)
    at android.view.View.access$3500(View.java:821)
    at android.view.View$PerformClick.run(View.java:27856)
    at android.os.Handler.handleCallback(Handler.java:914)
    at android.os.Handler.dispatchMessage(Handler.java:100)
    at android.os.Looper.loop(Looper.java:224)
    at android.app.ActivityThread.main(ActivityThread.java:7551)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:995)

Solution

  • Look into docs. You should call for registerForActivityResult before your lifecycle is in START state. It's absolutely legit to call registerForActivityResult initializing member variables.

    private val home = HomeFragment()
    private val player = PlayerFragment()
    private val profile = ProfileFragment()
    private val settings = SettingsFragment()
    val getPreviewImage = registerForActivityResult(ActivityResultContracts.GetContent(), ActivityResultCallback {
            // your logic 
        })
    val getPreviewVideo = registerForActivityResult(ActivityResultContracts.GetContent(), ActivityResultCallback {
           // your logic 
        })
    
    override fun onCreate(savedInstanceState: Bundle?)
    ...