I would like to display a personalized view (who display some data in real time) on the lockscreen (after that the user locked the phone on the activity).
Google Maps et Baidu Maps (and some other apps that I forgot the name) have exactly implemented what I want.
So I'm trying to add a view when my BroadcastReceiver is triggered.
There is some points that I tried from this answer and this one. I tried this one too.
Before I got some error according to permission :
permission denied for window type 2XXX
Now I don't have any error but my view is not displayed.
There is my situation :
MainActivity.kt:
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.provider.Settings
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
private val REQUEST_CODE = 10001
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
checkDrawOverlayPermission()
}
fun checkDrawOverlayPermission() {
/** check if we already have permission to draw over other apps */
if (!Settings.canDrawOverlays(this)) {
/** if not construct intent to request permission */
val intent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getPackageName()));
/** request permission via start activity for result */
startActivityForResult(intent, REQUEST_CODE);
}
else {
startService(Intent(this, LockScreenService::class.java))
}
}
override fun onActivityResult(
requestCode: Int,
resultCode: Int,
data: Intent?
) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == REQUEST_CODE) {
if (Settings.canDrawOverlays(this)) {
startService(Intent(this, LockScreenService::class.java))
}
}
}
}
LockSceenService.kt:
class LockScreenService : Service() {
private var mReceiver: BroadcastReceiver? = null
private var isShowing = false
override fun onBind(intent: Intent): IBinder? {
// TODO Auto-generated method stub
return null
}
private var windowManager: WindowManager? = null
private var textview: TextView? = null
private var mView: View? = null
var params: WindowManager.LayoutParams? = null
override fun onCreate() {
super.onCreate()
windowManager = getSystemService(Context.WINDOW_SERVICE) as WindowManager
mView = View.inflate(baseContext, R.layout.lockscreen_view, null)
mView!!.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE
or View.SYSTEM_UI_FLAG_FULLSCREEN
or View.SYSTEM_UI_FLAG_VISIBLE
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)
mView!!.visibility = View.VISIBLE
//set parameters for the textview
val flag: Int = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
} else {
WindowManager.LayoutParams.TYPE_PHONE
}
params = WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
flag,
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
or WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
or WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
or WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
or WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
or WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
PixelFormat.TRANSLUCENT
)
params!!.gravity = Gravity.BOTTOM
//Register receiver for determining screen off and if user is present
mReceiver = LockScreenStateReceiver()
val filter = IntentFilter(Intent.ACTION_SCREEN_ON)
filter.addAction(Intent.ACTION_USER_PRESENT)
registerReceiver(mReceiver, filter)
}
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
return START_STICKY
}
inner class LockScreenStateReceiver : BroadcastReceiver() {
override fun onReceive(
context: Context,
intent: Intent
) {
if (intent.action == Intent.ACTION_SCREEN_ON) {
//if screen is turn off show the textview
if (!isShowing) {
windowManager!!.addView(mView, 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) {
windowManager!!.removeViewImmediate(textview)
isShowing = false
}
}
}
}
override fun onDestroy() {
//unregister receiver when the service is destroy
if (mReceiver != null) {
unregisterReceiver(mReceiver)
}
//remove view if it is showing and the service is destroy
if (isShowing) {
windowManager!!.removeViewImmediate(textview)
isShowing = false
}
super.onDestroy()
}
}
Manifest.xml:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.ACTION_MANAGE_OVERLAY_PERMISSION" />
<uses-permission android:name="android.permission.INTERNET" />
If you have any suggestions or other ways like "transparent activity over lock screen" (?) or just an upvote could be useful.
Thanks for your time!
EDIT: There is a video of what I want