How to load native lib in android with static{System.loadLibrary()} - android

I was studying the android source code and I found that there are many places in framework that use native code without using static{System.loadLibrary()}.
For example, in SystemServer.java, native method "init1(args)" is called but there is no static{System.loadLibrary()} in the file. How native code is loaded without static{System.loadLibrary()}? thanks.

The native library has to be loaded only once for the whole application, so it has probably already been loaded by another class which has been instantiated before. Note that this is not a best practice as it makes assumptions on the order by which the classes are called!
A commonly used technic to avoid this is to create a Loader class like this:
class Loader {
private static boolean done = false;
protected static synchronized void load() {
if (done)
return;
System.loadLibrary("library_name");
done = true;
}
}
This way, if you call static{Loader.load();} on every class that requires the use of native functions, you ensure that the library has been loaded (and only once).

Related

Android app with weak reference and singleton

I'm in the process of completely redesigning my Android app. Before, EVERYTHING was in the same class.
So I tried to redraw everything so that the code is clearer apart Admob than the doc advice to put in the Main thread, I separate the different part of my code in class. So I used two technique: I created a songleton that contains variables that I want to have access to constantly,and I call my classes via weak reference.
Here is what it looks like:
For example, the UIManager class that needs to update the game's IU have a weak reference looks like this:
private static SoftReference<UIManager> ManageUI;
static{ManageUI= new SoftReference<>(null);}
static UIManager get()
{
if(ManageUI.get()==null)
{
ManageUI= new SoftReference<>(new UIManager());
}
return ManageUI.get();
}
GameManager Manager=GameManager.getInstance();
to be able to use the findviewbyid for example I place in method argument the main class that is the mainthread
the singleton that contains all my variables that I want to have permanent access to looks like this:
private GameManager()
{}
/** Holder */
private static class Manager
{
/** Instance unique non préinitialisée */
private final static GameManager instance = new GameManager();
}
/** Point d'accès pour l'instance unique du singleton */
public static GameManager getInstance()
{
return Manager.instance;
}
To separate all in different class, I pass argument to my method so I can call au stuff belong to Activity like that:
(My main class is called GamePlay)
void OpenGlobalScene(GamePlay activity)
{
Manager.OnTitle=false;
if (!checkLayout(activity,R.id.globalscene)) {
LayoutInflater(activity,9, true);
LinearLayout GamePlan = (LinearLayout) activity.findViewById(R.id.globalscene);
GamePlan.setAlpha(Manager.AlphaBord);
}
}
For now, I have not noticed any problems except a few slownesses on old android phone 4.4.2.
Also compared to my old code were EVERYTHING was in the same class, it's much easier to change pieces of code (going to the inapp billing V3 was simpler since everything was in one class that I call like the others with weak referencre)
My questions are:
-What are the problems that such a structure might pose?
I had also chosen that structure to not load or leave in memory things that are not useful
-How are chance that Android will erase from memory an action in progress called with weak reference?
-As you can see I pass the activity has argument to the method, sometimes I pass it from a method to another. Is that fact can cause some trouble?
Thank you for your help.
Check Dagger2 is better than the clasic singleton https://developer.android.com/training/dependency-injection/dagger-android?hl=es-419
thanks for your answer and your tips. I'am gonna check this out.
Anyone else know something about consequences on memory when using weak references ?

How to configure Android library from an app that imports it?

I'm kinda new to Android development so my question might be weird or not even possible. I wouldn't know!
Anyway, I'm building multiple apps that will have a lot of shared elements, so I decided to build a library with those components and use it in all of the apps, rather than stupid copying and pasting code.
For example, the library handles the welcome screen and login/signup flow activities, among other things. So here are the problems this approach might cause:
While the behavior is the same across the apps, but the logo that I show at the welcome screen is different. Right now I populate it with an image resource from the library resources (R class) which will be the same for all apps and is obviously not correct.
The login/signup process is based on Firebase, which will require the app to have a key to be able to use them. Right now I also populate it with a dummy string resource from the library resources.
So my question really boils down to 3 parts:
Is there anyway I could pass this info from the app to the library? can I somehow modify the R class of the library? Or can I use the app's R class from the library? I can also call this part of the library as a function passing the parameters I need. But the first solution looks maybe more clean to me?
Whatever the answer to Q1 is. Where would I do this and how? The library has the welcome activity itself which is supposed to be the first activity in the app. How and where do I do this once the app starts and before the first activity starts?
If what I'm doing is wrong or impossible, is there any other way to achieve it?
Is there anyway I could pass this info from the app to the library?
can I somehow modify the R class of the library? Or can I use the
app's R class from the library? I can also call this part of the
library as a function passing the parameters I need. But the first
solution looks maybe more clean to me?
You don't need to modify the R class because you can override the resource file by creating a file with the same name. But it's not a clean solution because you constantly need to ensure your project and library resources name are the same.
Whatever the answer to Q1 is. Where would I do this and how? The
library has the welcome activity itself which is supposed to be the
first activity in the app. How and where do I do this once the app
starts and before the first activity starts?
Instead of overriding the resources name, you're better to modify your library to receive a configuration as a contract to use the library. Here the sample:
First, create the class for holding the configuration:
public class Configuration {
private int welcomeImageDrawableId;
private int logoDrawableId;
// constructor
public Configuration(int welcomeImageDrawableId, int logoDrawableId) {
this.welcomeImageDrawableId = welcomeImageDrawableId;
this.logoDrawableId = logoDrawableId;
}
// setter and getter.
public int getLogoDrawableId() {
return logoDrawableId;
}
}
Second, use the configuration class for the library by creating a Singleton class which will be used internally by the library:
public class MyLibrary {
private static MyLibrary myLibrary;
private Configuration configuration;
private MyLibrary(){}
private MyLibrary(Configuration configuration) {
this.configuration = configuration;
}
public static MyLibrary getInstance() {
if(myLibrary == null) {
throw new RuntimeException("Need call createInstanceWith method first!!");
}
return myLibrary;
}
public static MyLibrary createInstanceWith(Configuration configuration) {
if(myLibrary == null) {
synchronized(MyLibrary.class) {
if (myLibrary == null) {
myLibrary = new MyLibrary(configuration);
}
}
}
return test;
}
public Configuration getConfiguration() {
return configuration;
}
}
Third, use the configuration class in your library via the singleton class. something like this:
// assume imvLogo is an existing ImageView
Configuration configuration = MyLibrary.getInstance().getConfiguration();
imvLogo.setImageResource(configuration.getLogoDrawableId());
Last, register the contract when the library is used with:
Configuration configuration = new Configuration(R.drawable.welcome, R.drawable.logo);
MyLibrary.createInstanceWith(configuration);
Note: all the code isn't tested yet, error is to be expected.
Apart from the solution above, I also found another way to achieve this whole thing without having to initialize libraries and whatnot.
I think the correct way to do this is to use productFlavors in the library. This allows the library to share the one main set of source code, one main set of resources, then an extra set of resource per app/flavors. This is very sufficient for my purposes.
For more info about build variants and flavors:
https://developer.android.com/studio/build/build-variants

Android intercept class loading

Is it possible to intercept Android's default class loading and conditionally avoid loading a class ?
My motivation is to intercept Android's default class loading process and avoid loading the class based on a condition, something like
if (!fooScope) {
throw IllegalStateException("Trying to load class from FooScope");
}
I am not intending to change where the classes are loaded from, but to have fine grained control over what classes can get loaded at what point of time, which I call Strict class loading. In this, any class which is not supposed to be loaded until certain conditions are met, should not be loaded. I am looking for ways to intercept the class loading to achieve this.
You'll probably need to use some kind of Hooking library.
like this library (https://github.com/cmzy/ZHookLib) which supports only up to Android 4.4
then you'll need to hook the loadClass(String name) method of ClassLoader.class
in order to see all the loaded classes.
but still there is the problem of the order in which the classes are loaded.
you could try to do it from a class which extends Application which might be loaded first but im not sure..
public class MyApplication extends Application {
static {
// code in static block is executed when the class is loaded
Set<Unhook> unhooks2 = ZHook.hookAllMethods(ClassLoader.class, "loadClass", new MethodHook() {...});
}
once you've hooked loadClass of ClassLoader you should be able to do what you like.
remember that there is more than one ClassLoader and also im not sure what will happen if you throw an exception.
i hope it helps

How to invoke getApplicationContext() from jni? [duplicate]

I would like to get the context of application which has reference/hosted my library at run-time inside one class of my library project. Is it possible? If yes, how?
Thanks
Update
I don't want my user to pass context in parameter to my library project because it is possible that my library project will be called through JNI and I have no idea how I can get context in JNI and pass it to Java layer.
There is one more way, add application class in your library project:
/**
* Base class for those who need to maintain global application state.
*/
public class LibApp extends Application {
/** Instance of the current application. */
private static LibApp instance;
/**
* Constructor.
*/
public LibApp() {
instance = this;
}
/**
* Gets the application context.
*
* #return the application context
*/
public static Context getContext() {
return instance;
}
}
Then in your regular project make the real application class extend LibApp:
/**
* Base class for those who need to maintain global application state.
*/
public class App extends LibApp {
#Override
public void onCreate() {
super.onCreate();
}
}
Make sure that you have "Name" defined in AndroidManifest:
<application android:name="App" ...>
and that your App class is in the base package.
You can then use LibApp.getContext() your library project to get the application context of the application that is using the library.
This may not be good solution but it works for me.
I am sharing it because it might be useful to somebody else.
Is it possible?
Yes.
If yes, how?
Pass it in as a parameter.
I don't want my user to pass context in parameter to my library project because it is possible that my library project will be called through JNI and I have no idea how I can get context in JNI and pass it to Java layer.
Then figure out "how [you] can get context in JNI and pass it to Java layer". I would imagine that you would pass it like any other object. As #Blundell noted, you do not really have any other option.
There's another way to get context in jni, neither passing a parameter nor saving context by yourself, but by using android api.
I found that there's a class named:
android.app.AppGlobals
in the source code. And the static function
getInitialApplication
can return an Application object. But it must be called in main thread, and the class is hidden.
Anyway you can use it by reflecting in java. And you can just use FindClass() and FindStaticObjectMethod() to find out the method, and use it.
Hope that helps.
According to this post you can let the library auto-initialize itself with the application context by the aid of a ContentProvider.
Be careful anyway, as described in the post comments, there may be drawbacks concerning loading time and instant run, as well as crashes on multi-process apps.
HTH
I would pass it as a parameter or pass it a singleton in that library.
Having the main app application extend the library's application class is a bad idea coz in java you can only extend once from a class. If your application requires to pass to another library you will be in trouble.

Instantiating multiple copies of a JNI library from Java

I have a JNI library that I've written to capture sensor (mostly accelerometer and gyro) data and do some feature detection algorithms on said data. The features detected are configurable via a few configuration files. When the features are detected, the JNI uses a callback to notify the java side of the application. All this works great.
Now I want to be able to have multiple instances of the same JNI library running simultaneously (so I can recognize features from multiple configuration files at once). To do this, I wrote a 'wrapper' class that implements the callbacks for the JNI library and takes care of all the initialization of the library as well. I was planning on simply instantiating this class and using each instance separately. What I've found is that while each wrapper instance is distinct, the library is reused across instances almost like it was statically declared. When I try to initialize the library from the second instance of the Wrapper class, I find it has already been initialized.
Here is a wrapper class similar to the code I've written:
public class JNIWrapper {
public native int initializeJNI(String configPath);
public native void endProcessing();
public native int getInstanceIdFromJNI();
public JNIWrapper(){
try {
System.loadLibrary("libjnicode.so");
}
catch (Exception e) {
Log.e("JNI", "WARNING: Could not load libjnicode.so: " + e.getMessage());
}
}
public int initialize(String configPath){
return initializeJNI(configPath);
}
public void stop(){
endProcessing();
}
public void callbackFromJNI(int output, int instanceId){
//notify the subscribed application(s) of the feature detection
//via message passing.
}
}
Does anyone know how I can instantiate multiple copies of a JNI library?
Thanks!
You can't do that. The dynamic linker will only load a given .so file into a process once.
Ideally you would modify the library to give it a light object-oriented style, allowing you to create instances and initialize those (rather than process-level static state) from your configuration files or calls. This isn't necessarily as complicated as it seems - basically put all your state in a struct and pass the pointer to it through all your calls. You'll have one marathon editor session resulting in a tired "paste" finger, and then some mistake cleanup. Fortunately once you remove the static variables you'll get compile errors on all remaining attempts to use them.
A very hacky alternative might be to declare some remote-process services in your AndroidManifest.xml and load the library into each of those. Or, really breaking the android model (and at theoretical risk of random killing), load the library into multiple created-on-demand native executables.

Categories

Resources