当用户移出android中的应用程序时,服务中的服务回调变为空

问题描述

我创建了一个启动浮动气泡的服务,在浮动气泡上,我添加了几个按钮。为了让这些按钮起作用,我在服务活动中创建了一个界面,并使用服务回调将其与我的主要活动绑定。

所以浮动气泡一切正常,但是一旦用户移出应用程序,浮动气泡仍然有效,但它的按钮不起作用,当用户按下浮动气泡应用程序上的任何按钮时,它会在后台崩溃,我尝试调试,发现用户一住app,界面变量就变成null了。

这是我的服务

public class FloatingViewService extends Service {
    private WindowManager mWindowManager;
    private View mFloatingView;
    // Binder given to clients
    private final IBinder binder = new LocalBinder();
    // Registered callbacks
    private ServiceCallbacks serviceCallbacks;

    // Class used for the client Binder.
    public class LocalBinder extends Binder {
        FloatingViewService getService() {
            // Return this instance of MyService so clients can call public methods
            return FloatingViewService.this;
        }
    }

    public void setCallbacks(ServiceCallbacks callbacks) {
        serviceCallbacks = callbacks;
    }

    public FloatingViewService() {
    }

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

    @Override
    public void onCreate() {
        super.onCreate();
        //Inflate the floating view layout we created
        mFloatingView = LayoutInflater.from(this).inflate(R.layout.layout_floating_widget,null);

        //Add the view to the window.
        final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,WindowManager.LayoutParams.WRAP_CONTENT,//              WindowManager.LayoutParams.TYPE_PHONE,WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,PixelFormat.TRANSLUCENT);

        //Specify the view position
        params.gravity = Gravity.TOP | Gravity.LEFT;        //Initially view will be added to top-left corner
        params.x = 0;
        params.y = 100;

        //Add the view to the window
        mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
        mWindowManager.addView(mFloatingView,params);


        //….
        //….

        //The root element of the collapsed view layout
        final View collapsedView = mFloatingView.findViewById(R.id.collapse_view);
        //The root element of the expanded view layout
        final View expandedView = mFloatingView.findViewById(R.id.expanded_container);


        //Set the close button
        ImageView closeButtonCollapsed = (ImageView) mFloatingView.findViewById(R.id.close_btn);
        closeButtonCollapsed.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //close the service and remove the from from the window
                stopSelf();
            }
        });


        //Set the view while floating view is expanded.
        //Set the start recording button.
        ImageView playButton = (ImageView) mFloatingView.findViewById(R.id.startRecording);
        playButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //Toast.makeText(FloatingViewService.this,"Recording started",Toast.LENGTH_LONG).show();
                //serviceCallbacks.onClick(1);
            }
        });


        //stop recording.
        ImageView nextButton = (ImageView) mFloatingView.findViewById(R.id.stopRecording);
        nextButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //Toast.makeText(FloatingViewService.this,"recording stoped.",Toast.LENGTH_LONG).show();
                serviceCallbacks.onClick(2);
            }
        });


        //Set the close button
        ImageView closeButton = (ImageView) mFloatingView.findViewById(R.id.close_button);
        closeButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                collapsedView.setVisibility(View.VISIBLE);
                expandedView.setVisibility(View.GONE);
            }
        });


        //Drag and move floating view using user's touch action.
        mFloatingView.findViewById(R.id.root_container).setOnTouchListener(new View.OnTouchListener() {
            private int initialX;
            private int initialY;
            private float initialTouchX;
            private float initialTouchY;


            @Override
            public boolean onTouch(View v,MotionEvent event) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:


                        //remember the initial position.
                        initialX = params.x;
                        initialY = params.y;


                        //get the touch location
                        initialTouchX = event.getRawX();
                        initialTouchY = event.getRawY();
                        return true;

                    case MotionEvent.ACTION_UP:
                        int Xdiff = (int) (event.getRawX() - initialTouchX);
                        int Ydiff = (int) (event.getRawY() - initialTouchY);


                        //The check for Xdiff <10 && YDiff< 10 because sometime elements moves a little while clicking.
                        //So that is click event.
                        if (Xdiff < 10 && Ydiff < 10) {
                            if (isViewCollapsed()) {
                                //When user clicks on the image view of the collapsed layout,//visibility of the collapsed layout will be changed to "View.GONE"
                                //and expanded view will become visible.
                                collapsedView.setVisibility(View.GONE);
                                expandedView.setVisibility(View.VISIBLE);
                            }
                        }
                        return true;

                    case MotionEvent.ACTION_MOVE:
                        //Calculate the X and Y coordinates of the view.
                        params.x = initialX + (int) (event.getRawX() - initialTouchX);
                        params.y = initialY + (int) (event.getRawY() - initialTouchY);


                        //Update the layout with new X & Y coordinate
                        mWindowManager.updateViewLayout(mFloatingView,params);
                        return true;
                }
                return false;
            }
        });


    }


    private boolean isViewCollapsed() {
        return mFloatingView == null || mFloatingView.findViewById(R.id.collapse_view).getVisibility() == View.VISIBLE;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (mFloatingView != null) mWindowManager.removeView(mFloatingView);
    }

    public interface ServiceCallbacks {
        void onClick(int type);
    }

}

这是我的主要活动

public class MainActivity extends AppCompatActivity implements View.OnClickListener,HBRecorderListener,FloatingViewService.ServiceCallbacks {

    private HBRecorder recorder;
    private static final int PERMISSION_REQ_ID_RECORD_AUDIO = 22;
    private static final int PERMISSION_REQ_ID_WRITE_EXTERNAL_STORAGE = PERMISSION_REQ_ID_RECORD_AUDIO + 1;
    private static final int CODE_DRAW_OVER_OTHER_APP_PERMISSION = 2084;
    private boolean hasPermissions = false;
    private FloatingViewService myService;
    private boolean bound = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        checkFloatingPermission();
        recorder = new HBRecorder(this,this);
        findViewById(R.id.startR).setOnClickListener(this);
        findViewById(R.id.stopR).setOnClickListener(this);
    }

    private void checkFloatingPermission() {
        //Check if the application has draw over other apps permission or not?
        //This permission is by default available for API<23. But for API > 23
        //you have to ask for the permission in runtime.
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(this)) {


            //If the draw over permission is not available open the settings screen
            //to grant the permission.
            Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,Uri.parse("package:" + getPackageName()));
            startActivityForResult(intent,CODE_DRAW_OVER_OTHER_APP_PERMISSION);
        } else {
            Toast.makeText(this,"floting permission already given",Toast.LENGTH_SHORT).show();
            initializeView();
        }
    }

    @Override
    protected void onStart() {
        super.onStart();
        // bind to Service
        Intent intent = new Intent(this,FloatingViewService.class);
        bindService(intent,serviceConnection,Context.BIND_AUTO_CREATE);
    }

    /**
     * Callbacks for service binding,passed to bindService()
     */
    private ServiceConnection serviceConnection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName className,IBinder service) {
            // cast the IBinder and get MyService instance
            FloatingViewService.LocalBinder binder = (FloatingViewService.LocalBinder) service;
            myService = binder.getService();
            bound = true;
            myService.setCallbacks(MainActivity.this); // register
        }

        @Override
        public void onServiceDisconnected(ComponentName arg0) {
            bound = false;
        }
    };

    @Override
    protected void onStop() {
        super.onStop();
        // Unbind from service
        if (bound) {
            myService.setCallbacks(null); // unregister
            unbindService(serviceConnection);
            bound = false;
        }
    }

    private void initializeView() {
        startService(new Intent(MainActivity.this,FloatingViewService.class));

    }

    @Override
    public void onClick(View view) {
        if (checkSelfPermission(Manifest.permission.RECORD_AUDIO,PERMISSION_REQ_ID_RECORD_AUDIO) && checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE,PERMISSION_REQ_ID_WRITE_EXTERNAL_STORAGE)) {
            hasPermissions = true;
        }
        if (view.getId() == R.id.startR && hasPermissions) {
            startRecordingScreen();
        } else if (view.getId() == R.id.stopR && hasPermissions) {
            recorder.stopScreenRecording();
        }
    }

    private boolean checkSelfPermission(String permission,int requestCode) {
        if (ContextCompat.checkSelfPermission(this,permission) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this,new String[]{permission},requestCode);
            return false;
        }
        return true;
    }

    @Override
    public void onRequestPermissionsResult(int requestCode,@NonNull String[] permissions,@NonNull int[] grantResults) {
        switch (requestCode) {
            case PERMISSION_REQ_ID_RECORD_AUDIO:
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE,PERMISSION_REQ_ID_WRITE_EXTERNAL_STORAGE);
                } else {
                    hasPermissions = false;
                }
                break;
            case PERMISSION_REQ_ID_WRITE_EXTERNAL_STORAGE:
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    hasPermissions = true;
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                        startRecordingScreen();
                    }
                } else {
                    hasPermissions = false;
                }
                break;
            default:
                break;
        }
    }

    public void startRecordingScreen() {
        if (recorder.isBusyRecording()) {
            recorder.stopScreenRecording();
        }
        MediaProjectionManager mediaProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
        Intent permissionIntent = mediaProjectionManager != null ? mediaProjectionManager.createScreenCaptureIntent() : null;
        startActivityForResult(permissionIntent,101);
    }

    @Override
    protected void onActivityResult(int requestCode,int resultCode,Intent data) {
        super.onActivityResult(requestCode,resultCode,data);
        if (requestCode == CODE_DRAW_OVER_OTHER_APP_PERMISSION) {
            //Check if the permission is granted or not.
            if (resultCode == RESULT_OK) {
                initializeView();
            } else { //Permission is not available
                Toast.makeText(this,"Draw over other app permission not available. Closing the application",Toast.LENGTH_SHORT).show();

                finish();
            }
        }

        if (requestCode == 101) {
            if (resultCode == RESULT_OK) {
                recorder.startScreenRecording(data,this);
            }
        }
    }

    @Override
    public void HBRecorderOnStart() {
        Toast.makeText(this,"recording start",Toast.LENGTH_SHORT).show();
    }

    @Override
    public void HBRecorderOnComplete() {
        Toast.makeText(this,"file saved at:   " + recorder.getFilePath(),Toast.LENGTH_LONG).show();
    }

    @Override
    public void HBRecorderOnError(int errorCode,String reason) {
        Toast.makeText(this,"recording error",Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onClick(int type) {
        Toast.makeText(myService,"workinggggggg",Toast.LENGTH_SHORT).show();
        if (type == 1) {
            if (checkSelfPermission(Manifest.permission.RECORD_AUDIO,PERMISSION_REQ_ID_WRITE_EXTERNAL_STORAGE)) {
                hasPermissions = true;
            }
            if (hasPermissions) {
                startRecordingScreen();
            }
        } else
            recorder.stopScreenRecording();
    }
}

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)