Reputation:
I am Working on a service which will draw a overlay icon on some predefined applications e.g. WhatsApp, FB Messenger, Instagram etc. we set their packages predefined so that our service can detect.
*Its Working Totally Fine on till 19API (Before and Equal to Kitkat Api level)
But its not working on Lollipop and Marshmallow we are testing on Nexus 5,6,5x,6p and Hawaii Devices P8.
in these devices we got error
E/Surface: getSlotFromBufferLocked: unknown buffer: 0x9db36030
Don't Know what does it mean and what the issue behind. Please Help me Here is my Service Code below
public class ChatHeadService extends Service implements OnClickListener {
private WindowManager windowManager;
private ImageView chatHead;
private LayoutParams params;
private Context context;
private BroadcastReceiver mReceiver;
private OnTouchListener mOnTouchlistener;
private Runnable handleIconVisibility;
private Handler mHandler;
private boolean mIsIconAttached;
public final String TAG = "CRAR";
private String mIm;
public ChatHeadService() {
handleIconVisibility = new Runnable() {
@Override
public void run() {
if (getResumedStatus()) {
addTopIcon();
} else {
removeTopIcon();
}
mHandler.postDelayed(handleIconVisibility, 500L);
}
};
mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(
"android.intent.action.SCREEN_OFF")) {
stopTick();
} else if (intent.getAction().equals(
"android.intent.action.SCREEN_ON")) {
startTick();
}
}
};
mOnTouchlistener = new OnTouchListener() {
private int initialX;
private int initialY;
private float initialTouchX;
private float initialTouchY;
@SuppressLint("ClickableViewAccessibility")
@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();
// case MotionEvent.ACTION_UP:
// case MotionEvent.ACTION_MOVE:
// params.x = initialX
// + (int) (event.getRawX() - initialTouchX);
// params.y = initialY
// + (int) (event.getRawY() - initialTouchY);
// windowManager.updateViewLayout(chatHead, params);
// }
Intent intent = new Intent(context, HomeActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("im_name", mIm);
context.startActivity(intent);
return true;
}
};
}
private String[] getActivePackages() {
ActivityManager am = (ActivityManager) context
.getSystemService(Context.ACTIVITY_SERVICE);
final Set<String> activePackages = new HashSet<String>();
final List<ActivityManager.RunningAppProcessInfo> processInfos = am
.getRunningAppProcesses();
for (ActivityManager.RunningAppProcessInfo processInfo : processInfos) {
if (processInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
activePackages.addAll(Arrays.asList(processInfo.pkgList));
}
}
return activePackages.toArray(new String[activePackages.size()]);
}
private boolean isImResumedForLollipop() {
String[] activePackages = getActivePackages();
if (activePackages != null) {
for (String activePackage : activePackages) {
// WhatsApp
if (activePackage.equals("com.whatsapp")
|| activePackage.equals("com.whatsapp.HomeActivity")
|| activePackage.equals("com.whatsapp.Conversation")) {
mIm = activePackage;
return true;
}
// Viber
if (activePackage.equals("com.viber.voip")) {
mIm = activePackage;
return true;
}
// WeChat
if (activePackage.equals("com.tencent.mm")) {
mIm = activePackage;
return true;
}
// Facebook Massenger
if (activePackage
.equals("com.facebook.orca.auth.StartScreenActivity")
|| activePackage
.equals("com.facebook.orca.creation.CreateThreadActivity")
|| activePackage
.equals("com.facebook.messenger.neue.MainActivity")
|| activePackage
.equals("com.facebook.orca.threadview.ThreadViewActivity")) {
mIm = activePackage;
return true;
}
// Tango
if (activePackage.equals("com.sgiggle.production")) {
mIm = activePackage;
return true;
}
// MMS
if (activePackage.equalsIgnoreCase("com.android.mms")) {
mIm = activePackage;
return true;
}
// Textra
if (activePackage.equals("com.textra")) {
mIm = activePackage;
return true;
}
// Hangout
if (activePackage.equals("com.google.android.talk")) {
mIm = activePackage;
return true;
}
// Line
if (activePackage.equals("jp.naver.line.android")) {
mIm = activePackage;
return true;
}
// IMO
if (activePackage.equals("com.imo.android.imoim")) {
mIm = activePackage;
return true;
}
// SKYPE
if (activePackage.equals("com.skype.raider")) {
mIm = activePackage;
return true;
}
// KIK
if (activePackage.equals("kik.android")) {
mIm = activePackage;
return true;
}
// Google Messenger
if (activePackage.equals("com.google.android.apps.messaging")) {
mIm = activePackage;
return true;
}
// Instagram
if (activePackage.equals("com.instagram.android")
|| activePackage.equals("com.instagram.selfupdate")
|| activePackage
.equals("com.instagram.android.activity.MainTabActivity")) {
mIm = activePackage;
return true;
}
// YAHOO Messenger
if (activePackage.equals("com.yahoo.mobile.client.android.im")) {
mIm = activePackage;
return true;
}
// HIKE
if (activePackage.equals("com.bsb.hike")) {
mIm = activePackage;
return true;
}
// BBM
if (activePackage.equals("com.bbm")) {
mIm = activePackage;
return true;
}
// ICQ
if (activePackage.equals("com.icq.mobile.client")) {
mIm = activePackage;
return true;
}
// Nimbuzz
if (activePackage.equals("com.nimbuzz")) {
mIm = activePackage;
return true;
}
// Twitter
if (activePackage.equals("com.twitter.android")
|| activePackage
.equals("com.twitter.android.DMActivity")) {
mIm = activePackage;
return true;
}
}
}
return false;
}
private boolean getResumedStatus() {
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT_WATCH) {
return isImResumedForLollipop();
} else {
return isImResumed();
}
}
@SuppressWarnings("deprecation")
private boolean isImResumed() {
try {
ActivityManager am = (ActivityManager) context
.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> alltasks = am
.getRunningTasks(1);
for (ActivityManager.RunningTaskInfo aTask : alltasks) {
Log.d("TAG", aTask.topActivity.getClassName());
Log.d("TAG", aTask.topActivity.getPackageName());
String className = aTask.topActivity.getClassName();
// WhatsApp
if (className.equals("com.whatsapp.Conversation")
|| className.equals("com.whatsapp")) {
mIm = aTask.topActivity.getPackageName();
return true;
}
// Viber
if (className
.equals("com.viber.voip.messages.ui.ConversationActivity")) {
mIm = aTask.topActivity.getPackageName();
return true;
}
// WeChat
if (className.equals("com.tencent.mm.ui.LauncherUI")) {
mIm = aTask.topActivity.getPackageName();
return true;
}
// Facebook Massenger
if (className
.equals("com.facebook.orca.auth.StartScreenActivity")
|| className
.equals("com.facebook.orca.creation.CreateThreadActivity")
|| className
.equals("com.facebook.messenger.neue.MainActivity")
|| className
.equals("com.facebook.orca.threadview.ThreadViewActivity")) {
mIm = aTask.topActivity.getPackageName();
return true;
}
// Tango
if (className
.equals("com.sgiggle.app.screens.tc.ConversationDetailActivitySWIG")) {
mIm = aTask.topActivity.getPackageName();
return true;
}
// MMS
if (aTask.topActivity.getPackageName().equalsIgnoreCase(
"com.android.mms")) {
mIm = aTask.topActivity.getPackageName();
return true;
}
// Textra
if (className.equals("com.mplus.lib.ui.main.Main")
|| className
.equals("com.mplus.lib.ui.convo.ConvoActivity")) {
mIm = aTask.topActivity.getPackageName();
return true;
}
// Hangout
if (className
.equals("com.google.android.apps.hangouts.phone.ConversationActivity")) {
mIm = aTask.topActivity.getPackageName();
return true;
}
// Line
if (className
.equals("jp.naver.line.android.activity.chathistory.ChatHistoryActivity")) {
mIm = aTask.topActivity.getPackageName();
return true;
}
// IMO
if (className
.equals("com.imo.android.imoim.activities.IMActivity")) {
mIm = aTask.topActivity.getPackageName();
return true;
}
// SKYPE
if (className.equals("com.skype.android.app.chat.ChatActivity")) {
mIm = aTask.topActivity.getPackageName();
return true;
}
// KIK
if (className.equals("kik.android.chat.activity.ChatActivity")) {
mIm = aTask.topActivity.getPackageName();
return true;
}
// Google Messenger
if (className
.equals("com.google.android.apps.messaging.ui.ConversationListActivity")) {
mIm = aTask.topActivity.getPackageName();
return true;
}
// Instagram
if (className
.equals("com.instagram.android.activity.MainTabActivity")) {
mIm = aTask.topActivity.getPackageName();
return true;
}
// YAHOO Messenger
if (className
.equals("com.yahoo.mobile.client.android.im.ConversationActivity")) {
mIm = aTask.topActivity.getPackageName();
return true;
}
// HIKE
if (className
.equals("com.bsb.hike.chatthread.ChatThreadActivity")) {
mIm = aTask.topActivity.getPackageName();
return true;
}
// BBM
if (className.equals("com.bbm.ui.activities.MainActivity")) {
mIm = aTask.topActivity.getPackageName();
return true;
}
// ICQ
if (className
.equals("ru.mail.instantmessanger.flat.chat.IcqFlatChatActivity")) {
mIm = aTask.topActivity.getPackageName();
return true;
}
// Nimbuzz
if (className.equals("com.nimbuzz.ChatView")) {
mIm = aTask.topActivity.getPackageName();
return true;
}
// Twitter
if (className.equals("com.twitter.android")
|| className.equals("com.twitter.android.DMActivity")) {
mIm = aTask.topActivity.getPackageName();
return true;
}
}
} catch (Throwable t) {
Log.i(TAG, "Throwable caught: " + t.getMessage(), t);
}
return false;
}
private void addTopIcon() {
if (mIsIconAttached) {
return;
} else {
drawIconView();
mIsIconAttached = true;
return;
}
}
@SuppressLint("RtlHardcoded")
private void drawIconView() {
params = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT, LayoutParams.TYPE_PHONE,
LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSLUCENT);
if (mIm.equalsIgnoreCase("com.twitter.android")
|| mIm.equals("com.twitter.android.composer.ComposerActivity")) {
params.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
params.y = 10;
params.x = -160;
} else {
params.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
params.y = 10;
}
windowManager.addView(chatHead, params);
}
@SuppressLint("RtlHardcoded")
private void reDrawIconView() {
int i = getResources().getConfiguration().orientation;
Log.d("TAG", "" + i);
params = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT, LayoutParams.TYPE_PHONE,
LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSLUCENT);
params.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
params.y = 10;
windowManager.updateViewLayout(chatHead, params);
}
private void removeTopIcon() {
if (!mIsIconAttached) {
return;
} else {
removeIconView();
mIsIconAttached = false;
return;
}
}
private void removeIconView() {
if (windowManager != null && chatHead != null) {
windowManager.removeViewImmediate(chatHead);
return;
}
}
private void stopTick() {
if (mHandler != null) {
mHandler.removeCallbacks(handleIconVisibility);
return;
} else {
Log.d("TAG", "mHandler is null");
return;
}
}
private void startTick() {
if (mHandler != null) {
mHandler.removeCallbacks(handleIconVisibility);
mHandler.postDelayed(handleIconVisibility, 1000L);
return;
} else {
Log.d("TAG", "mHandler is null");
return;
}
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
if (mIsIconAttached) {
reDrawIconView();
}
super.onConfigurationChanged(newConfig);
}
private void init() {
chatHead = new ImageView(context);
chatHead.setImageResource(R.drawable.chat_head);
chatHead.setOnTouchListener(mOnTouchlistener);
Log.e("Chat head", "On touch listner triggered");
chatHead.setOnClickListener(this);
Log.e("Chat head", "click listner triggered");
mHandler = new Handler();
}
private void registerIntentReceiver() {
IntentFilter intentfilter = new IntentFilter();
intentfilter.addAction("android.intent.action.SCREEN_ON");
intentfilter.addAction("android.intent.action.SCREEN_OFF");
registerReceiver(mReceiver, intentfilter);
}
private void unregisterIntentReceiver() {
unregisterReceiver(mReceiver);
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
context = this;
registerIntentReceiver();
init();
super.onCreate();
}
@Override
public void onDestroy() {
stopTick();
unregisterIntentReceiver();
mHandler = null;
super.onDestroy();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
startTick();
return START_STICKY;
}
@Override
public void onClick(View v) {
Log.e("Chat head", "on clickview function triggerd complete");
}
}
Any Help would be great...
Upvotes: 3
Views: 692
Reputation: 16609
For Lollipop:
it works for me. But You have to add this permission in your mainfest.
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
Anyway you can check if you got the permission before drowing:
if (Settings.canDrawOverlays(context)) {
// Here you go, you can draw you chathead view
}
For Marshmallow
Since it needs an extra permission, It does not work directly. I tried to find the settings and send user there. I found that you can send the user from your app directly to the permission page in the settings with this intent .
ACTION_MANAGE_OVERLAY_PERMISSION
montioned on in the documentation of Settings.canDrawOverlays(context) page
this may be helpful for you:
Android System overlay window - StackOverflow
UPDATE: This is the documentation of canDrawOverlays:
Checks if the specified context can draw on top of other apps. As of API level 23, an app cannot draw on top of other apps unless it declares the SYSTEM_ALERT_WINDOW permission in its manifest, and the user specifically grants the app this capability. To prompt the user to grant this approval, the app must send an intent with the action ACTION_MANAGE_OVERLAY_PERMISSION, which causes the system to display a permission management screen.
Settings.canDrawOverlays(context) documentation
Hope this helps.
Upvotes: 0