覆盖服务 - 按下返回按钮
Service with Overlay - catch back button press
我该怎么做?
当前解
我启动了一个透明的 activity,它捕捉到后退的压力,将其转发到我的服务并随后自行关闭。但是这个 activity 将在当前的 运行 活动中可见,因此这不是一个非常漂亮的解决方案。
看到的解决方案
我见过一个应用程序确实在服务中捕捉到后按 - 没有 activity 捕捉到后按。如果我显示当前 运行 个活动,则此应用程序没有任何内容。
问题
如何做到这一点?我读过很多帖子说,这是不可能的,但我可以看到,有些应用程序可以以某种方式实现这一目标...
我想我发现了它是如何工作的...不要在您的叠加视图中使用 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+ 覆盖您视图的 dispatchKeyEvent
:
@Override
public boolean dispatchKeyEvent(KeyEvent event)
{
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK)
{
// handle back press
// if (event.getAction() == KeyEvent.ACTION_DOWN)
return true;
}
return super.dispatchKeyEvent(event);
}
您可以捕捉后退按钮点击事件。为此,您需要创建 OverlayView 的容器 class。例如:创建 class Overlay,它将扩展一些 ViewGroup class。然后,在 class 中膨胀您的 xml 布局并将其添加到您的 Overlay.class ViewGroup。比 Overlay.class 覆盖方法 dispatchKeyEvent(KeyEvent event)。就这些!
class Overlay extends FrameLayout{
public Overlay(@NonNull Context context) {
super(new ContextThemeWrapper(context, R.style.AppTheme));
initView();
}
private void initView() {
//inflate your xml here
//than do: this.addView(<inflated view>);
//And in the end add your Overlay to WindowManager (in Service class of course).
}
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
//do staff here
// and return True!
return true;
}
return super.dispatchKeyEvent(event);
}
}
我找到了这个问题的解决方案,效果很好。
public class MyFooterService extends Service{
View myview;
WindowManager wm;
FrameLayout wrapper;
public MyFooterService() {
}
@Override
public void onCreate() {
Log.d(TAG, "onCreate called");
LayoutInflater li = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
wm = (WindowManager) getSystemService(WINDOW_SERVICE);
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
90, //height of ur layout
WindowManager.LayoutParams.TYPE_PHONE,
0,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.BOTTOM ;
params.x = 0;
params.y = 0;
wrapper = new FrameLayout(this) {
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getKeyCode()==KeyEvent.KEYCODE_BACK) {
// handle the back button code;
return true;
}
return super.dispatchKeyEvent(event);
}
//if pressed home key,
public void onCloseSystemDialogs(String reason) {
//The Code Want to Perform.
System.out.println("System dialog " + reason);
if (reason.equals("homekey")) {
// handle home button
}
}
};
myview = li.inflate(R.layout.my_footer, wrapper); // here set into your own layout
wm.addView(myview, params);
}
}
如果您在服务的 WindowManager 中附加了叠加层 window,请将您的视图属性设置为 setFocusableInTouchMode(true),并放置一个关键侦听器。您将收到关键事件,如本例所示:
view.setFocusableInTouchMode(true);
view.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if(keyCode == KeyEvent.KEYCODE_BACK) {
stopSelf();
return true;
}
return false;
}
});
编辑了,我没有用好的Whosebug账号
我该怎么做?
当前解
我启动了一个透明的 activity,它捕捉到后退的压力,将其转发到我的服务并随后自行关闭。但是这个 activity 将在当前的 运行 活动中可见,因此这不是一个非常漂亮的解决方案。
看到的解决方案
我见过一个应用程序确实在服务中捕捉到后按 - 没有 activity 捕捉到后按。如果我显示当前 运行 个活动,则此应用程序没有任何内容。
问题
如何做到这一点?我读过很多帖子说,这是不可能的,但我可以看到,有些应用程序可以以某种方式实现这一目标...
我想我发现了它是如何工作的...不要在您的叠加视图中使用 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+ 覆盖您视图的 dispatchKeyEvent
:
@Override
public boolean dispatchKeyEvent(KeyEvent event)
{
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK)
{
// handle back press
// if (event.getAction() == KeyEvent.ACTION_DOWN)
return true;
}
return super.dispatchKeyEvent(event);
}
您可以捕捉后退按钮点击事件。为此,您需要创建 OverlayView 的容器 class。例如:创建 class Overlay,它将扩展一些 ViewGroup class。然后,在 class 中膨胀您的 xml 布局并将其添加到您的 Overlay.class ViewGroup。比 Overlay.class 覆盖方法 dispatchKeyEvent(KeyEvent event)。就这些!
class Overlay extends FrameLayout{
public Overlay(@NonNull Context context) {
super(new ContextThemeWrapper(context, R.style.AppTheme));
initView();
}
private void initView() {
//inflate your xml here
//than do: this.addView(<inflated view>);
//And in the end add your Overlay to WindowManager (in Service class of course).
}
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
//do staff here
// and return True!
return true;
}
return super.dispatchKeyEvent(event);
}
}
我找到了这个问题的解决方案,效果很好。
public class MyFooterService extends Service{
View myview;
WindowManager wm;
FrameLayout wrapper;
public MyFooterService() {
}
@Override
public void onCreate() {
Log.d(TAG, "onCreate called");
LayoutInflater li = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
wm = (WindowManager) getSystemService(WINDOW_SERVICE);
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
90, //height of ur layout
WindowManager.LayoutParams.TYPE_PHONE,
0,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.BOTTOM ;
params.x = 0;
params.y = 0;
wrapper = new FrameLayout(this) {
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getKeyCode()==KeyEvent.KEYCODE_BACK) {
// handle the back button code;
return true;
}
return super.dispatchKeyEvent(event);
}
//if pressed home key,
public void onCloseSystemDialogs(String reason) {
//The Code Want to Perform.
System.out.println("System dialog " + reason);
if (reason.equals("homekey")) {
// handle home button
}
}
};
myview = li.inflate(R.layout.my_footer, wrapper); // here set into your own layout
wm.addView(myview, params);
}
}
如果您在服务的 WindowManager 中附加了叠加层 window,请将您的视图属性设置为 setFocusableInTouchMode(true),并放置一个关键侦听器。您将收到关键事件,如本例所示:
view.setFocusableInTouchMode(true);
view.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if(keyCode == KeyEvent.KEYCODE_BACK) {
stopSelf();
return true;
}
return false;
}
});
编辑了,我没有用好的Whosebug账号