In my application i'm trying to overlay a layout with a service here when i'm running service it successfully executes and display the layout on lock screen when target devices is lower than oreo but when i'm trying to overlay the same from versions later than oreo it's not working however when i change the flag to Type_Application_Overlay as suggested in other answers it just display layout when screen is unlocked but i want to show it over lock screen i tried searching a lot but didn't find any helpful answers to solving this problem some answers suggested displaying an activity over lockscreen i tried that too but still that didn't prove to be of any help!
Moreover, To add on there are some apps on play store which can easily display any layout over a lock screen even on oreo and pie:
You can take a look at this app:
https://play.google.com/store/apps/details?id=com.wifihacker.whousemywifi.wifirouter.wifisecurity
This app easily display a custom full screen layout over lockscreen even without asking for any overlay permission or device admin permissions.
So if this app is able to overlay over lock screen why am i unable to do the same?
Any help and suggestions into this will be really appreciated!
Here's is my current service code for lock screen:
class LockScreenService : Service() {
private lateinit var mReceiver: BroadcastReceiver
private var isShowing = false
private lateinit var windowManager: WindowManager
lateinit var params: WindowManager.LayoutParams
lateinit var myview: View
var downX:Int = 0
lateinit var locklayout:RelativeLayout
var upX:Int = 0
var indicator: WaveLoadingView?=null
lateinit var date:TextView
lateinit var time:TextView
lateinit var settings:ImageView
lateinit var unlock:LinearLayout
var r:Runnable?=null
companion object{
}
private val mBatInfoReceiver = object : BroadcastReceiver() {
override fun onReceive(ctxt: Context, intent: Intent) {
val level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0)
if (indicator!=null)
{
indicator!!.progressValue = level
indicator!!.setAnimDuration(3000)
indicator!!.startAnimation()
}
}
}
override fun onBind(intent: Intent): IBinder? {
// TODO Auto-generated method stub
return null
}
override fun onCreate() {
super.onCreate()
try {
EventBus.getDefault().register(this)
windowManager = applicationContext.getSystemService(WINDOW_SERVICE) as WindowManager
val li = getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
myview = li.inflate(R.layout.lockscreenlayout, null)
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
params = WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT
)
} else {
params = WindowManager.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
or WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
or WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
or WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
PixelFormat.TRANSLUCENT
)
myview.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
or View.SYSTEM_UI_FLAG_FULLSCREEN
or View.SYSTEM_UI_FLAG_VISIBLE
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_IMMERSIVE
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
)
}
myview.setVisibility(View.VISIBLE)
settings = myview.findViewById(R.id.imgsetting)
settings.setOnClickListener {
var intent = Intent(this, Settings::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
this.startActivity(intent)
windowManager.removeViewImmediate(myview)
}
indicator = myview.findViewById(R.id.indicator)
locklayout = myview.findViewById(R.id.locklay)
this.registerReceiver(this.mBatInfoReceiver, IntentFilter(Intent.ACTION_BATTERY_CHANGED))
time = myview.findViewById(R.id.time)
date = myview.findViewById(R.id.date)
date.text =
SimpleDateFormat("EEEE").format(Calendar.getInstance().time).toString() + "," + SimpleDateFormat("dd").format(
Calendar.getInstance().time
).toString() + " " + SimpleDateFormat("MMMM").format(Calendar.getInstance().time).toString()
try {
unlock.setOnTouchListener(object : View.OnTouchListener {
override fun onTouch(v: View?, event: MotionEvent?): Boolean {
if (event!!.getAction() == MotionEvent.ACTION_DOWN) {
downX = event.getX().toInt()
return true
} else if (event.getAction() == MotionEvent.ACTION_UP) {
upX = event.getX().toInt()
if (upX - downX > 100) {
val animation = AnimationUtils.loadAnimation(applicationContext, R.anim.left_right_anim)
animation.setAnimationListener(object : Animation.AnimationListener {
override fun onAnimationStart(animation: Animation) {}
override fun onAnimationRepeat(animation: Animation) {}
override fun onAnimationEnd(animation: Animation) {
windowManager.removeViewImmediate(myview)
}
})
locklayout.startAnimation(animation)
// swipe right
} else if (downX - upX > -100) {
}
return true
}
return false
}
})
} catch (ex: Exception)
{}
//Register receiver for determining screen off and if user is present
mReceiver = LockScreenStateReceiver()
val filter = IntentFilter(Intent.ACTION_SCREEN_OFF)
filter.addAction(Intent.ACTION_USER_PRESENT)
registerReceiver(mReceiver, filter)
}
catch (ex:Exception)
{
}
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
return START_STICKY
}
inner class LockScreenStateReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
try {
if (intent.action == Intent.ACTION_SCREEN_OFF) {
//if screen is turn off show the textview
if (!isShowing) {
windowManager.addView(myview, params)
isShowing = true
}
} else if (intent.action == Intent.ACTION_USER_PRESENT) {
//Handle resuming events if user is present/screen is unlocked remove the textview immediately
if (isShowing) {
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.O) {
//windowManager.removeViewImmediate(myview)
}
isShowing = false
}
}
}
catch (ex:Exception){
}
}
}
override fun onDestroy() {
//unregister receiver when the service is destroy
try {
EventBus.getDefault().unregister(this)
if (mReceiver != null) {
unregisterReceiver(mReceiver)
}
//remove view if it is showing and the service is destroy
if (isShowing) {
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.O) {
//windowManager.removeViewImmediate(myview)
}
isShowing = false
}
}
catch (ex:Exception)
{
}
super.onDestroy()
}
}