2

I'm trying to get a bitmap drawn from a view, as I want to blur that bitmap and use it as a background for a following activity. Logcat gives me:

NullPointerException at android.graphics.Bitmap.createBitmap(Bitmap.java:484)

My code:

 @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // Get the view from activity_main.xml
    setContentView(R.layout.activity_splash_page);

    ProgressWheel wheel = (ProgressWheel) findViewById(R.id.progress_wheel);
    wheel.setClickable(false);

    TextView touch = (TextView) findViewById(R.id.touch_splash);
    touch.setClickable(false);

    TextView level = (TextView) findViewById(R.id.level_splash);
    level.setClickable(false);


    wheel.setProgress(0.7f);
    wheel.setClickable(true);
    touch.setClickable(true);
    level.setClickable(true);

    RelativeLayout view = (RelativeLayout)findViewById(R.id.viewtocapture);
    ImageView bmImage = (ImageView)findViewById(R.id.imageView);

    view.setDrawingCacheEnabled(true);
    // this is the important code :)
    // Without it the view will have a dimension of 0,0 and the bitmap will be null

    view.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
            View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));

    view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());

    view.buildDrawingCache(true);
    view.buildDrawingCache();
    Bitmap b = Bitmap.createBitmap(view.getDrawingCache());      //Line 53
    view.setDrawingCacheEnabled(false); // clear drawing cache

    bmImage.setImageBitmap(b);


    wheel.setProgress(0.0f);

}

Here's the Stacktrace/Logcat:

Caused by: java.lang.NullPointerException
        at android.graphics.Bitmap.createBitmap(Bitmap.java:484)
        at com.redstonedevelopers.status_v1.SplashPage.onCreate(SplashPage.java:53)
        at android.app.Activity.performCreate(Activity.java:5047)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1094)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2056)       
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2117)
        at android.app.ActivityThread.access$700(ActivityThread.java:134)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1218)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:137)
        at android.app.ActivityThread.main(ActivityThread.java:4867)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:511)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1007)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:774)
        at dalvik.system.NativeStart.main(Native Method)

I've tried answers from: Here: take a screenshot from the activity Here: NullPointerException in createBitmap() from View and Here: android createBitmap NullPointerException

All to no avail. What should I change and/or do to get this working?

-R

Community
  • 1
  • 1
redstonedev
  • 119
  • 1
  • 10
  • 2
    `at com.redstonedevelopers.status_v1.SplashPage.onCreate(SplashPage.java:53)` show your onCreate and indicate line 53 please. – Simon May 13 '15 at 16:23
  • why are you calling view.buildDrawingCache() two times? – Krupal Shah May 13 '15 at 16:43
  • @Simon I've edited the post to display what you've asked. – redstonedev May 13 '15 at 16:51
  • @Krupal I believe the first one makes the function usable whilst the second actually builds the cache. Might be wrong though, either way I get the exception. – redstonedev May 13 '15 at 16:53
  • No...the boolean parameter is for setting autoscale enabled/disabled...delete the first one. http://developer.android.com/reference/android/view/View.html#buildDrawingCache(boolean) – Krupal Shah May 13 '15 at 16:54
  • @Krupal Thanks for the clarification. Although it doesn't change the exception... – redstonedev May 13 '15 at 16:56
  • 1
    @redstonedev ok then put view.setDrawingCacheEnabled(true); exactly above view.buildDrawingCache(); – Krupal Shah May 13 '15 at 16:58
  • @Krupal Still no luck... – redstonedev May 13 '15 at 17:01
  • 1
    @redstonedev ok...one last solution I have: use view.getRootView().getDrawingCache() intsead of view.getDrawingCache() – Krupal Shah May 13 '15 at 17:02
  • 1
    You won't detect anything until its actually drawn for the first time. The view won't even be drawn on the screen in the On Create so its going to be null. You need to use TreeViewObserver and do all this then. – Xjasz May 13 '15 at 17:06
  • @Jasz THIS makes sense... How would I go about this though? Sorry, pretty new to Android. – redstonedev May 13 '15 at 17:08
  • 1
    @redstonedev Try that answer out you can put it in your own method if you like. I use it when I need to know the size of a dynamic view the second that its drawn you can use it for other things though like what you're trying to do. – Xjasz May 13 '15 at 17:15

4 Answers4

1

Try this.
This will kick off when your view is actually drawn.
Then you should be able to save the bitmap for it.

-----Make sure bmImage and view should be class level so we can use them when the ViewTreeObserver fires.

 bmImage = (ImageView)findViewById(R.id.imageView);
 view = (RelativeLayout)findViewById(R.id.viewtocapture);
 view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @SuppressWarnings("deprecation")
        @Override
        public void onGlobalLayout() {
            view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
            System.out.println(view == null ? "is null" : "not null");
            Bitmap b = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);                
            Canvas c = new Canvas(b);
            view.layout(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
            view.draw(c);
            bmImage.setImageBitmap(b);
        }
    });
Xjasz
  • 1,238
  • 1
  • 9
  • 21
  • I get the following: Variable 'view' is accessed from within inner class, needs to be declared final When I do in fact declare it as final, I get the same NullPointerException as described in my initial post. – redstonedev May 13 '15 at 17:38
  • 1
    @redstonedex make view a global variable. Go to your outer class and do RelativeLayout view; Then set it view = (RelativeLayout)findViewById(R.id.viewtocapture); – Xjasz May 13 '15 at 17:41
  • I get the same error: java.lang.NullPointerException at android.graphics.Bitmap.createBitmap(Bitmap.java:484) – redstonedev May 13 '15 at 17:46
  • 1
    Editing the bitmap to the way I get a bitmap from a view – Xjasz May 13 '15 at 17:48
  • 1
    @restonedev keep in mind that bmImage also needs to be a global object. Because ViewTreeObserver doesn't fire off immediately and by the time it does trigger bmImage could be null. – Xjasz May 13 '15 at 17:53
  • I assumed that bmImage should be global as well. All the code works now, but I still get the same NullPointerExeption: java.lang.NullPointerException at android.graphics.Bitmap.createBitmap(Bitmap.java:484) at com.redstonedevelopers.status_v1.SplashPage$1.onGlobalLayout(SplashPage.java:83) Line 83 is where I call createBitmap(); – redstonedev May 13 '15 at 18:04
  • 1
    You don't mean global, you mean class level. Global has a very well defined meaning - a global has scope, visibility and lifetime equal to the application. – Simon May 13 '15 at 18:05
  • 1
    @redstonedev hey dev implement my edit and see it view is null it shouldn't be – Xjasz May 13 '15 at 18:09
  • @Simon Ya class level sorry. – Xjasz May 13 '15 at 18:09
  • @Jasz Sorry, internet connection is messing around. I changed the code to what you suggested. The app doesn't crash, but the imageview remains blank. To where will it print "is null"? – redstonedev May 13 '15 at 18:33
  • 1
    logcat should print that – Xjasz May 13 '15 at 18:41
  • "05-13 20:45:16.705 8139-8139/? W/System.err﹕ at com.redstonedevelopers.status_v1.SplashPage$1.onGlobalLayout(SplashPage.java:81) " That's all that's printed. Line 81 is where createBitmap is called. – redstonedev May 13 '15 at 18:46
  • 1
    It should log some whether or not its null before that "is null" || "not null" – Xjasz May 13 '15 at 18:48
  • @Jasz Finally got it working. I called createBitmap like this: Bitmap b = Bitmap.createBitmap( 480, 800, Bitmap.Config.ARGB_8888); Which means, view.getLayoutParams().height/width isn't working as it should. Any ideas? – redstonedev May 13 '15 at 20:12
  • 1
    @redstonedev try the change I made view.getWidth(); view.getHeight(); should work. – Xjasz May 13 '15 at 20:20
  • Works perfectly now! Thank you so much for all your trouble. I appreciate it so much. – redstonedev May 13 '15 at 20:23
  • how to reduce the toolbar layout height from the top, I don't need the toolbar design in that image – ranjith Sep 26 '17 at 14:52
1

The view tree is not measured, laid out and rendered until after onCreate().

You can use a tree view layout observer, like this.

public void onCreate(Bundle savedInstanceState)
{
     super.onCreate(savedInstanceState);

     // inflate your main layout here (use RelativeLayout or whatever your root ViewGroup type is
     LinearLayout mainLayout = (LinearLayout ) this.getLayoutInflater().inflate(R.layout.activity_splash_page, null); 

     // set a global layout listener which will be called when the layout pass is completed and the view is drawn
     mainLayout.getViewTreeObserver().addOnGlobalLayoutListener(
     new ViewTreeObserver.OnGlobalLayoutListener() {
          public void onGlobalLayout() {
               //Remove the listener before proceeding
               if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                    mainLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
               } else {
                    mainLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
               }

               // do your thing here
          }
     }
 );

 setContentView(mainLayout);
Simon
  • 14,407
  • 8
  • 46
  • 61
1

I use code like this to draw a view onto a canvas object. Not sure if this will work in your case.

picturePreLoad = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
   Canvas canvas = new Canvas(picturePreLoad);
   MyView.draw(canvas);
mjstam
  • 1,049
  • 1
  • 6
  • 5
0

In my case, the problem was that the bitmap files were copied by default in Drawable V24, instead of Drawable. To be able to see both folders at the same time, in the top left corner, change the setting from Android to Project.

Then go to app.src.main.res and there you can see both Drawable V24 and Drawable. You just have to remove the bitmaps from Drawable V24 and add them to Drawable.

royB
  • 12,779
  • 15
  • 58
  • 80
Monica
  • 1