Kotlin - get Firebase Image DownloadUrl returns "com.google.android.gms.tasks.zzu" - kotlin

I am trying to upload images to Real time Firebase Database by creating two folders using Compressor library and need to display image like messenger with username but i am unable to display image due to url issue
var filePath = mStorageRef!!.child("chat_profile_images")
.child(userId + ".jpg")
//Create another directory for thumbimages ( smaller, compressed images)
var thumbFilePath = mStorageRef!!.child("chat_profile_images")
.child("thumbs")
.child(userId + ".jpg")
filePath.putFile(resultUri)
.addOnCompleteListener{
task: Task<UploadTask.TaskSnapshot> ->
if (task.isSuccessful) {
//Let's get the pic url
var donwloadUrl = task.result?.storage?.downloadUrl.toString()
Log.d(TAG, "Profilepic link: $donwloadUrl")
//Upload Task
var uploadTask: UploadTask = thumbFilePath
.putBytes(thumbByteArray)
uploadTask.addOnCompleteListener{
task: Task<UploadTask.TaskSnapshot> ->
var thumbUrl = task.getResult()?.storage?.downloadUrl.toString()
Log.d(TAG, "Profilepic link: $thumbUrl")
i tried to change downloadUrl
filepath.downloadUrl.toString
thumbFilePath.downloadUrl.toString
but both these values getting "com.google.android.gms.tasks.zzu"
i also tried to change
task.result.sessionurl.downloadUrl.toString
for this one i am getting downloadUrl but not a complete solution for my problem as still i cannot display image i need to get thumbUrl downloadUrl

You have the exact same and very common misunderstanding as in this question, except it's in java. You should follow the documentation here to understand get getDownloadUrl works. As you can see from the linked API documentation, it's not a property getter, it's actually a method that returns a Task<Uri> that tracks the asynchronous fetch of the URL you want, just like the upload task:
filePath.downloadUrl
.addOnSuccessListener { urlTask ->
// download URL is available here
val url = urlTask.result.toString()
}.addOnFailureListener { e ->
// Handle any errors
}
This will only work after the upload is fully complete.

Correct way of getting download link after uploading
here

Just putting out there, I also encounter the same problem,
but both these values getting "com.google.android.gms.tasks.zzu"
but it wasn't the same mistake from the OP
used addOnCompleteListener instead of addOnSuccesslistener
My Error code:
imageRef.downloadUrl.addOnCompleteListener { url ->
val imageURL = url.toString()
println("imageURL: $imageURL , url: $url")
addUserToDatabase(imageURL)
}

Related

Ktor custom feature swap url

Im trying to add a custom feature in Ktor. It's basically a url swapper (we have a scenario where domains might be changed during anytime & can't update the client everytime).
We get the swapper list available and need a CustomFeature in Ktor to swap the url based on list. However, the context.request or request.url - everything is val and Im not able to assign new url to the request.
In Retrofit, it used to work like this
if (currentUrl.contains(urlSwapper.oldUrl)) {
val newUrl = currentUrl.replace(urlSwapper.oldUrl, urlSwapper.newUrl)
val newHttpUrl = request.url.newBuilder(newUrl)!!.build()
// build a new request with the new url. replace it
request = request.newBuilder().url(newHttpUrl).build()
break
}
}
In Ktor feature, Im trying something like this
scope.requestPipeline.intercept(HttpRequestPipeline.Transform) {
val currentUrl =
context.url.protocol.name + "://" + context.url.host + context.url.encodedPath
for (urlSwapper in feature.urlSwappers) {
if (currentUrl.contains(urlSwapper.oldUrl)) {
val newUrl = currentUrl.replace(urlSwapper.oldUrl, urlSwapper.newUrl)
val newHttpUrl = Url(newUrl)
context.url(url = newHttpUrl)
break
}
}
proceedWith(subject)
}
}
Is this the right way to do this ?
Generally yes, this is the right way. I have a few recommendations:
Intercept the sendPipeline instead of the requestPipeline.
An example:
client.sendPipeline.intercept(HttpSendPipeline.State) {
context.url(url = newUrl)
}
Get rid of proceedWith(subject) call because it's redundant.
Try to use Url objects instead of strings. You can get the current URL without affecting context by cloning UrlBuilder and building Url from it: context.url.clone().build()

Xamarin.Forms Open local PDF

I tried to open a locally stored pdf with xamarin.
example code:
var files = Directory.GetFiles(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData));
var filepath = "file://" + files[0];
if (File.Exists(filepath))
{
await Launcher.OpenAsync(filepath);
}
But the file does not open. The only message I get is (android device):
what do I miss?
EDIT
the variable filepath contains:
file:///data/user/0/com.companyname.scgapp_pdfhandler/files/.config/test.pdf
also tried
file://data/user/0/com.companyname.scgapp_pdfhandler/files/.config/test.pdf
does not help
Figured I would add my comment as an answer for easier visibility in case others run into it in the future.
Pass a OpenFileRequest object instead, if you use a string it has to be the correct uri scheme for it. I suspect the uri scheme you are passing to it isn't something that is understood by the system

Loading image from firebase storage not loading image using glide using Kotlin

I am trying to load an image from Firebase Storage using Kotlin and Glide. i added all the dependecies and apply plugin:
implementation 'com.firebaseui:firebase-ui-storage:6.2.0'
implementation 'com.google.firebase:firebase-storage-ktx:19.1.1'
implementation 'com.github.bumptech.glide:glide:4.8.0'
kapt 'com.github.bumptech.glide:compiler:4.9.0'
apply plugin: 'kotlin-kapt'
My code is as follows:
val storageRef = Firebase.storage.reference
val imageref = storageRef.child("test/test.jpg")
imagetest = findViewById(R.id.imageView5)
Glide.with(this)
.load(imageref)
.into(imagetest)
When running the code, the imageview which had a default image goes black indicating that the code is trying to retrieve something from Firebase Storage. but the imageView never populates the downloaded image. assuming the download actually happens.
Am I doing something wrong? my firebase Storage screenshot is below:
I have tested this a little bit more, and Glide seems to load images from HTTPS ok, regardless of where i pull the URL from. But cloud storage provide URL as GS://. so how do i convert the GS:// to HTTPS://?
Please help.
I Figured it out.
imageref = Firebase.storage.reference.child("test/test.jpg")
imageref.downloadUrl.addOnSuccessListener {Uri->
val imageURL = Uri.toString()
imagetest = findViewById(R.id.imageView5)
Glide.with(this)
.load(imageURL)
.into(imagetest)
}
the 'downloadurl' statement actually converts the GS:// to HTTPS://
The difference between the both:
GS URL:
gs://<your_project_id>.appspot.com/test/test.jpg
HTPPS URL:
https://firebasestorage.googleapis.com/v0/b/<your_project_id>.appspot.com/o/test%2Ftest.jpg
Here is the process where my problem fixed -
Step 1 - go to build.gradle(app) and add these dependency
implementation 'com.firebaseui:firebase-ui-storage:4.3.2'
implementation 'com.github.bumptech.glide:glide:4.x.x'
annotationProcessor 'com.github.bumptech.glide:compiler:4.x.x'
Step 2 -
Create a java file
#GlideModule
public class MyAppGlideModule extends AppGlideModule {
#Override
public void registerComponents(Context context, Glide glide, Registry registry) {
registry.append(StorageReference.class, InputStream.class,
new FirebaseImageLoader.Factory());
}
}
Step 3 - Set image where you want
FirebaseStorage storage = FirebaseStorage.getInstance();
StorageReference storageRef = storage.getReferenceFromUrl("gs://<your-app>/").child("folder"); //add .child(nested_folder) if nested folder occurs
GlideApp.with(context)
.load(storageRef.child(test_image.jpg))
.into(holder.thumbnail);
//that .load() will be load like .load(gs://<your_app/folder/test_image.jpg>)

How can the application user save data to one of his own cloud storage?

In my cn1 application, I want to make it possible for the user to back up their own cloud storage. For example, your own Dropbox account.
I was looking for a solution on the WEB. I think what I found (dropbox-codenameone-sdk) I can only manage a known account because I need to know consumerSecret and consumerKey. When I write the code, I don't know the actual user account information.
Based on the operation of other applications, I assume I have to log in to the actual user his account (eg Dropbox).
Please help what API calls can I do this.
Use the Share API in Display. You can zip the data using the zip cn1lib and save it in a file within the file system then use the share API to let the user pick a native app to share it with. On the simulator it will have options such as email/facebook but on the device you should have more options.
I think I'm using the API properly. Although I did not set correctly the file access on my phone.
However, the error occured in the simulator.
The mail and DropBox sharing on my android phone is successful.
I don't like the file getting a prefix (IMG_20200112_204126_). Can I change this?
I include screenshots and a code snippet.
Best regards, Péter
public ShareForm(Resources resourceObjectInstance, Form parentForm) {
this.parentForm = parentForm;
this.theme = resourceObjectInstance;
Layout layout = new BoxLayout(BoxLayout.Y_AXIS);
setLayout(layout);
getToolbar().setBackCommand("", e -> {
this.parentForm.showBack();
});
/* file exist on simulator */
/* String filePath = FileSystemStorage.getInstance().getAppHomePath() + "temp/vendeg_201807011754.json"; */
/* file exist on phone */
String filePath = "file:///storage/emulated/0/Download/stratos.pdf";
String mimeType = "application/octet-stream";
boolean exist = FileSystemStorage.getInstance().exists(filePath);
long size = FileSystemStorage.getInstance().getLength(filePath);
SpanLabel spanLabel0 = new SpanLabel("File path: " + filePath);
SpanLabel spanLabel1 = new SpanLabel("File exist: " + exist);
SpanLabel spanLabel2 = new SpanLabel("File size: " + size);
ShareButton shareButton = new ShareButton();
shareButton.setText("Share data (ShareButton)");
shareButton.addActionListener(e-> {
shareButton.setImageToShare(filePath, mimeType);
shareButton.actionPerformed(e);
});
Button shareButton1 = new Button("Share data (Share API in Display)");
FontImage.setMaterialIcon(shareButton1, FontImage.MATERIAL_SHARE);
shareButton1.addActionListener(e -> {
Display.getInstance().share(null, filePath, mimeType, shareButton1.getBounds(new Rectangle()));
});
addComponent(spanLabel0);
addComponent(spanLabel1);
addComponent(spanLabel2);
addComponent(shareButton);
addComponent(shareButton1);
}

ASP.net - Uploading Files Associated with a Database Record?

I know that there are tons of examples of multi-part form data uploading in ASP.net. However, all of them just upload files to the server, and use System.IO to write it to server disk space. Also, the client side implementations seem to handle files only in uploading, so I can't really use existing upload plugins.
What if I have an existing record and I want to upload images and associate them with the record? Would I need to write database access code in the upload (Api) function, and if so, how do I pass that record's PK with the upload request? Do I instead upload the files in that one request, obtain the file names generated by the server, and then make separate API calls to associate the files with the record?
While at it, does anyone know how YouTube uploading works? From a user's perspective, it seems like we can upload a video, and while uploading, we can set title, description, tags, etc, and even save the record. Is a record for the video immediately created before the API request to upload, which is why we can save info even before upload completes?
Again, I'm not asking HOW to upload files. I'm asking how to associate uploaded files with an existing record and the API calls involved in it. Also, I am asking for what API calls to make WHEN in the user experience when they also input information about what they're uploading.
I'm assuming you're using an api call to get the initial data for displaying a list of files or an individual file. You would have to do this in order to pass the id back to the PUT method to update the file.
Here's a sample of the GET method:
[HttpGet]
public IEnumerable<FileMetaData> Get()
{
var allFiles = MyEntities.Files.Select(f => new FileMetaData()
{
Name = f.Name,
FileName = f.FileName,
Description = f.Description,
FileId = f.Id,
ContentType = f.ContentType,
Tags = f.Tags,
NumberOfKB = f.NumberOfKB
});
return allFiles;
}
Here's a sample of the POST method, which you can adapt to be a PUT (update) instead:
[HttpPost]
[ValidateMimeMultipartContentFilter]
public async Task<IHttpActionResult> PutFile()
{
try
{
var streamProvider =
await Request.Content.ReadAsMultipartAsync(new InMemoryMultipartFormDataStreamProvider());
//We only allow one file
var thisFile = files[0];
//For a PUT version, you would grab the file from the database based on the id included in the form data, instead of creating a new file
var file = new File()
{
FileName = thisFile.FileName,
ContentType = thisFile.ContentType,
NumberOfKB = thisFile.ContentLength
};
//This is the file metadata that your client would pass in as formData on the PUT / POST.
var formData = streamProvider.FormData;
if (formData != null && formData.Count > 0)
{
file.Id = formData["id"];
file.Description = formData["description"];
file.Name = formData["name"] ?? string.Empty;
file.Tags = formData["tags"];
}
file.Resource = thisFile.Data;
//For your PUT, change this to an update.
MyEntities.Entry(file).State = EntityState.Detached;
MyEntities.Files.Add(file);
await MyEntities.SaveChangesAsync();
//return the ID
return Ok(file.Id.ToString());
}
I got the InMemoryMultipartFormDataStreamProvider from this article:
https://conficient.wordpress.com/2013/07/22/async-file-uploads-with-mvc-webapi-and-bootstrap/
And adapted it to fit my needs for the form data I was returning.