What APIs are used to draw over other apps (like Facebook's Chat Heads)?
This one:
Allows an application to open windows using the type TYPE_SYSTEM_ALERT, shown on top of all other applications. Very few applications should use this permission; these windows are intended for system-level interaction with the user.
Constant Value: "android.permission.SYSTEM_ALERT_WINDOW"
//EDIT: The full code here:
public class ChatHeadService extends Service {
private WindowManager windowManager;
private ImageView chatHead;
@Override public IBinder onBind(Intent intent) {
// Not used
return null;
}
@Override public void onCreate() {
super.onCreate();
windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
chatHead = new ImageView(this);
chatHead.setImageResource(R.drawable.android_head);
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_PHONE,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.TOP | Gravity.LEFT;
params.x = 0;
params.y = 100;
windowManager.addView(chatHead, params);
}
@Override
public void onDestroy() {
super.onDestroy();
if (chatHead != null) windowManager.removeView(chatHead);
}
}
Don't forget to start the service somehow:
startService(new Intent(context, ChatHeadService.class));
.. And add this service to your Manifest.
As a rule, Android activities are full screen, conceptually dedicated UIs that take all the interaction. There are a few exceptions to this. For a start, there are popup dialogs that don't fill the screen. Another is the Android toast, which is a non-interactive popup - you can't touch it, and if you try it'll go to whatever's underneath.
You can do your own special UIs too. You can add views directly to the WindowManager
, specifying a type flag. Chat Heads probably uses TYPE_PHONE. There are a few similar types, but the purpose is the same: special purpose overlays that can appear over the top of anything else without the parent application apparently being present.
That only gets you so far, though, because of problems with interaction. At first, your overlay will absorb all the interaction, so not only does the head get events, but you block interaction to everything underneath.
You configure this behaviour using the LayoutParams. FLAG_NOT_TOUCH_MODAL
means that events outside of your display area go to the underlying UIs. You'll now find it works, but that other bad things still happen, like the back/menu buttons don't get directed to apps, plus no keyboard. To solve that you need FLAG_NOT_FOCUSABLE
.
You get a side effect from the non-focusable bit too, which is no nice interactions with your overlay any more, e.g. button presses. You can get some basic touch events though, which you can always do maths on, and that's probably enough for Chat Heads. Just be aware that it leaves you on your own in plenty of areas, like UI animation.
A good overview of the detail, including allowing for selective interaction consumption, can be found in this StackOverflow thread. In particular one of the answer links will eventually take you here, which is a good example project. Note that ICS changed how this works a little, but the threads explain that.
This is all public API stuff, but it doesn't really seem like a mainstream thing that one ought to be doing as a matter of course. The documentation is littered with references to special system app behaviours, and with good reason; what if everyone did it?
Springy heads gives spring based behaviour of chat heads out of the box. All you have to define is the drawable for the chat head and the fragment to open once the chat head is clicked. The chat heads collapse when minimized and follow the finger when dragged.
The project includes a demo app which demonstrates all the built in functionality. To use it, you need to add this into your gradle dependencies.
compile 'com.flipkart.springyheads:library:0.9.6'