5. 利用广播进行通信
private var receiver: MyReceiver? = null
override fun onCreate() {
// 注册广播
receiver = MyReceiver()
val filter = IntentFilter()
filter.addAction(“android.intent.action.MyReceiver”)
registerReceiver(receiver, filter)
}
inner class MyReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val content = intent.getStringExtra(“content”) ?: “”
// 通过Handler更新UI
val message = Message.obtain()
message.what = 0
message.obj = content
handler.sendMessage(message)
}
}
val handler = Handler(this.mainLooper) { msg ->
tvContent.text = msg.obj as String
false
}
可以在Activity中通过广播给Service发送信息
fun sendMessage(view: View?) {
Intent(“android.intent.action.MyReceiver”).apply {
putExtra(“content”, “Hello, World!”)
sendBroadcast(this)
}
}
6. 设置权限
悬浮窗的显示需要权限,在AndroidManefest.xml中添加:
此外,还要通过Settings.ACTION_MANAGE_OVERLAY_PERMISSION来让动态设置权限,在Activity中设置。
// MainActivity.kt
fun startWindow(view: View?) {
if (!Settings.canDrawOverlays(this)) {
startActivityForResult(Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse(“package:$packageName”)), 0)
} else {
startService(Intent(this@MainActivity, FloatingWindowService::class.java))
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == 0) {
if (Settings.canDrawOverlays(this)) {
Toast.makeText(this, “悬浮窗权限授权成功”, Toast.LENGTH_SHORT).show()
startService(Intent(this@MainActivity, FloatingWindowService::class.java))
}
}
}
3.3 完整代码
class FloatingWindowService : Service() {
private lateinit var windowManager: WindowManager
private lateinit var layoutParams: WindowManager.LayoutParams
private lateinit var tvContent: AppCompatTextView
private lateinit var handler: Handler
private var receiver: MyReceiver? = null
private var floatingView: View? = null
private val stringBuilder = StringBuilder()
private var x = 0
private var y = 0
// 用来判断floatingView是否attached 到 window manager,防止二次removeView导致崩溃
private var attached = false
override fun onCreate() {
super.onCreate()
// 注册广播
receiver = MyReceiver()
val filter = IntentFilter()
filter.addAction(“android.intent.action.MyReceiver”)
registerReceiver(receiver, filter);
// 获取windowManager并设置layoutParams
windowManager = getSystemService(WINDOW_SERVICE) as WindowManager
layoutParams = WindowManager.LayoutParams().apply {
type = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
} else {
WindowManager.LayoutParams.TYPE_PHONE
}
format = PixelFormat.RGBA_8888
// format = PixelFormat.TRANSPARENT
gravity = Gravity.START or Gravity.TOP
flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
width = 600
height = 600
x = 300
y = 300
}
handler = Handler(this.mainLooper) { msg ->
tvContent.text = msg.obj as String
// 当文本超出屏幕自动滚动,保证文本处于最底部
val offset = tvContent.lineCount * tvContent.lineHeight
floatingView?.apply {
if (offset > height) {
tvContent.scrollTo(0, offset - height)
}
}
false
}
}
override fun onBind(intent: Intent?): IBinder? {
return null
}
@SuppressLint(“ClickableViewAccessibility”)
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
if (Settings.canDrawOverlays(this)) {
floatingView = LayoutInflater.from(this).inflate(R.layout.layout_show_log, null)
tvContent = floatingView!!.findViewById(R.id.tv_log)
floatingView!!.findViewById(R.id.iv_close).setOnClickListener {
stringBuilder.clear()
windowManager.removeView(floatingView)
attached = false
}
// 设置TextView滚动
tvContent.movementMethod = ScrollingMovementMethod.getInstance()
floatingView!!.findViewById(R.id.layout_drag).setOnTouchListener { v, event ->
when (event.action) {
MotionEvent.ACTION_DOWN -> {
x = event.rawX.toInt()
y = event.rawY.toInt()
}
MotionEvent.ACTION_MOVE -> {
val currentX = event.rawX.toInt()
val currentY = event.rawY.toInt()
val offsetX = currentX - x
val offsetY = currentY - y
x = currentX
y = currentY
layoutParams.x = layoutParams.x + offsetX
layoutParams.y = layoutParams.y + offsetY
windowManager.updateViewLayout(floatingView, layoutParams)
}
}
true
}
windowManager.addView(floatingView, layoutParams)
Android 悬浮窗 页面 申请 android悬浮窗开发
转载本文章为转载内容,我们尊重原作者对文章享有的著作权。如有内容错误或侵权问题,欢迎原作者联系我们进行内容更正或删除文章。
提问和评论都可以,用心的回复会被更多人看到
评论
发布评论
相关文章
-
有趣的CSS - 鼠标悬浮线条动态变化
今天分享的是一个文字按钮链接,当鼠标悬浮时,线条会发生动态变化的效果。
css html 选择器 文字按钮 -
Android 实现类似悬浮窗 android悬浮窗代码
Android 实现类似悬浮窗 android悬浮窗代码
悬浮窗 android 需求 算法 拖拽 -
悬浮窗 android studio 悬浮窗软件下载
IDM下载器能巧妙获取网页音频与视频,且下载迅速,还支持批量下载。但当下载的链接需要分别从不同的网站获取时,情况就比较麻烦了。今天小编要介绍的桌面悬浮窗功能,正是为了解决这个麻烦应运而生。一、桌面悬浮窗功能介绍桌面悬浮窗是该下载器的一大特色,别看这悬浮窗模样小巧就觉得不起眼,其实这悬浮窗是一个快捷按钮,只需要一个下载链接,就能够弹出IDM的下载界面,直接开始下载。再也不用复制粘贴那么麻烦了。
悬浮窗 android studio autojs开启悬浮窗权限 foobar2000隐藏桌面悬浮窗头像 html弹出悬浮窗口 html弹出悬浮窗口 模版 -
mysql 主建为Long比子符串效高多少
前言上一篇总结了Mysql的锁机制,通过读者的反映和阅读量显示,总体还是不错的,感兴趣的可以阅读一下[大厂面试官必问的Mysql锁机制]。写了那么多的Mysql文章,有读者问我是不是dba,工作真的需要掌握那么深吗。我想说的是:我是一名Java全职开发人员不是dba。假如你只满足于日常的crud,你可以放弃这些底层的知识,可以不必学的那么深,若是你想往高处走,这些底层的知识,是你必备的。话不多说,
mysql 联合主键 mysql 联合唯一索引 mysql创建唯一索引 分区字段必须包含在主键字段 创建了联合索引还用在单个字段上创建索引吗