Facebook chat like floating chat heads
Facebook recently released a new feature in Facebook Messenger in which the chat from person floats on screen instead of residing inside conventional application. This feature is very continent for multitasking as user can work and chat at the same time. Like you are using calculator and someone message you on facebook then this chat is shown over calculator like a floating bubble and you can reply to this chat by just by clicking the chat head and then resume your work after ward . So no app switching !!!
Chathead Basics :
At first it looks like some kind of transparent activity. But its not a transparent activity.
1 2 3 4 |
$ adb shell dumpsys activity Running activities (most recent first): TaskRecord{42b03c38 #2 A com.android.launcher U 0} Run #0: ActivityRecord{42adf3f8 u0 com.android.launcher/com.android.launcher2.Launcher} |
That means its a service running in background and controlling the view which is attached to window. As you probably know, an Activity has a Window instance. Dialogs also have their own dedicated Window. Even Services can have Window: InputMethodService uses a Window to receive touch events and draw a keyboard on top of another Window, and DreamService is used to create screensavers.
To open a new window in which you will draw the chathead, you need the SYSTEM_ALERT_WINDOW permission.<uses-permission android:name=”android.permission.SYSTEM_ALERT_WINDOW”/>
Preview:
Lets get Started :
1. Create new project :
Create a new project File -> New -> Android Project
2. Add a new service to project
Add a new class named ChatHeadService.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
package com.example.chatheads; import android.app.Service; import android.content.Intent; import android.graphics.PixelFormat; import android.os.IBinder; import android.view.Gravity; import android.view.MotionEvent; import android.view.View; import android.view.WindowManager; import android.widget.ImageView; public class ChatHeadService extends Service { private WindowManager windowManager; private ImageView chatHead; WindowManager.LayoutParams params; @Override public void onCreate() { super.onCreate(); windowManager = (WindowManager) getSystemService(WINDOW_SERVICE); chatHead = new ImageView(this); chatHead.setImageResource(R.drawable.face1); 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; //this code is for dragging the chat head chatHead.setOnTouchListener(new View.OnTouchListener() { private int initialX; private int initialY; private float initialTouchX; private float initialTouchY; @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: initialX = params.x; initialY = params.y; initialTouchX = event.getRawX(); initialTouchY = event.getRawY(); return true; case MotionEvent.ACTION_UP: return true; case MotionEvent.ACTION_MOVE: params.x = initialX + (int) (event.getRawX() - initialTouchX); params.y = initialY + (int) (event.getRawY() - initialTouchY); windowManager.updateViewLayout(chatHead, params); return true; } return false; } }); windowManager.addView(chatHead, params); } @Override public void onDestroy() { super.onDestroy(); if (chatHead != null) windowManager.removeView(chatHead); } @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub return null; } } |
3. Update activity_main.xml
Add following code to activity_main.xml. This will add buttons to control the visibility of the chathead.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.chatheads.MainActivity"> <Button android:id="@+id/startService" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:layout_marginTop="27dp" android:text="start chat head service"/> <Button android:id="@+id/stopService" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/startService" android:layout_below="@+id/startService" android:layout_marginTop="39dp" android:text="stop chat head service"/> </RelativeLayout> |
4. Update manifest file
Update the manifest file by adding service to manifest along with permission for SYSTEM_ALERT_WINDOW
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.chatheads" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="19"/> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme"> <activity android:name=".MainActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> <service android:name="com.example.chatheads.ChatHeadService"> </service> </application> </manifest> |
5. Build and Run
Now build and run the project to see the results