always on top button in android

how can i put my PopupWindow to system desk or other app? how can i use this permission:INTERNAL_SYSTEM_WINDOW
Any examples?Thanks!

link | edit | flag

0% accept rate
 
1 
Weird Coincidence, Asked something similar hours ago...stackoverflow.com/questions/3732935/…  –  st0le Sep 17 '10 at 9:43
 
yes, i want to know how can it happens?i can't get any information about INTERNAL_SYSTEM_WINDOW,please help me if you know anything.  –  yuankai   Sep 19 '10 at 1:12

3 Answers

ok,the problem is resolved. i use WindowManager.addView in a service, and WindowManager.LayoutParams.type = TYPE_SYSTEM_ALERT, then it's ok! you can try it!

link | edit | flag
 
 
@yuankai, Could you please share the Source Code? I'd be very gratefull. :)  –  st0le   Sep 21 '10 at 7:33
 
ok, how can i share my code here, can i put some files here?  –  yuankai   Sep 21 '10 at 9:59
 
@yunkai, i didn't notice your comment till now...just edit your answer and put your code there. that'll do. Thanks a lot! :)  –  st0le   Sep 27 '10 at 4:36
 
@yuankai, btw, FYI if you're addressing someone using comments use @username that'll notify that user of your comment. Cheers! :)  –  st0le   Sep 27 '10 at 4:37
 
@st0le,thank you very much!  –  yuankai   Oct 8 '10 at 1:14
public class PopupService extends Service implements IPopupTouchPosListener
{
 
public final static String FIELD_EVENT = "event";
 
/**
  * 开启
  */

 
public final static int EVENT_SWITCH_ON = 1;

 
/**
  * 关闭
  */

 
public final static int EVENT_SWITCH_OFF = 2;

 
private CustomPopupView mPopupView;
 
private int mCurrentY;

 
private RelativeLayout mLayout;

 
private WindowManager mWindowManager;
 
private WindowManager.LayoutParams mWmlp;

 
@Override
 
public void onCreate()
 
{
 
// TODO Auto-generated method stub
 
super.onCreate();

  mWindowManager
= (WindowManager)getSystemService(Context.WINDOW_SERVICE);

 
// 获取屏幕宽度
 
DisplayMetrics outMetrics = new DisplayMetrics();
  mWindowManager
.getDefaultDisplay().getMetrics(outMetrics);
 
int width = outMetrics.widthPixels;

  mWmlp
= new WindowManager.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
  mWmlp
.alpha = 0.5f;
  mWmlp
.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; // 不能抢占聚焦点
  mWmlp
.flags = mWmlp.flags | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
  mWmlp
.flags = mWmlp.flags | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS; // 排版不受限制
  mWmlp
.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;     // 系统提示类型
  mWmlp
.width = width;
  mWmlp
.height = 30;
  mWmlp
.gravity = 2;
  mWmlp
.format = -1;
  mWmlp
.token = null;
  mWmlp
.x = 0;
  mWmlp
.y = 200;

  mCurrentY
= mWmlp.y;

  mLayout
= new RelativeLayout(this);
  mLayout
.setBackgroundColor(0x00FFFFFF);
  mLayout
.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));

  mPopupView
= new CustomPopupView(this);
  mPopupView
.setTouchPosListener(this);
 
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT, 30);

  lp
.bottomMargin = 0;
  lp
.leftMargin = 0;

  mLayout
.addView(mPopupView, lp);
 
}

 
@Override
 
public void onStart(Intent intent, int startId)
 
{
 
super.onStart(intent, startId);

 
Log.i(Constants.LOG_TAG, "popup service onstart");

 
String action = intent.getAction();
 
if(action != null && action.equals(ActionDef.ACTION_POPUP_SERVICE))
 
{
   
Bundle bundle = intent.getExtras();
   
if(bundle != null)
   
{
   
int event = bundle.getInt(FIELD_EVENT);
   
if(event == EVENT_SWITCH_ON)
   
{
     
// 显示
     mWindowManager
.addView(mLayout, mWmlp);
   
}
   
else
   
{
     mWindowManager
.removeView(mLayout);
   
}
   
}
 
}
 
}

 
@Override
 
public IBinder onBind(Intent intent)
 
{
 
// TODO Auto-generated method stub
 
return null;
 
}

 
@Override
 
public void onMove(float x, float y)
 
{
 
if(mLayout != null)
 
{
   
Log.i(Constants.LOG_TAG, "y = " + y);
   
if(y > mLayout.getHeight())
   
{
    mCurrentY
= (int)y + mCurrentY - mLayout.getHeight();
   
}
   
else if(y < 0)
   
{
    mCurrentY
= (int)y + mCurrentY;
   
}

   
// 只更新位置
   mWmlp
.y = mCurrentY;
   mWindowManager
.updateViewLayout(mLayout, mWmlp);
 
}
 
}

}
link | edit | flag
 
 
there are some chinese words,you needn't care for it,just comment.  –  yuankai   Sep 28 '10 at 2:16
 
@yuankai, thanks.  –  st0le   Sep 28 '10 at 4:15

When I implement the code posted by @yuankai and add a Button view to the layout where he has a CustomPopupView, it appears as expected, over the top of all windows and responds to click events but won't change colour when pressed as Buttons normally do.

How can I update the button to change colour when depressed like its normal behaviour?

link | edit | flag
 
 
you can get the click event when you setOnClickListener,and then change the color。  –  yuankai   Dec 9 '10 at 1:59
 
@yuankai Thanks, I worked it out by using setOnTouchListener and setting Button.setBackgroundDrawable manually. I now have a similar problem with a GestureOverlayView which isn't deleting gestures which have been performed. GestureOverlayView.clear(false) doesn't seem to be working. What's missing from this service-to-window procedure that an Activity normally has?  –  deweylewie   Dec 9 '10 at 19:33
 
@deweylewie hi,i got nothing about GestureOverlayView,i think i cannot help you,sorry。  –  yuankai   Dec 15 '10 at 2:14

http://stackoverflow.com/questions/3734099/how-can-i-put-my-popupwindow-to-system-desk-or-other-app/3809160

 

 

 

 

I'm trying to create an always-op-top button/clickable-image which stays on top of all the windows all the time. The proof of concept is here http://www.appbrain.com/app/smart-taskbar-%28sidebar%29/com.smart.taskbar and here http://forum.xda-developers.com/showthread.php?t=865525 I'm following this example code http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;f=services/java/com/android/server/LoadAverageService.java;h=0d86429aaa5ccf6ecf311dfb3af0f3ccbf5f8d29;hb=HEAD

I have been successful and have a running service now. The service displays some text on top left corner of screen all the time while user can freely interact with rest of apps in normal manner. What I'm doing is subclass ViewGroup and add it to root window manager with flag TYPE_SYSTEM_OVERLAY. Now I want to add a button/clickable-image in place of this text which can receive touch events on itself. I tried overriding "onTouchEvent" for the whole ViewGroup but it does not receive any event. How can I receive events only on certain parts of my always-on-top view group? Kindly suggest.

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.os.IBinder;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.AbsoluteLayout;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Toast;

public class HUD extends Service {
   
HUDView mView;

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

   
@Override
   
public void onCreate() {
       
super.onCreate();
       
Toast.makeText(getBaseContext(),"onCreate", Toast.LENGTH_LONG).show();
        mView
= new HUDView(this);
       
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
               
WindowManager.LayoutParams.WRAP_CONTENT,
               
WindowManager.LayoutParams.WRAP_CONTENT,
               
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
               
0,
//              WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
//                      | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
               
PixelFormat.TRANSLUCENT);
       
params.gravity = Gravity.RIGHT | Gravity.TOP;
       
params.setTitle("Load Average");
       
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
        wm
.addView(mView, params);
   
}

   
@Override
   
public void onDestroy() {
       
super.onDestroy();
       
Toast.makeText(getBaseContext(),"onDestroy", Toast.LENGTH_LONG).show();
       
if(mView != null)
       
{
           
((WindowManager) getSystemService(WINDOW_SERVICE)).removeView(mView);
            mView
= null;
       
}
   
}
}

class HUDView extends ViewGroup {
   
private Paint mLoadPaint;

   
public HUDView(Context context) {
       
super(context);
       
Toast.makeText(getContext(),"HUDView", Toast.LENGTH_LONG).show();

        mLoadPaint
= new Paint();
        mLoadPaint
.setAntiAlias(true);
        mLoadPaint
.setTextSize(10);
        mLoadPaint
.setARGB(255, 255, 0, 0);
   
}

   
@Override
   
protected void onDraw(Canvas canvas) {
       
super.onDraw(canvas);
        canvas
.drawText("Hello World", 5, 15, mLoadPaint);
   
}

   
@Override
   
protected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int arg4) {
   
}

   
@Override
   
public boolean onTouchEvent(MotionEvent event) {
       
//return super.onTouchEvent(event);
       
Toast.makeText(getContext(),"onTouchEvent", Toast.LENGTH_LONG).show();
       
return true;
   
}
}
link | edit | flag

 
 
@coreSOLO, I hope you get you're answer, my oddly similar questions didnt get any response. :) +1 –  st0le Dec 19 '10 at 6:44
 
@st0le I promise I'll spend my night and day until I find the solution and share it with you :)  –  coreSOLO   Dec 19 '10 at 8:02
 
@coreSOLO, hehe ;)  –  st0le   Dec 19 '10 at 8:15
 
@st0le Ok maybe you and me can dig it out together, give me a link of your question and let me know how much progress you were able to make...  –  coreSOLO   Dec 19 '10 at 9:01
 
its not much :-/ stackoverflow.com/questions/3732935/…  –  st0le   Dec 19 '10 at 9:40
show 1 more comment

3 Answers

up vote 5 down vote accepted

This might be a stupid solution. But it works. If you can improve it, please let me know.

OnCreate of your Service: I have usedWindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH flag. This is the only change in service.

@Override
   
public void onCreate() {
       
super.onCreate();
       
Toast.makeText(getBaseContext(),"onCreate", Toast.LENGTH_LONG).show();
        mView
= new HUDView(this);
       
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
               
WindowManager.LayoutParams.WRAP_CONTENT,
               
WindowManager.LayoutParams.WRAP_CONTENT,
               
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
               
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
               
PixelFormat.TRANSLUCENT);
       
params.gravity = Gravity.RIGHT | Gravity.TOP;
       
params.setTitle("Load Average");
       
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
        wm
.addView(mView, params);
   
}

Now, you will start getting each and every click event. So, you need to rectify in your event handler.

In your ViewGroup touch event

@Override public boolean onTouchEvent(MotionEvent event) {

    // ATTENTION: GET THE X,Y OF EVENT FROM THE PARAMETER
   
// THEN CHECK IF THAT IS INSIDE YOUR DESIRED AREA


   
Toast.makeText(getContext(),"onTouchEvent", Toast.LENGTH_LONG).show();
   
return true;
}
link | edit | flag
 
 
AWESOME!!! Thanks a bunch. I'll try this out and let you know, but I know for sure that it works :) Yes I have a couple of possible improvements in mind for my original service which might optimize event handling. I'll let you know soon! Thanks again!  –  coreSOLO   Dec 19 '10 at 14:02
 
can you give some more codes,when i run the code,but get more errors  –  pengwang   Dec 27 '10 at 10:10
 
@pengwang: what errors are you getting? This code is not independent, you need to place them in your project with appropriate file names under appropriate project.  –  Sarwar Erfan   Dec 28 '10 at 3:34
 
i am sorry,i only do it as a commom demo. can you give a easy demo in your blog or other link,so that i can study it.thank you  –  pengwang   Dec 28 '10 at 3:45
1 
@pengwang: Find simplest implementation here: docs.google.com/…  –  Sarwar Erfan   Dec 28 '10 at 12:07
show 4 more comments

It is not possible to get event in this fashion. You can only "display".

====== I have added a solution that worked for me. See my another reply.

link | edit | flag
 
 
@Sarwar, i beg to differ, have you seen the Smart Task Bar app? It does handle click events...  –  st0le   Dec 19 '10 at 6:45
 
Yes please, its already been done...  –  coreSOLO   Dec 19 '10 at 8:01
 
depending how serious you are about this issue, how far you want to go, what is your ethical views, how much you understand assembly like code, how much you are interested in a particular app... there exists ways to partially discover what others are doing in their apps... But, lets see if anyone can provide a good answer in normal way. Voting up your question.  –  Sarwar Erfan   Dec 19 '10 at 9:42
 
Thanks a lot. Ethically, its all about my ZTE Blade which has a shobby back button and I want to add an on screen back button, but in a much simpler way than the two implementations described above. I'm trying to contact original authors and just in case i'll get something i'll post it here too!  –  coreSOLO   Dec 19 '10 at 9:53
 
I have got some success in testing... I will post after confirming.  –  Sarwar Erfan   Dec 19 '10 at 11:39
show 1 more comment

Well try my code, atleast it gives you a string as overlay, you can very well replace it with a button or an image. You wont believe this is my first ever android app LOL. Anyways if you are more experienced with android apps than me, please try

  • changing parameters 2 and 3 in "new WindowManager.LayoutParams"
  • try some different event approach
link | edit | flag
 
 
@coreSOLO, I've got over 8 months of Android behind me, but here's a thread that helped me earlier...stackoverflow.com/questions/3734099/…  –  st0le   Dec 19 '10 at 11:05
 
@coreSOLO, i eventually didnt find time to pursue this, hence i'm still scarce on its details...  –  st0le   Dec 19 '10 at 11:06

 

http://stackoverflow.com/questions/4481226/creating-a-system-overlay-always-on-top-button-in-android

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值