1

First some background (I always like when people asking questions give that): I am writing a library project. It is a simple OpenGL 'graphics distortions' library. Users are supposed to be able to create certain objects called 'Regions' with a simple call to

myRegion = new DistortedRegion(w,h);

then define various distortions on them and draw them:

myRegion.addTwistDistortion(...)
myRegion.draw(x,y);

That's all there is to it. The library uses OpenGL to draw the Region (a rectangular bitmap really) distorted in various user-defined ways.

Now, the problem: the library needs to access its vertex and fragment shaders, which are .glsl files stored with its resources, in the 'raw' folder. In order to do that, we have to access the Resources object, and in order to do that we AFAIK have to have the Context object. So currently as it stands the library has to first be initialized with a call

Distorted.init(Context)

This is a giant problem for me, because this IMHO makes the whole API clumsy. If not for this damn Context, there would be no need to initialize anything, and the user would simply be able to create new objects straight away whenever he wants, which is elegant and simple to explain in the docs. A separate init() call , which is only really needed to pass the Context object to the library, which is only needed to retrieve the Resources object, which is only needed to open up two files containing shader code, makes all of that very clumsy.

I was thinking to simply move the shader code into statically initialized Strings inside my library instead, but this is cumbersome for development (the shaders are several hundred lines long of quite complicated code, and if I keep them in a separate .glsl files, I can have syntax highliting among other things)

Any advice?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Utumno
  • 21
  • 3

1 Answers1

0

So yes, I hopefully figured it out. Here's a function that returns the Context of the current Application by directly calling the underlying Android code by reflection. It can be called from anywhere, not only from classes which extend Application or Activity:

import android.content.Context;
import android.app.Application;
import java.lang.reflect.Method;

private Context getCurrentContext()
  {
  Class<?>     cl =null;    
  Method   method =null;
  Application app =null;

  try
    {
    cl = Class.forName("android.app.AppGlobals");       
    }
  catch(ClassNotFoundException ex)
    {
    Log.e(TAG_DISTORTED_REGION, "Failure to retrieve the AppGlobals class: "+ex.toString() );  
    return null;
    }

  try
    {
    method = cl.getMethod("getInitialApplication", (Class [])(null) );
    }
  catch(NoSuchMethodException nm)
    {
    Log.e(TAG_DISTORTED_REGION, "No such method: "+nm.toString() );
    return null;
    }

  try
    {
    app = (Application)method.invoke(null, (Object [])(null) );
    }
  catch(Exception e)
    {
    Log.e(TAG_DISTORTED_REGION, "failure calling method getInitialApplication: "+e.toString() );
    return null;
    }

  return app.getApplicationContext();  
  }
Utumno
  • 21
  • 3
  • Dammit. That only works in Android 4.4 and 4.3. 4.2 and 4.1 give me a NullPointerException trying to getApplicationContext(). – Utumno Mar 05 '14 at 23:27