Android前台服务不会停止

时间:2016-11-26 08:27:13

标签: android service

我的前台服务不会停止。它与MainActivity绑定,单击通知会调用exit() - Method。然后通知消失,覆盖视图消失但服务仍在运行。为什么呢?

OverlayService.java

public class OverlayService extends Service implements View.OnKeyListener, View.OnClickListener {

    private WindowManager.LayoutParams iconViewLayoutParams, textFieldLayoutParams;
    private RelativeLayout iconViewOverlay, textViewOverlay;
    private ImageView iconImageView;
    private TextView textView;
    private WindowManager windowManager;
    private ScreenUtils screenUtils;
    private boolean isTextViewVisible;
    final String LOG = "MYLOG";
    private boolean isCtrlPressed;
    private final IBinder mBinder = new LocalBinder();
    final int SCROLL_OFFSET=10;


    @Override
    public void onCreate() {
        init();
        addTextViewOverlay();
        addOverlayScreen();
        addNotification();
    }


    public void init() {
        windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
        screenUtils = new ScreenUtils(windowManager);
        iconViewLayoutParams = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_PHONE,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                PixelFormat.TRANSLUCENT);
        iconViewLayoutParams.gravity = Gravity.TOP | Gravity.LEFT;

        textFieldLayoutParams = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_PHONE,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                PixelFormat.TRANSLUCENT);
        textFieldLayoutParams.gravity = Gravity.TOP | Gravity.LEFT;
    }

    public void addNotification(){
        Intent exitIntent = new Intent(this, MainActivity.class);
        exitIntent.putExtra("exit", true);
        PendingIntent exitPendingIntent =  PendingIntent.getActivity(this, 2, exitIntent, PendingIntent.FLAG_CANCEL_CURRENT);

        android.app.Notification.Builder mBuilder =
                new Notification.Builder(this)
                        .setSmallIcon(R.drawable.icon)
                        .setContentText(getString(R.string.app_name))
        .addAction(R.drawable.notificationexit, getResources().getString(R.string.exit), exitPendingIntent);
        startForeground(999, mBuilder.build());
    }

    public void addOverlayScreen() {
        iconViewOverlay = (RelativeLayout) LayoutInflater.from(getApplicationContext())
                .inflate(R.layout.icon_view, null);
        iconImageView = (ImageView) iconViewOverlay.findViewById(R.id.iconImageView);
        iconImageView.setOnClickListener(this);
        iconViewLayoutParams.x = 0;
        iconViewLayoutParams.y = 500;
        windowManager.addView(iconViewOverlay, iconViewLayoutParams);
    }

    public void addTextViewOverlay() {
        textViewOverlay = (RelativeLayout) LayoutInflater.from(getApplicationContext())
                .inflate(R.layout.text_view, null);
        textView = (TextView) textViewOverlay.findViewById(R.id.textView);
        windowManager.addView(textViewOverlay, textFieldLayoutParams);
        textViewOverlay.setVisibility(View.GONE);
    }


    public void positionTextViewOverlay() {
        if (screenUtils.getOrientation() == Configuration.ORIENTATION_LANDSCAPE) {
            textFieldLayoutParams.x = screenUtils.getScreenHeight() - textView.getLayoutParams().width / 2;
        } else if (screenUtils.getOrientation() == Configuration.ORIENTATION_PORTRAIT) {
            textFieldLayoutParams.x = screenUtils.getScreenWidth() / 2 - textView.getWidth() / 2;
        }
        textFieldLayoutParams.y = iconViewLayoutParams.y;
        windowManager.updateViewLayout(textViewOverlay, textFieldLayoutParams);
    }

    public void changeTextViewVisibility() {
        if (isTextViewVisible()) {
            hideTextView();
            setTextViewVisible(false);
        } else {
            showTextView();
            setTextViewVisible(true);
            positionTextViewOverlay();
        }
    }

    public void showTextView(){
        textViewOverlay.setVisibility(View.VISIBLE);
    }

    public void hideTextView(){
        textViewOverlay.setVisibility(View.GONE);

    }

    @Override
    public void onDestroy(){
        super.onDestroy();
    }

    private boolean isTextViewVisible() {
        return isTextViewVisible;
    }

    public void setTextViewVisible(boolean textViewVisible) {
        isTextViewVisible = textViewVisible;
    }

    public void showToast(String text) {
        Toast.makeText(getApplicationContext(), text, Toast.LENGTH_SHORT).show();
    }

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

    @Override
    public boolean onKey(View v, int keyCode, KeyEvent event) {
        if(isTextViewVisible()) {
            if (event.getKeyCode() == KeyEvent.ACTION_DOWN) {
                switch (event.getAction()) {
                    case KeyEvent.KEYCODE_CTRL_LEFT:
                        isCtrlPressed = true;
                        return true;
                    case KeyEvent.KEYCODE_CTRL_RIGHT:
                        isCtrlPressed = true;
                        return true;
                    case KeyEvent.KEYCODE_DPAD_DOWN:
                        if (isCtrlPressed) {
                            scrollIconViewDown();
                            positionTextViewOverlay();
                        }
                        return true;
                    case KeyEvent.KEYCODE_DPAD_UP:
                        if (isCtrlPressed) {
                            scrollIconViewUp();
                            positionTextViewOverlay();
                        }
                        return true;
                    case KeyEvent.KEYCODE_ESCAPE:
                        changeTextViewVisibility();
                        return true;
                    default:
                        return false;
                }
            }

            if (event.getKeyCode() == KeyEvent.ACTION_UP) {
                switch (event.getAction()) {
                    case KeyEvent.KEYCODE_CTRL_LEFT:
                        isCtrlPressed = false;
                        return true;
                    case KeyEvent.KEYCODE_CTRL_RIGHT:
                        isCtrlPressed = false;
                        return true;
                    default:
                        return false;
                }
            }
        }else{
            showTextView();
        }
        return false;
    }

    public void scrollIconViewDown(){
        iconViewLayoutParams.y -= SCROLL_OFFSET;
        windowManager.updateViewLayout(iconViewOverlay, iconViewLayoutParams);
    }

    public void scrollIconViewUp(){
        iconViewLayoutParams.y += SCROLL_OFFSET;
        windowManager.updateViewLayout(iconViewOverlay, iconViewLayoutParams);
    }

    public void removeViews(){
        try {
            windowManager.removeView(iconViewOverlay);
            windowManager.removeView(textViewOverlay);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.iconImageView:
                changeTextViewVisibility();
                break;
            default:
                break;
        }
    }

    public void exit(){
        removeViews();
        stopForeground(true);
        stopSelf();
    }

    public class LocalBinder extends Binder {
        OverlayService getService() {
            return OverlayService.this;
        }
    }
}

MainActivity.java

    public class MainActivity extends Activity {

    OverlayService mService;
    private boolean mBound;
    private Intent serviceIntent;

    private ServiceConnection mConnection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName className,
                                       IBinder service) {
            OverlayService.LocalBinder binder = (OverlayService.LocalBinder) service;
            mService = binder.getService();
            mBound = true;
            if(getIntent().getBooleanExtra("exit", false)){
                mService.exit();
                if(mConnection!=null){
                getApplicationContext().unbindService(mConnection);
                }
                finish();
            }
        }

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

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if(!getIntent().hasExtra("exit")) {
            serviceIntent = new Intent(getApplicationContext(), OverlayService.class);
            getApplicationContext().startService(serviceIntent);
            getApplicationContext().bindService(serviceIntent, mConnection, Context.BIND_AUTO_CREATE);
            checkDrawOverlayPermission();
        }
    }

    public void checkDrawOverlayPermission() {
        /** check if we already  have permission to draw over other apps */
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (!Settings.canDrawOverlays(this)) {
                /** if not construct intent to request permission */
                Intent intent = new Intent(ACTION_MANAGE_OVERLAY_PERMISSION,
                        Uri.parse("package:" + getPackageName()));
                /** request permission via start activity for result */
                startActivityForResult(intent, 555);
            }
        }else{
            finish();
        }
    }

    public void showToast(String text) {
        Toast.makeText(getApplicationContext(), text, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           String permissions[], int[] grantResults) {

                // If request is cancelled, the result arrays are empty.
                if (grantResults.length > 0
                        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    Log.d("LOG","permission denied");

                } else {
                    Log.d("LOG","permission NOT denied");

                    // permission denied, boo! Disable the
                    // functionality that depends on this permission.
                }
        finish();


            // other 'case' lines to check for other
            // permissions this app might request

    }

    @Override
    protected void onStart() {
        super.onStart();
        Intent intent = new Intent(this, OverlayService.class);
        getApplicationContext().bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onStop() {
        super.onStop();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }
}

1 个答案:

答案 0 :(得分:0)

您可能会泄漏一些会使服务保持活动状态的绑定。在活动生命周期中解除绑定。

@Override
protected void onStop() {
    getApplicationContext().unbindService(mConnection);
    super.onStop();
}

此外,您应该在断开连接时取消设置服务。

@Override
public void onServiceDisconnected(ComponentName arg0) {
    mBound = false;
    mService = null;
}