getData() is not working since migration to kotlin - android

I am new to kotlin. I wrote this code that will get image from image picker.
But I am getting error on line:val filePath: Uri = attr.data.getData()
error: Unresolved reference. Is there any change in kotlin because this code was working properly in java (Means I migrated to kotlin)
And another error on imageStore(bitmap) error: smart cast to bitmap is impossible.
I've searched for documentation but couldn't solve this 2 problems .
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK && requestCode == 1) {
val filePath: Uri = attr.data.getData()
try {
val inputStream: InputStream? = contentResolver.openInputStream(filePath)
bitmap = BitmapFactory.decodeStream(inputStream)
imageStore(bitmap)
} catch (e: FileNotFoundException) {
e.printStackTrace()
}
}
}

But I am getting error on line:val filePath: Uri = attr.data.getData() error: Unresolved reference
Well, this means the compiler can't understand what you're referring to. Is it correct to say this ?
Well, considering you don't have any object named attr it would seem that the compiler is correct.
this means you should remove the attr part, something like:
val filePath: Uri = data?.getData() ?: return
The return here will stop executing the rest of the method if the data from the intent is null
To resolve your second problem, you'll need something like this :
bitmap?.let { bitmapInstance ->
imageStore(bitmapInstance)
}
What does this do ?
Well, it gives you thread safe access to your bitmap object and also ensures that the instance isn't null.

As #a_local_nobody said "the migration tool isn't perfect", I learned the basics of kotlin and found that the following code works fine for me.
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == 1 && resultCode == Activity.RESULT_OK && data != null) {
val filePath = data.data
try {
val inputStream = contentResolver.openInputStream(filePath!!)
bitmap = BitmapFactory.decodeStream(inputStream)
imageView!!.setImageBitmap(bitmap)
imageStore(bitmap)
} catch (e: FileNotFoundException) {
e.printStackTrace()
}
}
super.onActivityResult(requestCode, resultCode, data)
}

Replace this line val filePath: Uri = attr.data.getData() with
val filePath: Uri = data!!.getData()!!
Updated code
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK && requestCode == 1) {
val filePath: Uri = data!!.getData()!!
try {
val inputStream: InputStream? = contentResolver.openInputStream(filePath)
var bitmap = BitmapFactory.decodeStream(inputStream)
imageStore(bitmap)
} catch (e: FileNotFoundException) {
e.printStackTrace()
}
}
}

Related

how to preview video and upload that video file to firebase in android kotlin

I am trying to upload a video file to firebase.:-
this is the code:-
lateinit var file: Any
private fun selectingVideo() {
val videoPickIntent = Intent(Intent.ACTION_PICK)
videoPickIntent.type = "video/*"
startActivityForResult(Intent.createChooser(videoPickIntent, "Please pick a video"), videoRequest )
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == videoRequest && resultCode == Activity.RESULT_OK && null != data) {
feedImageSelect.visibility = View.GONE
feedVideoSelect.visibility = View.VISIBLE
val pickedVideoUrl = getRealPathFromUri(applicationContext, data.data!!)
file = pickedVideoUrl
feedVideoSelect.setVideoPath(pickedVideoUrl)
// Default Media-Controller
feedVideoSelect.setMediaController(MediaController(this))
// start playing
feedVideoSelect.start()
}
}
// Retrieve Video Path from URI.
private fun getRealPathFromUri(context: Context, contentUri: Uri): String {
var cursor: Cursor? = null
try {
val proj = arrayOf(MediaStore.Images.Media.DATA)
cursor = context.contentResolver.query(contentUri, proj, null, null, null)
val columnIndex = cursor!!.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)
cursor.moveToFirst()
return cursor.getString(columnIndex)
} finally {
cursor?.close()
}
}
I am getting this as the error.:-
java.lang.ClassCastException: java.lang.String cannot be cast to android.net.Uri
I have tried all the possible ways to solve it. But Still I am getting this error. I tried other methods as well still they are not working for my requirements.
Make these changes to the code:-
val pickedVideoUrl = data.data
feedVideoSelect.setVideoPath(pickedVideoUrl.toString())

How can I pass a variable control name to findViewById in Kotlin?

I am trying to learn Kotlin and I'm building a simple example as I go. I have 3 image buttons that open the camera and take a photo. The thumbnail is then set into an ImageView. I've used the examples from https://developer.android.com/training/camera/photobasics?hl=en to get the basics working (figuring if I can make it work for one, it'll work for all. It does indeed work for one, but I can't figure out how to make it one function that drops the thumbnail into the correct ImageView.
Inside my onCreate I have the listener for each of the buttons that will invoke the camera:
camRead1.setOnClickListener {dispatchTakePictureIntent() }
camRead2.setOnClickListener {dispatchTakePictureIntent() }
camRead3.setOnClickListener {dispatchTakePictureIntent() }
And I took the sample from the url above:
val REQUEST_IMAGE_CAPTURE = 1
private fun dispatchTakePictureIntent() {
val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
try {
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE)
} catch (e: ActivityNotFoundException) {
// display error state to the user
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
val thumb: ImageView = findViewById(R.id.thumbRead1)
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
val imageBitmap = data.extras.get("data") as Bitmap
thumb.setImageBitmap(imageBitmap)
}
}
and pasted it into my class MainActivity, and after I replaced imageView in the override function with a variable (thumb) and added the super, it worked perfectly for the first one.
However, I am trying to get 3 photos, read1, read2, and read3 which each need to display the thumb in thumbRead1, thumbRead2 and thumbRead3. I can't figure out how the onActivityResult is executed since the call inside dispatchTakePictureIntent is calling startActivityForResult (especially as Android Studio says that startActivityForResult is deprecated).
Obviously, once onActivityResult executes, I can see that thumb defines R.id.thumbRead1 and receives imageBitmap but I don't understand how I can make it aware of the button that was clicked.
Without understanding how onActivityResult is called, I'm thinking that if I can do something like:
findViewById(R.id("thumbRead" + imgID))
to define the specific ImageView that I want the photo pasted into. Am I on the right track here? If not, what is the recommended way of doing this?
Note they've recently added what's supposed to be a cleaner way of starting other activities for results and getting the results, explained here. But since you're already doing it the traditional way, I'll explain how to get that working.
I think the easiest thing to do in this situation is just make more request codes, so you can check which request it was.
val REQUEST_IMAGE_CAPTURE_SOURCE_1 = 1
val REQUEST_IMAGE_CAPTURE_SOURCE_2 = 2
val REQUEST_IMAGE_CAPTURE_SOURCE_3 = 3
//...
camRead1.setOnClickListener { dispatchTakePictureIntent(REQUEST_IMAGE_CAPTURE_SOURCE_1) }
camRead2.setOnClickListener { dispatchTakePictureIntent(REQUEST_IMAGE_CAPTURE_SOURCE_2) }
camRead3.setOnClickListener { dispatchTakePictureIntent(REQUEST_IMAGE_CAPTURE_SOURCE_3) }
//...
private fun dispatchTakePictureIntent(requestCode: Int) {
val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
try {
startActivityForResult(takePictureIntent, requestCode)
} catch (e: ActivityNotFoundException) {
// display error state to the user
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode != RESULT_OK) {
// possibly show message to user
return
}
val imageViewId = when (requestCode) {
REQUEST_IMAGE_CAPTURE_SOURCE_1 -> R.id.thumbRead1
REQUEST_IMAGE_CAPTURE_SOURCE_2 -> R.id.thumbRead2
REQUEST_IMAGE_CAPTURE_SOURCE_3 -> R.id.thumbRead3
}
val imageView = findViewById<ImageView>(imageViewId)
imageView.imageBitmap = data.extras.get("data") as Bitmap
}
By the way, if you want to get an ID for a view using the String like you were showing you were trying, you would do it like this:
val viewId = resources.getIdentifier("thumbRead$imgId", "id", packageName)
val imageView = findViewById<ImageView>(viewId)
You need to pass different request code for each call and pass it to the dispatchTakePictureIntent function. You do not need to get id by findviewbyid. You simply can add the image on the basis of the request code.
val REQUEST_IMAGE_CAPTURE_ONE = 1
val REQUEST_IMAGE_CAPTURE_TWO = 2
val REQUEST_IMAGE_CAPTURE_THREE = 3
private fun dispatchTakePictureIntent(requestCode: Int) {
val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
try {
startActivityForResult(takePictureIntent, requestCode)
} catch (e: ActivityNotFoundException) {
// display error state to the user
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == RESULT_OK) {
val imageBitmap = data.extras.get("data") as Bitmap
if (requestCode == REQUEST_IMAGE_CAPTURE_ONE ) {
thumbRead1.setImageBitmap(imageBitmap)
}else if (requestCode == REQUEST_IMAGE_CAPTURE_TWO ) {
thumbRead2.setImageBitmap(imageBitmap)
}else if (requestCode == REQUEST_IMAGE_CAPTURE_THREE ) {
thumbRead3.setImageBitmap(imageBitmap)
}
}
}

I can't delete the folder's content from path

I'm currently getting this path from my FileExplorer
val path = "content://com.android.externalstorage.documents/tree/primary:Download"
And I'm trying to delete the content of this location:
val fileFolder = File(path)
deleteFolderContent(fileFolder)
private fun deleteFolderContent(fileFolder: File) {
val files = fileFolder.listFiles()
if (files.isNullOrEmpty()) {
return
} else {
for (file in files) {
file.delete()
}
}
}
But files is always null and I can't delete the content. What am I doing wrong? Can anyone help me? Thanks.
Update:
For obtain this "path" I did this:
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
startActivityForResult(intent, SELECT_FOLDER_REQUEST_CODE)
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == SELECT_FOLDER_REQUEST_CODE && resultCode == RESULT_OK) {
val uriTree = data?.data
}
}
you can't access content directory as a File (even when URI points on local storage). check out Providers and ContentResolver, HERE you have some basics, for files there is special one: FileProvider. but for your case ContentResolver may fit for your needs best, with method:
context.contentResolver.delete(uriToDelete, null, null)

OnActivityResult Kotlin

I am currently using firebase storage to allow users to upload images.
I copied my old working java code and is trying to convert it to Kotlin but I have a mismatch issue. The error message is:
Type mismatch
Required: Uri
Found: Uri?
Here is my code.
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK && requestCode == 1046) {
try {
val imageUri : Uri? = data?.data
val imageStream: InputStream? = this.contentResolver.openInputStream(imageUri) //this is the line that errors imageUri has a mismatch error
val selectedImage = BitmapFactory.decodeStream(imageStream)
CloudStorage().upload(imageUri,
{ s ->
uploadedImageURL = s
}) { e ->
Toast.makeText(this#CreatePostActivity, e.message, Toast.LENGTH_SHORT).show()
e.printStackTrace()
}
} catch (e: FileNotFoundException) {
e.printStackTrace()
Toast.makeText(this, "file not found", Toast.LENGTH_SHORT).show()
}
}
}
Thanks!
imageUri cannot be null since openInputStream does not accept nullable values. You can fix it by only executing the code if the value is not nullable, for example:
data?.data?.let { imageUri ->
try {
val imageStream: InputStream? = this.contentResolver.openInputStream(imageUri)
val selectedImage = BitmapFactory.decodeStream(imageStream)
CloudStorage().upload(imageUri,
{ s ->
uploadedImageURL = s
}) { e ->
Toast.makeText(this#CreatePostActivity, e.message, Toast.LENGTH_SHORT).show()
e.printStackTrace()
}
} catch (e: FileNotFoundException) {
e.printStackTrace()
Toast.makeText(this, "file not found", Toast.LENGTH_SHORT).show()
}
} ?: notifyUserImageUriIsNull()
Note that you're calling super.onActivityResult() twice.
"Android Studio" shows the answers.

onActivityResult return null data

I've just been coding in kotlin for a while. I've got some problems.
It always return null data in after I click item in second activity.
first activity
btnClick.setOnClickListener { v ->
val intent = Intent(applicationContext, NumberPickerActivity::class.java)
startActivityForResult(intent, 777)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
try {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == 777 && resultCode == Activity.RESULT_OK) {
val result = data?.getStringExtra("picked_product").toString()
Toast.makeText(applicationContext, result, Toast.LENGTH_SHORT).show()
}
} catch (e: Exception) {
Toast.makeText(applicationContext, e.message, Toast.LENGTH_LONG).show()
}
}
second activity
override fun onItemClick(item: Product) {
val intent = Intent()
intent.putExtra("picked_product", item.price)
setResult(Activity.RESULT_OK, intent)
finish()
}
Because you are expecting an Int, do this instead:
val result = data?.getIntExtra("picked_product", 0) //0 will be used in case no value in data and result is now Integer.
The extra you put in your intent is an Integer (item.price). But you are trying to retrive a String data?.getStringExtra("picked_product").
Sinc the intent does not contain a String at the key "picked_product", it returns null.
You should try to get an Int extra :
val result = data?.getIntExtra("picked_product")
Nothing to do with your problem but it's useless to do
data?.getStringExtra("picked_product").toString()
Since it return you a String the use of toString() is useless

Categories

Resources