2014년 3월 31일 월요일

Android, floating window app을 위한 StandOut library

Activity 실행에 상관없이 항상 떠 있는 Floating window app을 만들어야 했기에 찾아보고 정리함. (하지만 구글 앱스토어에 이런 앱을 만들어 올려 다른 앱 실행을 방해한다면 등록 불허 될 수도 있음 ^^;;;; )

찾아보니 StandOut library가 거의 유일 하게 존재하여 대충 정리 ㅜㅜ

[StandOut library]
 by pingpongboss
 Intorduction : http://forum.xda-developers.com/showthread.php?t=1688531
 Source code : https://github.com/pingpongboss/StandOut

Functionality
  • Provide your own view. Very easy to integrate
  • Window decorators (titlebar, minimize/close buttons, border, resize handle)
  • Windows are moveable and resizable. You can bring-to-front, minimize, and close
  • Minimized windows can be restored (the example APK demos this using the notification panel)
  • Create multiple types of windows, and multiple windows of each type
  • Continuously being developed. More coming.

깔끔하게 library 형태로 되어 있고 소스코드의 규모도 간단하여 분석 쉬움.
Android Service를 상속한 StandOutWindow를 상속하여 각 창에 해당되는 window class를 생성하여 floating window를 보여주며 StandOut library 내에서 touch event를 각 view의 widget들에 전달할 수 있도록 처리하고 있음.

StandOutWindow class
: https://github.com/pingpongboss/StandOut/blob/master/library/src/wei/mark/standout/StandOutWindow.java


/**
 * Extend this class to easily create and manage floating StandOut windows.
 * 
 * @author Mark Wei <markwei@gmail.com>
 * 
 *         Contributors: Jason <github.com/jasonconnery>
 * 
 */
public abstract class StandOutWindow extends Service {
 static final String TAG = "StandOutWindow";

Window class
: https://github.com/pingpongboss/StandOut/blob/master/library/src/wei/mark/standout/ui/Window.java



/**
 * Special view that represents a floating window.
 * 
 * @author Mark Wei <markwei@gmail.com>
 * 
 */
public class Window extends FrameLayout {
 public static final int VISIBILITY_GONE = 0;
 public static final int VISIBILITY_VISIBLE = 1;
 public static final int VISIBILITY_TRANSITION = 2;

 static final String TAG = "Window";

 /**
  * Class of the window, indicating which application the window belongs to.
  */
 public Class<? extends StandOutWindow> cls;
...생략

 /**
  * Context of the window.
  */
 private final StandOutWindow mContext;
 private LayoutInflater mLayoutInflater;

 public Window(Context context) {
  super(context);
  mContext = null;
 }

 public Window(final StandOutWindow context, final int id) {
  super(context);
  context.setTheme(context.getThemeStyle());

  mContext = context;
  mLayoutInflater = LayoutInflater.from(context);

...생략

  // create the window contents
  View content;
  FrameLayout body;

...생략
  addView(content);

  body.setOnTouchListener(new OnTouchListener() {

   @Override
   public boolean onTouch(View v, MotionEvent event) {
    // pass all touch events to the implementation
    boolean consumed = false;

    // handle move and bring to front
    consumed = context.onTouchHandleMove(id, Window.this, v, event)
      || consumed;

    // alert implementation
    consumed = context.onTouchBody(id, Window.this, v, event)
      || consumed;

    return consumed;
   }
  });

  // attach the view corresponding to the id from the
  // implementation
  context.createAndAttachView(id, body);


사용자는 StandOutWindow를 상속받아 app 이름, view 구성, window 크기 설정등을 하면 간단한 window를 생성할 수 있으며 window의 세부 설정을 지정할 수 있도록 parameter를 풍부하게 제공하고 있음.

StandOutWindow example 중 SimpleWindow
: https://github.com/pingpongboss/StandOut/blob/master/example/src/wei/mark/example/SimpleWindow.java


public class SimpleWindow extends StandOutWindow {

 @Override
 public String getAppName() {
  return "SimpleWindow";
 }

 @Override
 public int getAppIcon() {
  return android.R.drawable.ic_menu_close_clear_cancel;
 }

 @Override
 public void createAndAttachView(int id, FrameLayout frame) {
  // create a new layout from body.xml
  LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
  inflater.inflate(R.layout.simple, frame, true);
 }

 // the window will be centered
 @Override
 public StandOutLayoutParams getParams(int id, Window window) {
  return new StandOutLayoutParams(id, 250, 300,
    StandOutLayoutParams.CENTER, StandOutLayoutParams.CENTER);
 }

 // move the window by dragging the view
 @Override
 public int getFlags(int id) {
  return super.getFlags(id) | StandOutFlags.FLAG_BODY_MOVE_ENABLE
    | StandOutFlags.FLAG_WINDOW_FOCUSABLE_DISABLE;
 }

다만 각 window를 닫을 때 StandOut.close,  StandOut.closeAll을 호출하면 되는대 각 window가 Android service로 돌아가고 있어 서비스까지 완전히 종료하려면 service의 intent filter 걸어서 stop시켜야 함.

[TouchSoftly]
 : http://stackoverflow.com/questions/11443820/floating-widget-overlay-on-android-launcher?answertab=votes#tab-top
Source code : https://github.com/t0mm13b/TouchSoftly

floating window app을 만드는 방법에 대한 글과 간단한 prototype이다.
StandOut library 분석이 좀 부담된다면 이것을 참고하면 될듯.

댓글 없음:

댓글 쓰기