This is for my messaging app, whenever I try to send a gif from this GIPHY UI SDK, I get this error: An unknown error occurred, please check the HTTP result code and inner exception for server response.
override fun onGifSelected(media: Media, searchTerm: String?, selectedContentType: GPHContentType) {
val image = media.images.fixedWidth
val gif_url = image!!.gifUrl
val gifUri = Uri.parse(gif_url)
val reference2 = FirebaseDatabase.getInstance().getReference("Friends")
reference2.child(firebaseUser!!.uid)
.addListenerForSingleValueEvent(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
if (snapshot.hasChild(visitorsUid!!)) {
//progressDialog
val pd = ProgressDialog(this#ChatActivity)
pd.setTitle("Please wait...")
pd.setMessage("Sending Gif...")
pd.setCanceledOnTouchOutside(false)
pd.show()
val databaseReference = FirebaseDatabase.getInstance().reference
//file name and path in firebase storage
val filenamePath = "Gif Images/" + firebaseUser!!.uid + System.currentTimeMillis()
val storageReference = FirebaseStorage.getInstance().getReference(filenamePath)
//upload image
storageReference.putFile(gifUri!!)
.addOnSuccessListener { taskSnapshot ->
//image uploaded, get url
val p_uriTask = taskSnapshot.storage.downloadUrl
while (!p_uriTask.isSuccessful);
val p_downloadUri = p_uriTask.result
if (p_uriTask.isSuccessful) {
//image url recieved, save in db
//timestamp
val timestamp = "" + System.currentTimeMillis()
//setup message data
val hashMap = HashMap<String, Any>()
hashMap["sender"] = firebaseUser!!.uid
I think the problem is with this line
val gifUri = Uri.parse(gif_url)
I tried to upload it to my firebase storage
storageReference.putFile(gifUri!!)
Here's what my logcat shows
E/StorageException: No content provider: https://media3.giphy.com/media/iJbxNEqePoPp7l8I0g/200w.gif?cid=e8dbb930ge42y7jitdl6z424143u7ah6bti5nmz7v16mdi53&rid=200w.gif
java.io.FileNotFoundException: No content provider: https://media3.giphy.com/media/iJbxNEqePoPp7l8I0g/200w.gif?cid=e8dbb930ge42y7jitdl6z424143u7ah6bti5nmz7v16mdi53&rid=200w.gif
at android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:1969)
at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:1798)
at android.content.ContentResolver.openInputStream(ContentResolver.java:1475)
There is no way to upload a file to Firebase Storage directly from a URL. You will first have to download the data from the URL, and then upload that local data to Firebase as either a String, a local File object, or a Stream.
Also see:
Upload image from URL to Firebase Storage, which has some valid answers wondering why you'd want to copy the file over to Firebase Storage if Giphy already hosts it.
Related
I want to do get reference from any image with random name in Firebase Storage. I set image name with UUID.randomUUID method but I can not reference that image for deleting it before uploading new image. I can delete that image with entering that file original name which is I copied from Firebase Storage. But I need getting reference for file, without entering name manually.
Here is my Firebase Storage and image names
Here is my Kotlin codes
val uuid = UUID.randomUUID()
val imageName = "$uuid.jpg"
val imagereference =
FirebaseStorage.getInstance().reference.child("images/$cu/profphoto")
.child(imageName)
val ref2 = FirebaseStorage.getInstance().reference.child("images/$cu/profphoto/5a91e7f3-144a-4c38-b7b5-36ed644603ca.jpg")
val db = FirebaseFirestore.getInstance()
ref2.delete().addOnSuccessListener {
}
imagereference.putFile(imageUri!!)
.addOnSuccessListener {}
UPDATE: Solution
Getting to create imagename in Firestore/Realtime Database documents.
/////
val uploadPictureReference =
storage.reference.child("images/$cu/profphoto").child(imageName)
uploadPictureReference.downloadUrl.addOnSuccessListener {
val downloadUrl = it.toString()
val auth = FirebaseAuth.getInstance()
val cu = auth.currentUser?.uid
if (cu != null) {
val postMap = hashMapOf<String, Any>()
postMap.put("imgName", imageName)
postMap.put("downloadUs", downloadUrl)
postMap.put("date", Timestamp.now())
if ("downloadUs".isEmpty()) {
val new = db.collection("Publikusers").document(cu)
new.set(postMap, SetOptions.merge())
.addOnSuccessListener {}
2. Reference to that name
val ref = db.collection("Publikusers").document(cu!!)
ref.get().addOnSuccessListener {
val currentImageName = it.data?.get("imgName")?.toString()
val ref2 =
FirebaseStorage.getInstance().reference.child("images/$cu/profphoto/$currentImageName")
ref2.delete().addOnSuccessListener {}
When I get the ImageURI from the edamam API and try to upload it it gives some errors, which I am not getting when I transform the BitMap I get when taking a picture and transform it into URI, I have tried to transform the ImageURI into Bitmap to pass it to the same function but that doesnt work. This below is the function that does work
fun bitmapToUri(imageBitmap: Bitmap, cacheDir: File): Uri {
val baos = ByteArrayOutputStream()
imageBitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos)
data2 = baos.toByteArray()
val file = File(cacheDir, imageBitmap.toString())
// When calling it with imageBitmap.toString() each item has its image (before the same one repeated)
file.delete()
// Just in case there is another File
file.createNewFile()
val fileOS = FileOutputStream(file)
fileOS.write(data2)
fileOS.flush()
fileOS.close()
baos.close()
return file.toUri()
}
I am getting these errors
E/UploadTask: could not locate file for uploading:
https://www.edamam.com/food-img/28a/28ae0e32feff919253b2cd17c47d2f23.jpg
E/StorageException: StorageException has occurred.
An unknown error occurred, please check the HTTP result code and inner exception for server response.
Code: -13000 HttpResult: 0
E/StorageException: No content provider: https://www.edamam.com/food-img/28a/28ae0e32feff919253b2cd17c47d2f23.jpg
java.io.FileNotFoundException: No content provider: https://www.edamam.com/food-img/28a/28ae0e32feff919253b2cd17c47d2f23.jpg
This is the function I have to upload to Storage
private fun uploadImage() {
val name = binding.inputName?.editText?.text.toString()
val provider = binding.inputProvider?.editText?.text.toString()
val address = binding.inputStreet?.editText?.text.toString()
val fileName = "$name $provider $address"
Log.d("INFO IMAGE URI UPLOAD->>", imageUri.toString())
storage = FirebaseStorage.getInstance().getReference("images/$fileName")
storage.putFile(imageUri).addOnSuccessListener {
binding.imageButton.setImageURI(null)
}.addOnFailureListener {
Toast.makeText(this#NewItem, "Image Not Uploaded", Toast.LENGTH_SHORT).show()
}
}
And this is the value I'm passing to imageUri
imageUri = apiCallBody.listHints.first().food.image.toUri()
Which is this value
https://www.edamam.com/food-img/862/862434152a3191f30c889f10eb2989b0.jpg
The Firebase Storage SDK doesn't allow you to directly upload the contents of random http URLs like the one you're showing here. The putFile method requires a Uri from a ContentProvider that's serviced by an Android app on the device. That's not what you're doing here at all.
If you want to upload an image that exists outside your app, you will have to download it first locally, then upload the data that you downloaded using putBytes, putStream or putFile.
My Method of setting a selected Image to a image view to then be Uploaded is
private val ImageLauncher = registerForActivityResult(ActivityResultContracts.GetContent()){ uri: Uri? ->
uri?.let { binding.GroupImageAdd.setImageURI(uri)
ImageUri = uri
}
}
The Uri is a Local val
set when the images is selected from file
and then
fun UploadImage(UUid: String, uri: Uri, ImageType: String) {
val storageRef = FirebaseStorage.getInstance().reference
Log.d("URI", uri.toString())
val task = storageRef.child("**Image Directory").putFile(uri)
task.addOnSuccessListener {
Log.d("UploadImage", "Task Is Successful")
}.addOnFailureListener {
Log.d("UploadImageFail", "Image Upload Failed ${it.printStackTrace()}")
}
}
Unsure if this helps
I am trying to create an android app with kotlin, this app need to have a mini download manager as I will need to download files from 100MB to 8GB and user can pause and resume download later when the server supports the pause, searching I found the Ktor library and reading the documentation plus some videos on youtube, I managed to write a base code where I could download the files and make the process of stopping the download and keep going all right when one of mine tests gave error there are files whose url pattern is: http://server.com/files?file=/10/55/file.zip
The problem is that I put this link, but Ktor converts to http://server.com/files?file=%2F10%2F55%2Ffile.zip this generate an error response on the server, as I don't have access to the server to change this rule I need to send the right url without encoding. Does anyone know how to do this? Prevent Ktor from doing a URL_encode in the url parameters, I couldn't find anything in the documentation
My code is this:
ktor-client version 1.6.7
fun startDownload(url: String, auth: String = "", userAgentS: String = "", fileName: String = ""){
val client = HttpClient(CIO)
val path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
val file = File.createTempFile("File", "index", path)
runBlocking {
client.get<HttpStatement>(url){
headers {
append(HttpHeaders.Authorization, auth)
append(HttpHeaders.UserAgent, userAgentS)
append(HttpHeaders.Range, "bytes=${file.length()}-")
}
}
.execute { httpResponse ->
val channel: ByteReadChannel = httpResponse.receive()
while (!channel.isClosedForRead) {
val packet = channel.readRemaining(DEFAULT_BUFFER_SIZE.toLong())
while (!packet.isEmpty) {
val bytes = packet.readBytes()
file.appendBytes(bytes)
println("Received ${(file.length())} bytes from ${httpResponse.contentLength()}")
}
}
val pathF = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS + "/${fileName}")
file.renameTo(pathF)
println("A file saved to ${file.path}")
}
}
}
Can anyone help me solve this problem with ktor, if there is no solution, can someone tell me another way to achieve the same goal? Need to be with Kotlin.
update 2022-02-17
Thanks to Aleksei Tirman's help I managed to solve the problem, thank you very much. And the base code looks like this:
fun startDownload(url: String, auth: String = "", userAgentS: String = "", fileName: String = ""){
val client = HttpClient(CIO)
val path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
val file = File.createTempFile("File", "index", path)
runBlocking {
client.get<HttpStatement>(url){
url {
parameters.urlEncodingOption = UrlEncodingOption.NO_ENCODING
}
headers {
append(HttpHeaders.Authorization, auth)
append(HttpHeaders.UserAgent, userAgentS)
append(HttpHeaders.Range, "bytes=${file.length()}-")
}
}
.execute { httpResponse ->
val channel: ByteReadChannel = httpResponse.receive()
while (!channel.isClosedForRead) {
val packet = channel.readRemaining(DEFAULT_BUFFER_SIZE.toLong())
while (!packet.isEmpty) {
val bytes = packet.readBytes()
file.appendBytes(bytes)
println("Received ${(file.length())} bytes from ${httpResponse.contentLength()}")
}
}
val pathF = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS + "/${fileName}")
file.renameTo(pathF)
println("A file saved to ${file.path}")
}
}
}
You can disable query parameters encoding by assigning the UrlEncodingOption.NO_ENCODING value to the urlEncodingOption property of the ParametersBuilder. Here is an example:
val requestBuilder = HttpRequestBuilder()
requestBuilder.url {
protocol = URLProtocol.HTTP
host = "httpbin.org"
path("get")
parameters.urlEncodingOption = UrlEncodingOption.NO_ENCODING
parameters.append("file", "/10/55/file.zip")
}
val response = client.get<String>(requestBuilder)
I'm uploading user's profile pic to azure server using Azure blob storage.
This is my code
fun uploadImage(path: String, fileInputStream: FileInputStream) =
viewModelScope.launch(Dispatchers.IO) {
try {
val storageAccount = CloudStorageAccount.parse(connectionString)
val bobClient = storageAccount.createCloudBlobClient()
val container = bobClient.getContainerReference(storageContainer)
val blob = container.getBlockBlobReference("$storageContainer.jpg")
val file = File(path)
blob.upload(fileInputStream, file.length() )
} catch (e: Exception) {
e.printStackTrace()
}
}
The code is working fine and the image is uploading, when I checked using the URL, but how can I get a callback on success or error of uploading, so that I can perform action on the basis of that.
How can I know when upload finishes or if any error occurred?
I have some sort of comments section in my app where I have attached a child event listener to get real-time comment update.
private fun addListener() {
reference.addChildEventListener(this)
}
override fun onChildAdded(dataSnapshot: DataSnapshot, previousChildName: String?) {
val newPost = dataSnapshot.getValue(Comment::class.java)
adapter.addToTop(newPost)
key.add(dataSnapshot.key!!)
errorDiscussion.visibility = View.GONE
}
While adding a new comment, tt works perfectly when I don't upload an image to FirebaseStorage and post a comment with null value to the attachImage field.
But when I try to upload an image to FirebaseStorage and add than try to push a new comment with attachImage field in that particular databaseReference the data actually get pushed to the database but the onChildAdded method is not invoked. And the listener is de-attached.
What I see in the logs are some SocketTimeoutException
08-30 09:18:43.175 12208-25905/np.com.aawaz.csitentrance D/NativeCrypto: jniThrowException: java/net/SocketTimeoutException: Read timed out
08-30 09:18:43.693 12208-25905/np.com.aawaz.csitentrance D/UploadTask: Increasing chunk size to 524288
08-30 09:18:43.719 12208-25905/np.com.aawaz.csitentrance D/NativeCrypto: jniThrowException: java/net/SocketTimeoutException: Read timed out
Am I doing something wrong here? Isn't it the good way to accomplish this task.
Image Upload Logic
val ref = FirebaseStorage.getInstance().getReference("discussion").child(fileName)
val file = Uri.fromFile(File(image?.path))
val uploadTask = ref.putFile(file)
val progressDialog = MaterialDialog.Builder(this)
.content("Uploading....")
.progress(false, 100)
.autoDismiss(false)
.build()
progressDialog.show()
uploadTask.addOnProgressListener {
val data = it.bytesTransferred / it.totalByteCount * 100;
val progress = data.toInt()
progressDialog.setProgress(progress)
}
uploadTask.addOnSuccessListener {
addCommentWithImage(addCommentTextDiscussion.text.toString(), fileName)
progressDialog.dismiss()
image = null
itemSelected.visibility = View.GONE
}
uploadTask.addOnFailureListener {
progressDialog.dismiss()
it.printStackTrace()
Toast.makeText(this, "Unable to upload image, please try again later.", Toast.LENGTH_SHORT).show()
}
Database Push Logic
val comment = Comment(currentUser!!.uid, currentUser.displayName, System.currentTimeMillis(), message, currentUser.photoUrl!!.toString(), imagePath)
val postValues = comment.toMap()
reference.push().setValue(postValues)