I'm writing an Android app that has some functionality encapsulated in an internal library. However, for this functionality to work, the library needs an instance of the Application Context. What's the best way to give the library this Context? I see a few options, none of them appealing:
Have my library classes extend Application, and call getApplicationContext()
This is generally discouraged
Have my library classes each implement the singleton pattern, and have each caller pass in a Context each time they get a reference to the singleton.
This requires every caller to retrieve the Application Context before using the library, and also requires that the caller call against an instance of the library instead of against static methods defined on the library class (and thus further requires keeping a reference to this instance).
What's the best way to give the library this Context?
Pass a Context into the methods exposed by your library that need a Context. This is what the Android SDK does in places.
Or, change your library to expose objects, not static methods, and have the objects hold an instance of Context (supplied to the constructor or factory method that created the instance).
Have my library classes extend Application, and call getApplicationContext()
If you can call getApplicationContext() on a Context, you would just do that, without needing to subclass Application.
This is a solution that I found, which I have not tested, but is used by Firebase apparently to avoid creating an init method:
"What happens on Application start is, that it registers all ContentProviders in the system (calling onCreate). This means that at this point no activity has been started, but we have access to the (Application)Context, where we can initialise our library using this Context"
Essentially you are utilizing the onCreate of the empty ContentProvider as the init. It is hacky, but seamless.
https://medium.com/#andretietz/auto-initialize-your-android-library-2349daf06920
I am not sure best practice for this case but i would like to set the Context in my singleton class during Application onCreate.
MyLibrary.init(this);
Why?
If you had use Crashlytic/Fabric before, you will found that they are using
Fabric.with(this, new Crashlytics());
If you read the code in Fabric will found that they store the Context in Fabric singleton.
Facebook Android SDK did similar thing:
FacebookSdk.sdkInitialize(getApplicationContext());
If your browse their codes will found that they store static Context.
Well, which are the best practices? I am not sure but i believe those are awesome developers create awesome libraries and they did debate on this before come out this libraries. Anyway, I am still learning how to write best android library and come across this topics.
App Startup library is the part of Android Jetpack. It allows to listen application startup without the cost of multiple ContentProviders. Also, it provides the ability to handle dependencies tree.
Implementation example
Related
Some of my Kotlin classes are implemented by a native library (Rust using jni). These classes are used in most of the activies and by one sync service (a second service may come later).
What is the recommended solution to load this library and handle loading errors (for example sending a bug report if loading fails)?
Basic examples loads a library in the MainActivity.onCreate. Or often I see a static block inside the MainActivity class.
Another method may be loading the library in a derived class from Application. But I'm not sure if there is only one Application instance for all activities and services or if one `` Application``` instance is created for each service and another one for all activities.
So my question is: where to put System.loadLibrary()?
Yes, the Application is a singleton for the whole Android app. But you should not worry, LoadLibrary() does nothing if the library had been loaded before. So, the best practice is to add LoadLibrary in static blocks of all classes that depend on this library.
Consider using ReLinker library that provides logging and also workarounds for some widespread problems with loading native libraries.
Coming from Java EE to an Android application (i'm not Guru in Java EE), For a fatest load of the application, we decided to process a files asynchronously, when the application starts, we launch some asynchronous channels to read the files, then we open the main activity, the idea is the user may not go directly to the use cases which need these files, but if he go it direclty and the asynchronous read wasn't terminated, he should wait a while(what the client wanted).
My question is how to passe the Future object between activities? my team agreed for using static methods or singletons, but i really don't love singleton because its an antipattern and i don't like static methods because they behave nearly like singleton.
Trying to use parceable or serializable, but future doesn't use implement anyone of it, i tried to use RoboGuice (its based on static fields but its busniss) but its a little buggy, how can i do it in android in pretty way, if there's another idea, i will be obliged to use singleton or static methods.
EventBus can be used to send objects from 1 place to another (e.g. asyncTask to Activity). It's great and easy to use, and it will accomplish what you're trying to do perfectly.
You can create your custom object classes to send between almost any 2 classes, Activities, Services, or whatever you with.
Converting an existing Android application to a library is incredibly simple: All I have to do is check the is Library checkbox in the project's properties.
However, once this easy step has been applied, a much more serious task lies ahead: How to retain the original application code unchanged (as a library!), while building different applications based on it.
That is, I don't really want to add another activity, but rather re-use the original activity (now in a library), where only a few methods (in the one-and-only activity) are different in each derived application.
Is the solution really is as simple as subclassing the library's activity in each application based on it?
What caveats should I watch for?
Is there a better approach?
You will mostly have to derive new classes from the ones included in the librairy or call their methods. If your librairy has classes such as activities, applications, you can extends them has you said.
Another solution could be to isolate the code you want to reuse and plugit into other activities by dependency injection. But this framework seems an overkill to me where you can just derive new classes.
A more android specific problem could be : how to call my new activities from within my new applications. The answer here relies in intent and to use different action names to call for the extended activities.
Regards,
Stéphane
I'm making an app in conjunction with a websites API, and in the application I created a class that would deal with the OAuth authentication and API calls. Now, how would I be able to instantiate an object from that class, and share the object across various Activities? I'm quite sure what would be the best practice in a situation like this.
Thanks a bunch!
You could create a subclass of Application and store your authorization module there. This would be accessible to all of your activities within that process.
You just need to declare you Application subclass in your manifest and it will be instantiated instead of the default.
From your Activity, you would call getApplication() and cast it to the correct subclass type and access your custom methods
Since the whole Android stuff is open source I was thinking about to do some minor modifications in a few internal classes from the com.android.internal.telephony package and of course then I would love if somehow my application could use the modified classes. I was thinking about replacing the classes with the original ones at runtime by using reflection or other kind of unknown java tricks :D ...maybe what I'm trying to do is impossible :( I don't know that's why I'm asking.
Note: The changes in the internal classes would not change their functionality in any way, its more about extending their functionality so even if other apps would use the modified versions it would not break them!
Why I want to do it? What I'm trying to achieve ?
Well i would like to modify the com.android.internal.telephony.gsm.CallTracker internal class so i could do proper call handling (call blocking etc..)
Maybe if you know about another way how to do what I want to I would like to hear about it :)
Note2: I know about the method when you handle the android.intent.action.PHONE_STATE, action , but its simply too late to react when this action is broadcasted. I'm really looking for a better solution even if that solution involve ugly hacks :)
As always thanks for all your replies...
You cannot do this :) I'll let you imagine what would happen if any application was allowed to freely replace core parts of the system. You can download the Android source code and you can modify it and you can upload the modifications to your phone (if your phone is rooted/unlocked) but you cannot apply such modifications with a simple app.
Changing a classes functionality (methods, byte code) after a class ha been loaded is impossible. Reflection/Invocation does not affect classes but static fields and instances only.
Your looking at a way to add additional methods or change existing methods of a running system, because the classes in question probably will be loaded already when your 'hacking' application is executed.
The only technical approach that I see is to change the classes in advance and deploy a modified system. I'm just ignoring possible licensing issues and security at the moment. But even with this way, your software would depend on a custom OS, a branch from some andorid version, disconnected from official updates, and you'd have to ask your customers to install a custom OS with, say, unknown features.
Sidenote - I'm very happy, that this is really impossible, otherwise my mobile would already be full of trojans, viruses, etc...
Romain is correct you can't and shouldn't try to change existing system classes.
That said, implementing call screening as you suggest should be possible by creating a replacement to the dialer application that handles phone calls.
Specifically the intent ACTION_ANSWER should be handled by your application, which could then either implement a dialer-like interface or open the dialer app (or any other call manager) explicitly.
There are actually ways to hack on Android framework classes, it just depends on which ones you want to hack.
You must extend the class you intent to hack on.
If you want to override package private methods and/or access package private variables you can put your class in the same package.
You can use reflection.
I've actually had to do this to work around bugs. Romain is correct, to an extent. It all depends on the structure of the code you are trying to hack on. You definitely can't hack on Android internals, but you can hack on other framework classes like Activity, View, etc.