I receive such error at my websocket:
Error: [okio.RealBufferedSource.require(RealBufferedSource.kt:201), okio.RealBufferedSource.readByte(RealBufferedSource.kt:210), okhttp3.internal.ws.WebSocketReader.readHeader(WebSocketReader.kt:119), okhttp3.internal.ws.WebSocketReader.processNextFrame(WebSocketReader.kt:102), okhttp3.internal.ws.RealWebSocket.loopReader(RealWebSocket.kt:293), okhttp3.internal.ws.RealWebSocket$connect$1.onResponse(RealWebSocket.kt:195), okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:504), java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162), java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636), java.lang.Thread.run(Thread.java:764)]
It happens when I try to send chunked string files to server. For example when I send file in string with size 14B everything goes well, but when I send file up to 10kB I receive such error. When I try to send chunked 120kB file I receive such error:
Error: [okio.RealBufferedSource.require(RealBufferedSource.kt:201), okio.RealBufferedSource.readByte(RealBufferedSource.kt:210), okhttp3.internal.ws.WebSocketReader.readHeader(WebSocketReader.kt:119), okhttp3.internal.ws.WebSocketReader.processNextFrame(WebSocketReader.kt:102), okhttp3.internal.ws.RealWebSocket.loopReader(RealWebSocket.kt:293), okhttp3.internal.ws.RealWebSocket$connect$1.onResponse(RealWebSocket.kt:195), okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:504), java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162), java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636), java.lang.Thread.run(Thread.java:764)]
Place where I send file:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when {
requestCode == 1 && resultCode == Activity.RESULT_OK -> {
if (data != null) {
val fileUri = data.data!!
val partSize = 10000
val fileString = readTextFile(fileUri)
var name = ""
var size: Long? = null
fileUri.let { returnUri ->
contentResolver.query(returnUri, null, null, null, null)
}?.use { cursor ->
val nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
val sizeIndex = cursor.getColumnIndex(OpenableColumns.SIZE)
cursor.moveToFirst()
name = cursor.getString(nameIndex)
size = cursor.getLong(sizeIndex)
}
if (size!! <= partSize) {
ws.send(ChatRequestMessages.sendFile(fileString!!,
name,
selectedContactId.toString(),
size!!,
0))
} else {
val partsCount = if (size!!.rem(partSize).toInt() == 0) {
size!!.div(partSize)
} else {
size!!.div(partSize)
}
for (currentPart in 0..size!!.div(partSize)) {
val slicedString = if ((currentPart + 1) * partSize <= size!!.toInt()) {
fileString!!.substring(currentPart.toInt() * partSize..(currentPart + 1).toInt() * partSize)
} else {
fileString!!.substring(currentPart.toInt() * partSize until fileString.length)
}
Timber.i("${fileString.length.toLong()} ${currentPart * partSize} ${slicedString.length} $slicedString $name")
ws.send(ChatRequestMessages.sendFile(slicedString,
name,
selectedContactId.toString(),
fileString.length.toLong(),
(currentPart * partSize).toInt()))
}
}
}
}
}
I don't understand why it doesn't happen with small files and how to solve these errors :(
It looks like an empty response. The javadoc from RealBufferedSource.require says Returns when the buffer contains at least byteCount bytes. Throws an
[java.io.EOFException] if the source is exhausted before the required bytes can be read.
okhttp.internal.ws.WebSocketReader tries to read the first byte from the response, but doesn't get it.
Related
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())
Fatal Exception: android.database.CursorIndexOutOfBoundsException
Index 0 requested, with a size of 0
This is my function that I have in my FileHelper class:
fun downloadFile(url: String, fileName: String, completion: (DataResponse<File>) -> Unit) {
val downloadManager = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
val uri = Uri.parse(url)
val request = DownloadManager.Request(uri).apply {
setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI or DownloadManager.Request.NETWORK_MOBILE)
.setAllowedOverRoaming(false)
.setTitle(fileName)
.setDescription("")
.setDestinationInExternalFilesDir(
context,
Environment.DIRECTORY_DOWNLOADS,
fileName
)
}
val downloadId = downloadManager.enqueue(request)
val query = DownloadManager.Query().setFilterById(downloadId)
Thread {
var downloading = true
var downloadRepeatCount = 0
while (downloading) {
val cursor: Cursor = downloadManager.query(query)
cursor.moveToFirst()
val status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS))
if (status == DownloadManager.STATUS_SUCCESSFUL) {
val file =
File("${context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)}${fileName}")
downloading = false
completion(getSuccessResponseData(file))
} else if (status == DownloadManager.STATUS_FAILED) {
downloading = false
sendFirebaseError("status STATUS_FAILED", url, fileName, uri)
completion(getErrorResponseData())
} else {
if (downloadRepeatCount < 10 && status == DownloadManager.STATUS_PAUSED) {
Thread.sleep(1000)
downloadRepeatCount++
} else if (status == DownloadManager.PAUSED_QUEUED_FOR_WIFI) {
downloading = false
sendFirebaseError("status PAUSED_QUEUED_FOR_WIFI", url, fileName, uri)
completion(getErrorResponseData())
} else if (status == DownloadManager.ERROR_INSUFFICIENT_SPACE && status == DownloadManager.ERROR_DEVICE_NOT_FOUND) {
downloading = false
sendFirebaseError("status ERROR_INSUFFICIENT_SPACE and ERROR_DEVICE_NOT_FOUND", url, fileName, uri)
completion(getErrorResponseData())
} else if (status > 10) {
downloading = false
sendFirebaseError("status > 10", url, fileName, uri)
completion(getErrorResponseData())
} else {
downloading = true
}
}
cursor.close()
}
}.start()
}
When I searched for this crash I have received the information about how to fix this issue. However, I want to make that crash in purpose in order to be sure about the reason of it. In addition I wonder that if possible, cursor did not crash but the non fatal error would cause download manager to go the DownloadManager.STATUS_FAILED condition. I want to discuss about those topics.
Make sure you have a null check and as #laalto said call the function only if it's true.
if( cursor != null && cursor.moveToFirst() ){
status =cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
cursor.close();
}
Your query matched no rows. You need to check the return value of cursor.moveToFirst() and call cursor.getInt() only if it returned true.
You can check cursor's size using this method :
if (cursor != null && cursor.getCount() > 0){
// Do your stuff
}
This question already has answers here:
Android Kotlin: Getting a FileNotFoundException with filename chosen from file picker?
(5 answers)
Create a file from a photo URI on Android
(1 answer)
Closed 2 years ago.
I want to upload a logo picked in gallery to our api via multipart.
I am using multipartFile method from the networking library witch take a File in parameter: uploading a file to server
The File object can take an Uri as constructor.
With the uri received from the gallery return, i can display the image in a ImageView, but the uri or uri.path cause FileNotFoundException when passed in FileConstructor. (internet, read, write permissions are declared in manifest)
there is all code concerning this feature:
//selected image uri
private var imageUri: Uri? = null
set(value) {
field = value
field?.let { //value after picking image is : content://com.android.providers.media.documents/document/image%3A25
uploadImageFile(imageUri= it,
route = "uploadImageRoute/",
onProgression = { progress ->
Log.d("upload", "progress= $progress")
},
onSuccess = {
Log.d("upload", "upload success !")
},
onError = { errorMessage ->
Log.d("upload", "error= $errorMessage")
})
}
}
//select image button clicked, go to image gallery to pick an image
override fun onClick(v: View?) {
val intent = Intent()
intent.type = "image/*"
intent.action = Intent.ACTION_GET_CONTENT
startActivityForResult(Intent.createChooser(intent, "Select Picture"), 0)
}
//comeback from image gallery
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == 0 && resultCode == Activity.RESULT_OK && data != null) {
val selectedPhotoUri = data.data!!
imageUri = selectedPhotoUri
}
}
//prepare request headers
private fun configureHeaders(): MutableMap<String,Any> {
var headerMap = mutableMapOf<String, Any>()
headerMap["Content-Type"] = "multipart/form-data"
headerMap["Accept"] = "application/json, text/plain"
return headerMap
}
private fun uploadImageFile(imageUri: Uri, route: String, onProgression: (Double) -> Unit, onSuccess: () -> Unit, onError: (String?) -> Unit) {
val headers = configureHeaders()
var file = File(imageUri.path)
AndroidNetworking.upload("https://api.ourDomain.com/$route")
.addMultipartFile("file", file)
.addHeaders(headers)
.build()
.setUploadProgressListener { uploaded, total ->
val percentage = 100 * uploaded / total as Double
onProgression(percentage)
}
.getAsJSONObject(object : JSONObjectRequestListener {
override fun onResponse(response: JSONObject?) {
onSuccess()
}
override fun onError(anError: ANError?) {
onError(anError.toString())
}
})
}
How to get the real path to the file to put in parameter of File constructor ?
I am getting these errors when I am uploading images. The path is storing in database table, But the image folder does not have image.
These are the errors
E/ErrorUtil: Error: /document/primary:DCIM/Camera/20190804_111501.jpg (No such file or directory)
W/System.err: java.io.FileNotFoundException: /document/primary:DCIM/Camera/20190804_111501.jpg (No such file or directory)
Here I shared my code.
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == PICK_IMAGE_MULTIPLE && resultCode == Activity.RESULT_OK
&& null != data) {
if(data.getClipData() != null) {
val count = data.getClipData().getItemCount(); //evaluate the count before the for loop --- otherwise, the count is evaluated every loop.
for(i in 0..count-1) {
val imageUri : Uri = data.getClipData().getItemAt(i).uri
// getRealPathFromURI(applicationContext,imageUri)
imageUri.let {
Log.d("imageUri",it.toString())
Log.d("imagePath",it.path)
file = File(it.path)
val jj=Gson()
Log.d("fileIS",jj.toJson(file))
fileType = EnumUtils.FileType.IMAGE.value
val name = file!!.name
Log.d("fimenameis",name)
multipartArray!!.add(MultipartBody.Part.createFormData("files[]", file!!.name, RequestBody.create(MediaType.parse(file!!.path.getMimeType()?: ""), file!!)))
val s = Gson()
Log.d("multipartArray",s.toJson(multipartArray).toString())
}
}
//do something with the image (save it to some directory or whatever you need to do with it here)
} else if(data.getData() != null) {
val imagePath = data.getData().getPath();
fileType = EnumUtils.FileType.IMAGE.value
file = File(imagePath)
multipartArray!!.add(MultipartBody.Part.createFormData("files[]", file!!.name, RequestBody.create(MediaType.parse(file!!.path.getMimeType()?: ""), file!!)))
Log.d("imagePath",imagePath.toString())
//do something with the image (save it to some directory or whatever you need to do with it here)
}
}
yes it happen some time due to file path does not get the absolute path and failed to convert it into file
` private fun getRealPathFromURI(contentURI: Uri): String? {
val result: String?
val cursor = contentResolver.query(contentURI, null, null, null, null)
if (cursor == null) { // Source is Dropbox or other similar local file path
result = contentURI.path
} else {
cursor.moveToFirst()
val idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA)
result = cursor.getString(idx)
cursor.close()
}
return result
}`
val file: File = File(getRealPathFromURI(Uri.parse(imagePath)))
This question already has answers here:
Error "must not be null" in Kotlin
(3 answers)
Closed 4 years ago.
I am working on an Application for making a video from multiple images in kotlin. I got many code of java but can not convert it in propare way to kotlin code. Alwayse got an error cursor.getString(column_index) must not be null. I am just beginner at Kotlin. so can anyone give a brief solution for my problem.
val cursor = contentResolver.query(uri, filePathColumn, null, null, null)
cursor!!.moveToFirst()
val columnIndex = cursor.getColumnIndex(filePathColumn[0])
Hey I m also suffering with same issue nd got the solution. just follow my code.
private var context: Context? = null
var PICK_IMAGE_MULTIPLE = 1
lateinit var imagePath: String
var imagesPathList: MutableList<String> = arrayListOf()
call gallery intent first
if (Build.VERSION.SDK_INT < 19) {
var intent = Intent()
intent.type = "image/*"
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)
intent.action = Intent.ACTION_GET_CONTENT
startActivityForResult(
Intent.createChooser(intent, "Select Picture")
, PICK_IMAGE_MULTIPLE
)
} else {
var intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)
intent.addCategory(Intent.CATEGORY_OPENABLE)
intent.type = "image/*"
startActivityForResult(intent, PICK_IMAGE_MULTIPLE);
}
now check onActivityResult
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
// When an Image is picked
if (requestCode == PICK_IMAGE_MULTIPLE && resultCode == Activity.RESULT_OK
&& null != data
) {
if (data.getClipData() != null) {
var count = data.clipData.itemCount
for (i in 0..count - 1) {
var imageUri: Uri = data.clipData.getItemAt(i).uri
getPathFromURI(imageUri)
}
} else if (data.getData() != null) {
var imagePath: String = data.data.path
Log.e("imagePath", imagePath);
}
displayImageData()
}
}
private fun getPathFromURI(uri: Uri) {
var path: String = uri.path // uri = any content Uri
val databaseUri: Uri
val selection: String?
val selectionArgs: Array<String>?
if (path.contains("/document/image:")) { // files selected from "Documents"
databaseUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
selection = "_id=?"
selectionArgs = arrayOf(DocumentsContract.getDocumentId(uri).split(":")[1])
} else { // files selected from all other sources, especially on Samsung devices
databaseUri = uri
selection = null
selectionArgs = null
}
try {
val projection = arrayOf(
MediaStore.Images.Media.DATA,
MediaStore.Images.Media._ID,
MediaStore.Images.Media.ORIENTATION,
MediaStore.Images.Media.DATE_TAKEN
) // some example data you can query
val cursor = contentResolver.query(
databaseUri,
projection, selection, selectionArgs, null
)
if (cursor.moveToFirst()) {
val columnIndex = cursor.getColumnIndex(projection[0])
imagePath = cursor.getString(columnIndex)
// Log.e("path", imagePath);
imagesPathList.add(imagePath)
}
cursor.close()
} catch (e: Exception) {
Log.e(TAG, e.message, e)
}
}
This is a solution using Github repo for your requirement.
In your app gradle file add these lines
implementation 'com.github.esafirm.android-image-picker:imagepicker:1.13.1'
// for experimental rx picker
implementation 'com.github.esafirm.android-image-picker:rximagepicker:1.13.1'
// If you have a problem with Glide, please use the same Glide version or simply open an issue
implementation 'com.github.bumptech.glide:glide:4.8.0'
in Java class call this to pick or take image
startActivityForResult(ImagePicker.create(getActivity())
.multi()
.folderMode(true)
.returnMode(ReturnMode.ALL)
.getIntent(getActivity()), IpCons.RC_IMAGE_PICKER);
and in onActivityResult() get the arraylist of selected images
#Override
protected void onActivityResult(int requestCode, final int resultCode, Intent data) {
if (ImagePicker.shouldHandle(requestCode, resultCode, data)) {
// Get a list of picked images
List<Image> images = ImagePicker.getImages(data)
// do your stuff here
// or get a single image only
//Image image = ImagePicker.getFirstImageOrNull(data)
}
super.onActivityResult(requestCode, resultCode, data);
}
This code is less complex and no need to handle image multiple selection , just adding multi() to enable multiple selection.
Note:- Copy this code and paste in your kotlin project , the converter will
automatically convert it to kotlin