0

In my app I am using programmatically made relativeLayout which is attached to WindowManager.I am trying to blur the relativeLayout so that everything behind that relativeLayout will look blur.I have tried this below code:

/** * Created by Adarsh on 12-08-2016. */

public class Exa extends Service {

    RelativeLayout relativeLayout;
    WindowManager windowManager;
    RenderScript mRS;
    ScriptIntrinsicBlur script;
    Allocation allocOriginalScreenshot,allocBlurred;
    TextureView textureViewBlurred;
    private static final String TAG="MainActivity";
    @Override
    public void onCreate(){

        example();
        relativeLayout=new RelativeLayout(this);
        RelativeLayout.LayoutParams layoutParams=new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        relativeLayout.setLayoutParams(layoutParams);

        windowManager=(WindowManager)getSystemService(WINDOW_SERVICE);
        WindowManager.LayoutParams layoutParamsw= new WindowManager.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.TYPE_PHONE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,PixelFormat.TRANSPARENT);
        windowManager.addView(relativeLayout,layoutParamsw);
        blurView(relativeLayout);    //adding layout for blurring effect
    }



    ////all these code helps to give blurring effect
    private void example() {
        mRS=RenderScript.create(this);
        script=ScriptIntrinsicBlur.create(mRS, Element.RGBA_8888(mRS));
        script.setRadius(5);


    }


    Bitmap getViewScreenshot(View v){
        v.setDrawingCacheEnabled(true);
        Bitmap b=Bitmap.createBitmap(v.getDrawingCache());
        v.setDrawingCacheEnabled(false);

        return b;
    }

    void replaceView(View originalView,View newView){
        originalView.setTag(newView);
        newView.setLayoutParams(new FrameLayout.LayoutParams(originalView.getLayoutParams()));
        ViewGroup parent=(ViewGroup)originalView.getParent();
        int index=parent.indexOfChild(originalView);
        parent.removeView(originalView);
        parent.addView(newView,index);
    }

    void restoreView(View v){
        Log.i("hii","unblurring view");
        View otherView=(View)v.getTag();

        if (otherView!=null&&otherView.getParent()!=null){
            replaceView(otherView,v);
        }
        else if (v!=null&&v.getParent()!=null){
            replaceView(v,otherView);
        }
    }

    void blurView(View v){
        Bitmap viewScreenshot=getViewScreenshot(v);

        if(allocOriginalScreenshot!=null&&(allocOriginalScreenshot.getType().getX()!=viewScreenshot.getWidth()||allocOriginalScreenshot.getType().getY()!=viewScreenshot.getHeight())){
            allocOriginalScreenshot.destroy();
            allocBlurred.destroy();

            textureViewBlurred=null;
            allocOriginalScreenshot=null;
            allocBlurred=null;
        }
        if(allocOriginalScreenshot==null){
            allocOriginalScreenshot=Allocation.createFromBitmap(mRS,viewScreenshot);
            allocBlurred=Allocation.createTyped(mRS,allocOriginalScreenshot.getType(),Allocation.USAGE_SCRIPT|Allocation.USAGE_IO_OUTPUT);
            textureViewBlurred=new TextureView(this);
            textureViewBlurred.setOpaque(false);
            textureViewBlurred.setSurfaceTextureListener(surfaceTextureListener);
        }
        else {
            allocOriginalScreenshot.copyFrom(viewScreenshot);
        }
        replaceView(v,textureViewBlurred);
    }

    void unblur(View v){
        restoreView(v);
    }

    void executeBlur(){
        Log.d(TAG,"Executing blur");
        script.setInput(allocOriginalScreenshot);
        script.forEach(allocBlurred);

        allocBlurred.ioSend();
    }


    TextureView.SurfaceTextureListener surfaceTextureListener=new TextureView.SurfaceTextureListener() {
        @Override
        public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
            allocBlurred.setSurface(new Surface(surface));
            executeBlur();
        }

        @Override
        public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {

        }

        @Override
        public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
            return false;
        }

        @Override
        public void onSurfaceTextureUpdated(SurfaceTexture surface) {

        }
    };

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

When I try to run the program it gives me error like this

java.lang.NullPointerException: Attempt to invoke virtual method 'int android.graphics.Bitmap.getWidth()' on a null object reference

When I try the same program in my MainActivity it perfectly works and blur all the contents inside the relativeLayout. Please help me.

mehrdad khosravi
  • 2,228
  • 9
  • 29
  • 34
Adarsh
  • 165
  • 2
  • 16

1 Answers1

0

The exception you get is a NullPointerException.

To take a screenshot using your getViewScreenshot() method, you need to have a view. Meaning it will only work from an activity and not from a service.

Since a service can't have a view, you can't get a screenshot and blurring doesn't work. Also there's no point in attaching a view to a service. Docs

Anubhav
  • 83
  • 1
  • 1
  • 6
  • OK then do you have any idea how can I blur that layout – Adarsh Aug 14 '16 at 07:15
  • A service cannot have a layout. If you're trying to record external apps you should look into [MediaProjection](https://developer.android.com/reference/android/media/projection/package-summary.html) which was added in API 21. You should also check [this](http://stackoverflow.com/a/32623147/5980145) if you want to extend support to earlier API's. – Anubhav Aug 14 '16 at 07:22