Adding Metadata to Uploaded Image Firebase/Kotlin - android

I am able to upload a corresponding image through the call:
var uploadTask = firebase_ref.putStream(stream)
I want to add metadata to the uploaded image, so I want to do this inside the putStream call:
var uploadTask = firebase_ref.putStream(stream, metadata)
Now the issue is I am able to import StorageMetadata with this import:
import com.google.firebase.storage.*
I am able to create a StorageMetadata object like:
var metadata = StorageMetadata()
I go to adjust a simple name parameter for the metadata as:
metadata.name = "something"
ERROR:
val cannot be reassigned
I have looked at this reference:
https://firebase.google.com/docs/storage/android/upload-files#kotlin+ktx_5
They suggest doing:
var metadata = storageMetadata {
contentType = "image/jpg"
}
ERROR:
unresolved reference storageMetadata
What is the best way to adjust a simple StorageMetadata and pass it into putStream?

The Kotlin+KTX sample it's showing depends on adding the Cloud Storage for Firebase KTX library to your dependencies (that's what the "KTX" is telling you). After you do that, you will have the storageMetadata builder available in your code as shown in the documentation. If you want to use that, be sure to follow the documentation a linked here. You will add a dependency that looks like this:
// See maven.google.com for the latest versions
// This library transitively includes the firebase-storage library
implementation 'com.google.firebase:firebase-storage-ktx:$VERSION'
If you don't want to use the KTX library, you can work with the metadata object using the StorageMetadata.Builder object as shown in the Java sample. StorageMetadata objects are immutable (notice there are no setters in that class), so you can't create one and just modify it - you have to build one using the provided builder.

Related

How to use Kotlin Symbol Processing (KSP) to populate an existing list

I've been playing recently with KSP and have managed to develop interesting capabilities (such as automatic recyclerview and view holder generators based on their layout id), and so far all is well.
However, I am now trying to do something different than creating files based on the annotations I design. Instead of creating files, I would only want to populate a list with the classes/objects annotated by me.
Example:
ClassA.kt
#MyAnnotation
class ClassA(context: Context): SomeBaseClass(context) {
override fun baseClassFunction() {
// custom code goes here
}
}
ClassB.kt
#MyAnnotation
class ClassB(context: Context): SomeBaseClass(context) {
override fun baseClassFunction() {
// custom code goes here
}
}
MyListAgregator.kt
object MyListAgregator {
const val classList: List<SomeBaseClass> = mutableListOf()
}
Where my custom KSP would do the following
Collect all classes/objects (the usual) that are annotated by my
#MyAnnotation
Create an instance of them with the appropriate
parameters (in this case just a context)
Add each one to the classList in the MyListAgregator
I can always get to the point of the class collection (step 1) but the rest is a complete mystery to me, and feels like KSP always expects to create code, not execute it? Perhaps I am incorrect on the later one, but I could not find anything related to that explained in the available documentation.
Another alternative I considered, but would rather avoid out of concern for any negative hit (performance, for example) is to actually modify that MyListAgregator file directly to include all the instances in the list, as if I had written them myself. However, I would still prefer to go with the previous option instead if it is at all possible.
First, you need to establish a ruleset that will be applied to the classes annotated with your annotation (symbol in KSP glossary). For example, they must contain one argument, that argument must be a member property and of type Context and must be subclass of SomeBaseClass. I suggest first look up for correct inheritance then look up for argument count and type.
You are still within reading and exploring all files with this symbol. Filtering based on this ruleset you will land with a set of classes at point 2.
Here, KSP can provide you with the interface to generate your code. However, KSP will not let you edit the source file, but generate new one based on your conditions. Here you have to write your implementation for the overriden function, by visiting it
You can preserve the output (newly generated classes at step 2) and generate your MyListAggregator object.

kotlin- PaymentSessionConfiguration

Hello I am trying to update stripe but when I have to call PaymentSessionConfig my code blocks because the companion of the PaymentSessionConfig class is in private, I cannot modify the class because it is in read only, here is the line :
mPaymentSession = PaymentSession (activity = summaryActivity, config = PaymentSessionConfig)
and the error message I have :
Cannot access 'Companion': it is private in 'PaymentSessionConfig'
Type mismatch.
Required:
PaymentSessionConfig
Found:
PaymentSessionConfig.Companion
Can you share the details of what versions of the SDK you're updating from and to? The migration docs cover a lot of details changes for various versions.
Is it possible you mean to reference some paymentSessionConfig, or what is your config here?
See this example implementation using the PaymentSessionConfig.Builder() (github)

What is the constructor for Firebase Storage Reference?

So I tried to follow the tutorial on youtube about Firebase Storage, and I found this code:
val filePathAndName="product_images/"+""+timeStamp
val storageReference=FirebaseStorage.getInstance().getReference(filePathAndName)
But the code above uses Java in the tutorial, I changed it to Kotlin syntax and I tried to run the application and it worked.
After reading the documentation regarding Firebase Storage, I found:
// Create a child reference
// imagesRef now points to "images"
var imagesRef: StorageReference? = storageRef.child("images")
// Child references can also take paths
// spaceRef now points to "images/space.jpg
// imagesRef still points to "images"
var spaceRef = storageRef.child("images/space.jpg")
So what is the proper way to declare a reference? And what is the function of filePathAndName on getReference(filePathAndName)? Does it have the same functionality as a child in Kotlin syntax?
When you have an instance of FirebaseStorage you can call reference/getReference on it to get a StorageReference object to the root, or (by passing in a path string) to a specific file.
When you have a StorageReference object, you can call child(...) on it to get a reference to a location under that reference.
It's similar to how you deal with directories in many other parts of programming: you can either pass in the entire path to a file right away, or you can pass in parts of the path and build the same path that way.
So as shown in the documentation on creating references, you can get a reference to the root with:
var storageRef = storage.reference
From there, you can then get a reference to a specific file with:
var spaceRef = storageRef.child("images/space.jpg")
But you can also replace the above two lines with this single line:
var storageRef = storage.getReference("images/space.jpg")
The above approaches have the exact same result, and it makes no practical difference which one you use (as these references are lightweight objects that make no call to the network yet).

java.lang.FileNotFoundException in Android/Kotlin even though file is present

I have a data class called Contact which has a companion object property 'allContacts: List' which returns contacts after parsing them from a JSON file.
Relevant code:
val allContacts: List<Contact>
get() {
val json = JSONObject(File("app/src/main/res/data/contacts.json").readText()).getJSONArray("contacts")
val contacts = mutableListOf<Contact>()
...
I do indeed have a contacts.json in res/data package. (data package created manually).
Here's the proof:
Why is this happening? Is the contacts.json file not included in the final .apk?
I have tried logging the current path of the app using
Log.i('.MainActivity', System.getProperty('user.dir'))
But always get . in Logcat.
EDIT: I decompiled the apk in Android Studio and found no traces of contacts.json
Your file doesn't exist in the same project directory you expect it to.
You have to create a resource directory raw and paste your file in there.
Then, you can reference your file as R.raw.contacts wherever you need to reference the file.
Reading the file is another story.
I found it best to create a separate top-level extension function for reading and returning the file contents
fun Activity.readFile(fileID: Int): String {
val inputStream = this.resources.openRawResources(fileID)
return inputStream.use{it.readText()} // Returns entirety of file contents as string.
}

Why Apollo-android is not generating custom types even after adding custom mapping in the gradle?

Steps i am following to implement custom types in Android
I have added customTypeMapping in the app's gradle file.
Also created a customtype Adapater.
Problem
Next i am trying to add it to the apollo client where i have to pass customtype and the adapter but the problem is that i am not getting any custom type that i am generating. Apollo only has ID,Numeric,Date etc there but the custom type i am mapping isn't being generated by the apollo-client.
I am using official docs https://github.com/apollographql/apollo-android#custom-scalar-types to implement it
From https://github.com/apollographql/apollo-android/issues/1702:
You will need to write the code for the adapter that you pass to addCustomTypeAdapter() in addition to specifying customTypeMapping in your gradle file. See https://github.com/apollographql/apollo-android#custom-scalar-types for an exemple of adapter for java.util.Date
Apollo cannot generate the custom typse as by definition this is a type you control.
PS: please do not cross post on stack overflow + github as it duplicates the effort to reply and scatters information.
In your apps build.gradle add this:
android {
...
apollo {
customTypeMapping = [ "customtype":"java.lang.String"] //or the appropriate type mapping
}
}
In where you build your apollo client:
val apolloClient = ApolloClient.builder()
.addCustomTypeAdapter(CustomType.YOUTTYPE, customAdapter)
.serverUrl(BASE_URL)
.okHttpClient(okHttpClient)
.build()
private var customAdapter: CustomTypeAdapter<String> = object : CustomTypeAdapter<String> {
override fun decode(#NotNull value: CustomTypeValue<*>): String = value.value.toString()
#NotNull
override fun encode(#NotNull value: String): CustomTypeValue<*> =
CustomTypeValue.GraphQLString(value)
//appropriate type mapping
}

Categories

Resources