AsyncTask all i get is a blank/black texture screen
Assuming that you have been modifying your code and the code you posted isn't the version that actually saves you time, and assuming that the AsyncTask works, then I think the issue is making sure the results of the BitmapWorkerTask are pushed into the UI thread when they are done. You would do this by using the AsyncTask's onPostExecute() method, which is run on the UI thread and has access to the results of the doInBackground() method. So here is an example, where I modify the loadTexture() method to take the result Bitmap in as a parameter, and use the onPostExecute() method to make sure that the loadTexture() method is called only after the Bitmap is loaded...
view plaincopy to clipboardprint?
Note: Text content in the code blocks is automatically word-wrapped
/* load the texture bitmap properly */
private void loadTextures(Bitmap bitmap) {
// Generate textures
GLES20.glGenTextures(2, mTextures, 0);
mEffectContext = EffectContext.createWithCurrentGlContext();
mTexRenderer.init();
// Load input bitmap
try {
//load Bitmap from previous activity
mImageWidth = bitmap.getWidth();
mImageHeight = bitmap.getHeight();
mTexRenderer.updateTextureSize(mImageWidth, mImageHeight);
// Upload to texture
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextures[0]);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
// Set texture parameters
GLToolbox.initTexParams();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
class BitmapWorkerTask extends AsyncTask<Uri, Void, Bitmap> {
Uri uri;
@Override
protected Bitmap doInBackground(Uri... imageuri) {
uri = imageuri[0];
return decodeSampledBitmapFromResource(uri, dw, dh);
}
@Override /* When loading bitmap is done, make sure it is displayed. */
protected void onPostExecute(Bitmap bitmap) {
// have bitmap, so load it to GL context
loadTexttures(bitmaps[0]);
// next time onDraw is called, it should do the rendering
mInitialized = true;
// do the rendering now
processEffectsAndRender();
}
}
/* load the texture bitmap properly */
private void loadTextures(Bitmap bitmap) {
// Generate textures
GLES20.glGenTextures(2, mTextures, 0);
mEffectContext = EffectContext.createWithCurrentGlContext();
mTexRenderer.init();
// Load input bitmap
try {
//load Bitmap from previous activity
mImageWidth = bitmap.getWidth();
mImageHeight = bitmap.getHeight();
mTexRenderer.updateTextureSize(mImageWidth, mImageHeight);
// Upload to texture
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextures[0]);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
// Set texture parameters
GLToolbox.initTexParams();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
class BitmapWorkerTask extends AsyncTask<Uri, Void, Bitmap> {
Uri uri;
@Override
protected Bitmap doInBackground(Uri... imageuri) {
uri = imageuri[0];
return decodeSampledBitmapFromResource(uri, dw, dh);
}
@Override /* When loading bitmap is done, make sure it is displayed. */
protected void onPostExecute(Bitmap bitmap) {
// have bitmap, so load it to GL context
loadTexttures(bitmaps[0]);
// next time onDraw is called, it should do the rendering
mInitialized = true;
// do the rendering now
processEffectsAndRender();
}
}
So the onPostExecute() method triggers the loadTexture() method, signals that the loading is done, and then makes sure the effects are rendered. I modified a couple of the other methods to make sure that things happen only when the bitmap is available. First, the onDrawFrame() method is modified to only work after the bitmap is loaded completely (the mInitialized variable is true). I also broke the rest of what was in the onDrawFrame() method out into its own method so it could be called either from onDrawFrame() of from the onPostExecute() methods:
view plaincopy to clipboardprint?
Note: Text content in the code blocks is automatically word-wrapped
/* draw frame if bitmap and effects are ready... */
public void onDrawFrame(GL10 gl) {
if (mInitialized) {
processEffectsAndRender();
}
}
/* initialize effect and draw */
private void processEffectsAndRender() {
if (mCurrentEffect != R.id.none) {
// if an effect is chosen initialize it and apply it to the texture
initEffect();
//applyEffect();
}
renderResult();
}
/* draw frame if bitmap and effects are ready... */
public void onDrawFrame(GL10 gl) {
if (mInitialized) {
processEffectsAndRender();
}
}
/* initialize effect and draw */
private void processEffectsAndRender() {
if (mCurrentEffect != R.id.none) {
// if an effect is chosen initialize it and apply it to the texture
initEffect();
//applyEffect();
}
renderResult();
}
Finally, I wanted to kick the BitmapWorkerTask off as soon as possible, so I figured I would run it from the onCreate() method:
view plaincopy to clipboardprint?
Note: Text content in the code blocks is automatically word-wrapped
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tinypost_filters);
/*
* Initialize renderer and set it to only render when explicitly
* requested with the RENDERMODE_WHEN_DIRTY option.
*/
mEffectView = (GLSurfaceView) findViewById(R.id.effectsview);
mEffectView.setEGLContextClientVersion(2);
mEffectView.setRenderer(this);
mEffectView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
mCurrentEffect = R.id.none;
/* start loading Bitmap as soon as possible. */
mInitialized = false;
myuri = Uri.parse(getIntent().getStringExtra("uri"));
new BitmapWorkerTask().execute(myuri);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tinypost_filters);
/*
* Initialize renderer and set it to only render when explicitly
* requested with the RENDERMODE_WHEN_DIRTY option.
*/
mEffectView = (GLSurfaceView) findViewById(R.id.effectsview);
mEffectView.setEGLContextClientVersion(2);
mEffectView.setRenderer(this);
mEffectView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
mCurrentEffect = R.id.none;
/* start loading Bitmap as soon as possible. */
mInitialized = false;
myuri = Uri.parse(getIntent().getStringExtra("uri"));
new BitmapWorkerTask().execute(myuri);
}
So in this situation, the onCreate() method starts loading the BitmapWorkerTask. When the BitmapWorkerTask is done, it makes sure the bitmap is sized and processed, and rendered. Meamwhile, if the onDrawFrame() is called before the bitmap is complete, it won't do anything, afterwards, it will display the results. all this is relatively naive, of course. I haven't used OpenGL on the Android yet and I didn't compile or test the code. all I did was to organize it in a way that made sure the code that needed to execute only after the Bitmap was loaded did so, and to make sure that that code gets called as soon as the Bitmap is loaded.
This will NOT make the bitmap load faster. If it takes 7 seconds to load the bitmap that is how long it takes, and it still shouldn't show up until the end of that load time. What this will do is allow your UI remain responsive and allow other things to happen WHILE the bitmap loads.