我的前台服务不会停止。它与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();
}
}
答案 0 :(得分:0)
您可能会泄漏一些会使服务保持活动状态的绑定。在活动生命周期中解除绑定。
@Override
protected void onStop() {
getApplicationContext().unbindService(mConnection);
super.onStop();
}
此外,您应该在断开连接时取消设置服务。
@Override
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
mService = null;
}