In my app, I put helper methods in the top level, not contained in any class, so I can call any of them from anywhere. And I have an assets folder (app/src/main/assets) with text files in it.
I get access to this folder inside Main Activity using this code
val file: String = applicationContext.assets.open("folderInAssets/filename.txt").bufferedReader().use {
it.readText()
}
However, it seems that I cannot access the assets folder from outside activities or classes. applicationContext is not defined, and I cannot have access to a Context. I also tried
Application().assets.open(...)
but it gives me the error: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.AssetManager android.content.Context.getAssets()' on a null object reference
My Question: How can I get access to the folder from a top-level function in Kotlin? And is there a preferable "Kotlinic" way to define helper methods in an app?
Thanks in Advance.
Related
I try to create a POST request with Android Volley but when I type volleyRequestQueue = Volley.newRequestQueue(this), this is a error "this is not defined in this context".
I know that I have this problem because my function can't resolve Android Context but I don't understand how to import the context in my file.
Here you have my project scheme:
and the error
The function is called in the "FormsAddAliments" file.
Thanks you !
The error "this is not defined in this context" is not referring to the abstract class android.content.Context, but rather the context of the code.
You are using this in a top level function in a file. There is no object that this can be a reference to, if you want it to be a top level function and have an object that this can reference, you will need to declare it as an extension function on the type that you want this to reference like Context.sendFoodToServer(...). This should work, but it is likely violating some design principles to do it this way (usually passing a context around is a bad idea because it can lead to context leaking).
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).
I am using realm in our iOS and Android app. For some reason i want to rename one of my realm object.
Initially we name the object Demo and now I want to change it to RealmDemo
In android we achieved it by using #RealmClass annotation
#RealmClass(name = "Demo")
open class RealmDemo : RealmObject() {
}
On iOS side i am not sure how exactly i can do similar as i did in android.
class RealmDemo: Object {
override static func className() -> String {
"Demo"
}
}
I tried above ^ but getting following error "Terminating app due to uncaught exception 'RLMException', reason: 'Object type 'Demo' not managed by the Realm'"
Two things.
First, You can name an object anything you want and change its name at any time.
HOWEVER, that's a destructive change, and Realm doesn't have any way to know the the newly named object 'is the same object' as the prior object.
How that's handled depends on what the use case is:
If this is a development situation, delete your local Realm files and run the app and the object with the new name will be created automatically.
If this is production then a migration block is needed (as on any platform) to migrate the data from the old object to the new one.
Secondly, The other important thing is the name of the object is now RealmDemo, whereas the prior object is Demo
class RealmDemo: Object {
so technically those are two separate objects. To Realm, you've abandoned the Demo object totally and that's a destructive change. Demo is still hanging around but is not referenced in your code so an error is thrown
On a possibly unrelated note, the className function references Demo
override static func className() -> String {
"Demo"
}
But the object name is RealmDemo.
It's not clear why the className function exists but it's not required or really needed. See the documentation for objects to get a feel for their structure - they may need a Primary Key
Seems like realm does not support className overriding for cocoa/ios.
https://github.com/realm/realm-cocoa/issues/2194
https://github.com/realm/realm-cocoa/issues/6624
I came across the following methods:
Environment.getDataDirectory() : /data
and
getFilesDir() : /data/data/package/files
One method uses Environment and other does not.
whats the significance. It would be simple to use without Environment because the method names are not same.
Well, either I don't understand what you don't understand, either you don't understand the difference between a call of a method like Environment.method() and method() ...
If that's what you want to understand, why the class name is written at the first call, is because the first method is a STATIC one and you don't need an instance of that class to call it. It also belongs to Environment class. ALL static methods are called with the name of their class(when you are inside the class, ex. Test class or a subclass, then and only then you can call without the name of the class in front of its call. And even so, you can put the class name there...
The getFilesDir() is a method that needs an instantance of the class where it belongs - that is ContextWrapper - or an instance of a subclass of it to be called on... So, if you are in an Activity (which is an indirect subclass of ContextWrapper), you can call it like : this.getFilesDir() or simply getFilesDir(). You can also call it like getActivity().getFilesDir() from a Fragment or getApplication().getFilesDir() and so on... You can go to ContextWrapper Class from Android and look to the hierarchy.
Sorry if this explanation was not what you needed, but I understand you know what these methods are used for...
I have c++ lib used with my application. I passed java object to jni and saved it to global reference. Then, I wish to call method of this java object from jni from antoher thread (I use pthread).
Java class is:
public class WaitingServiceReadyCallback {
public void ready(String serviceName) throws Exception { ... // some code }
}
To call java method I use next code:
jvm->AttachCurrentThread(&env, 0);
cls = env->GetObjectClass(__obj__); // __obj__ is global reference to object.
if (!cls)
goto detach;
mid = env->GetMethodID(cls, "ready", "(Ljava/lang/String;)V");
There GetMethodID fails to find method.
When I use
cls = env->FindClass("com/mypackage/WaitingServiceReadyCallback");
instead of GetObjectClass, FindClass fails to find this class.
I tried to check class name of the object referencd by my __obj__ global reference (used getName from com/java/Class, made call to getName in the same place of my code as above call to ready), I got right class name - com.mypackage.WaitingServiceReadyCallback.
I am sure that class exists and loaded (java code executed before jni and instance of this class is created there), I am sure that method exists in the class.
So, I can't understand, what I done wrong?
I met this problem. The reason in short: within another thread VM does not provide us an info about loaded classes. I've solved this by storing the classloader of some sample java object and then using it for manual loading of needed classes from another threads.