Skip to content

How to launch new Activity from FrameLayout #2

Description

@AlexUser97

I try to study overlay library for kotlin applications https://github.com/KoderLabs/overlay-service. Right now I have a problem related with opening a new activity from a button which is located inside a FrameLayout class.
So, the task is push on button on Main Activity -> open new overlay small window and roll up Main Activity -> push on button inside a small window -> open new Activity.
In this code nothing happens after the clicking on button.
The project include main 3 classes:

  1. MainActivity

class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    btn_simple_pip.setOnClickListener {
        checkDrawOverlayPermission(IMPLEMENTED_PIP_OVERLAY_REQUEST_CODE)
        finishAffinity()
    }

}

private fun checkDrawOverlayPermission(code: Int) {
    if (Build.VERSION.SDK_INT >= 23) {
        if (!Settings.canDrawOverlays(this)) {
            val intent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:$packageName"))
            startActivityForResult(intent, IMPLEMENTED_PIP_OVERLAY_REQUEST_CODE)
        } else {
            openFloatingWindow(code)
        }
    } else {
        openFloatingWindow(code)
    }
}

private fun openFloatingWindow(code: Int) {
    when (code) {
        IMPLEMENTED_PIP_OVERLAY_REQUEST_CODE -> {
            val intent = Intent(this, ImplementPipOverlayService::class.java)
            val videoUrl =
                "https://s3.amazonaws.com/data.development.momentpin.com/2019/7/3/1562152168485485-0661a550-9d83-11e9-9028-d7af09cf782e.mp4"
            val notificationTitle = "Pip Overlay"
            val notificationDescription = "Pip overlay description"
            val notificationIcon = R.drawable.ic_launcher_foreground
            val closeBtnColor = android.R.color.black
            val closeBtnBgColor = android.R.color.transparent
            intent.putExtra(ImplementPipOverlayService.KEY_STRING_VIDEO_URL, videoUrl)
            intent.putExtra(ImplementPipOverlayService.KEY_STRING_NOTIFICATION_DESCRIPTION, notificationDescription)
            intent.putExtra(ImplementPipOverlayService.KEY_STRING_NOTIFICATION_TITLE, notificationTitle)
            intent.putExtra(ImplementPipOverlayService.KEY_INT_NOTIFICATION_ICON, notificationIcon)
            intent.putExtra(ImplementPipOverlayService.KEY_INT_CLOSE_BUTTON_COLOR, closeBtnColor)
            intent.putExtra(ImplementPipOverlayService.KEY_INT_CLOSE_BUTTON_BG_COLOR, closeBtnBgColor)
            ContextCompat.startForegroundService(this, intent)
        }
    }
}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    when (requestCode) {
        IMPLEMENTED_PIP_OVERLAY_REQUEST_CODE, RESIZEABLE_CUSTOM_WEB_OVERLAY_REQUEST_CODE,
        PIP_OVERLAY_REQUEST_CODE, RESIZEABLE_CUSTOM_VIDEO_OVERLAY_REQUEST_CODE -> {
            if (Build.VERSION.SDK_INT >= 23) {
                if (Settings.canDrawOverlays(this)) {
                    openFloatingWindow(requestCode)
                }
            } else {
                openFloatingWindow(requestCode)
            }
        }
    }
    super.onActivityResult(requestCode, resultCode, data)
}

companion object {
    const val IMPLEMENTED_PIP_OVERLAY_REQUEST_CODE = 251
    const val PIP_OVERLAY_REQUEST_CODE = 252
    const val RESIZEABLE_CUSTOM_VIDEO_OVERLAY_REQUEST_CODE = 253
    const val RESIZEABLE_CUSTOM_WEB_OVERLAY_REQUEST_CODE = 254
}
  1. ImplementPipOverlayService

    class ImplementPipOverlayService : PipOverlayService() {
    
    var videoUrl: String? = null
    var notificationTitle: String? = null
    var notificationDescription: String? = null
    var notificationIcon: Int? = null
    var closeButtonColor: Int? = null
    var closeButtonBg: Int? = null
    
    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        videoUrl = intent?.getStringExtra(KEY_STRING_VIDEO_URL)
        notificationTitle = intent?.getStringExtra(KEY_STRING_NOTIFICATION_TITLE)
        notificationDescription = intent?.getStringExtra(KEY_STRING_NOTIFICATION_DESCRIPTION)
        notificationIcon = intent?.getIntExtra(KEY_INT_NOTIFICATION_ICON, -1)
        closeButtonColor = intent?.getIntExtra(KEY_INT_CLOSE_BUTTON_COLOR, -1)
        closeButtonBg = intent?.getIntExtra(KEY_INT_CLOSE_BUTTON_BG_COLOR, -1)
        return super.onStartCommand(intent, flags, startId)
    }
    
    override fun getForegroundNotification(): Notification {
        val channelId =
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                    createNotificationChannel("my_service", "My Background Service")
                } else {
                    packageName
                }
        var notificationBuilder = NotificationCompat.Builder(this, channelId)
    
        notificationBuilder = notificationTitle?.let {
            notificationBuilder.setContentTitle(it)
        } ?: run {
            notificationBuilder.setContentTitle("Title")
        }
        notificationDescription?.let {
            notificationBuilder = notificationBuilder.setContentText(it)
        }
        notificationIcon?.let {
            notificationBuilder = notificationBuilder.setSmallIcon(it)
        }
    
        val notification: Notification = notificationBuilder.build()
        return notification
    }
    
    @RequiresApi(Build.VERSION_CODES.O)
    private fun createNotificationChannel(channelId: String, channelName: String): String {
        val chan = NotificationChannel(channelId,
                channelName, NotificationManager.IMPORTANCE_NONE)
        chan.lightColor = Color.BLUE
        chan.lockscreenVisibility = Notification.VISIBILITY_PRIVATE
        val service = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        service.createNotificationChannel(chan)
        return channelId
    }
    
    override fun getInitialWindowSize(): Point {
        return Point(100.toDp(), 100.toDp())
    }
    
    override fun getCustomLayoutId(): Int {
        return R.layout.pip_layout
    }
    
    override fun onServiceRun() {
        setOnEventListener(onFullscreen = {
            // Not implemented
        }, onClosed = {
            // Not implemented
        })
    
        pipView.removeFullscreenButton()
    
        closeButtonColor?.let {
            pipView.getCloseButton().setColorFilter(it)
        }
    
        closeButtonBg?.let {
            pipView.getCloseButton().setBackgroundColor(it)
        }
        
    }
    
    
    companion object {
        const val KEY_STRING_VIDEO_URL = "video_url"
        const val KEY_INT_CLOSE_BUTTON_COLOR = "close_button_color"
        const val KEY_INT_CLOSE_BUTTON_BG_COLOR = "close_button_background"
        const val KEY_STRING_NOTIFICATION_TITLE = "notification_title"
        const val KEY_STRING_NOTIFICATION_DESCRIPTION = "notification_description"
        const val KEY_INT_NOTIFICATION_ICON = "notification_icon"
    }
    
  2. OverlayPipCustomView

class OverlayPipCustomView : FrameLayout {
private lateinit var constraintsRoot: ConstraintLayout
private lateinit var imageFullscreenButton: ImageView
private lateinit var imageCloseButton: ImageView
private lateinit var customLayoutContent: FrameLayout
private lateinit var customView: View
private lateinit var touchView: View
private lateinit var button: Button

private var playerViewSize: Int = 0
private var sizeChangeable: Boolean = true
private var playerType: Int = 0

private var haveFullscreen = true
/**
 * Tracks if viewResizeable is fullscreen.
 */
private var fullscreenOn: Boolean = false
val isDraggable: Boolean
    get() {
        return !fullscreenOn
    }

private var onFullscreen: () -> Unit = {}
private var onClosed: () -> Unit = {}

private var canHideActionButtons = true
private val hideActionHandler = Handler()
private val HIDE_ACTION_DURATION = 2000L
private val hideActionRunnable = Runnable {
    if (!isMoving) {
        hideActions()
    }
}

var isMoving: Boolean = false

constructor(ctx: Context) : super(ctx) {
    inflate(context, R.layout.layout_pip_custom_view, this)
    initView()
}

constructor(ctx: Context, attrs: AttributeSet) : super(ctx, attrs) {
    setAttributes(attrs)
    inflate(context, R.layout.layout_pip_custom_view, this)
    initView()
}

constructor(ctx: Context, attrs: AttributeSet, defStyle: Int) : super(ctx, attrs, defStyle) {
    setAttributes(attrs)
    inflate(context, R.layout.layout_pip_custom_view, this)
    initView()
}

private fun setAttributes(attrs: AttributeSet) {
    context.theme.obtainStyledAttributes(
            attrs,
            R.styleable.OverlayCustomView,
            0, 0).apply {
        try {
            playerViewSize = getInteger(R.styleable.OverlayCustomView_ov_player_size, 0)
            playerType = getInteger(R.styleable.OverlayCustomView_ov_size_changeable, 0)
            sizeChangeable = getBoolean(R.styleable.OverlayCustomView_ov_size_changeable, true)
        } finally {
            recycle()
        }
    }

    doOnLayout {
        startHideAction()
    }
}

private fun initView() {
    button = findViewById(R.id.button)
    constraintsRoot = findViewById(R.id.constraints_root)
    imageFullscreenButton = findViewById(R.id.image_screen_action)
    imageCloseButton = findViewById(R.id.image_close)
    customLayoutContent = findViewById(R.id.custom_view)
    touchView = findViewById(R.id.touch_view)

    setListeners()
}

fun addCustomView(view: View) {
    customLayoutContent.addView(view)
}

fun addCustomView(layoutId: Int) {
    customView = inflate(context, layoutId, null)
    customLayoutContent.addView(customView)
}

fun getCloseButton() = imageCloseButton
fun getConstraintsRoot() = constraintsRoot
fun getCustomLayoutContent() = customLayoutContent
fun getCustomView() = customView
fun getFullscreenButton() = imageFullscreenButton
fun getTouchView() = touchView

fun removeFullscreenButton() {
    haveFullscreen = false
    imageFullscreenButton.invisible()
}


private fun setListeners() {
    imageFullscreenButton.setOnClickListener {
        onFullscreen.invoke()
    }

    button.setOnClickListener{
        println("pressed")
        fun alert(context: Context, text: String) {
            val intent = Intent(context, MainActivity2::class.java)
            intent.putExtra("text", text)
            context.startActivity(intent)
        }
    }


    imageCloseButton.setOnClickListener {
        onClosed.invoke()
    }
}

fun setOnEventActionListener(
        onFullscreen: () -> Unit,
        onClosed: () -> Unit
) {
    this.onFullscreen = onFullscreen
    this.onClosed = onClosed
}

private fun startHideAction() {
    if (canHideActionButtons) {
        hideActionHandler.postDelayed(hideActionRunnable, HIDE_ACTION_DURATION)
    }
}

fun restartHideAction() {
    hideActionHandler.removeCallbacks(hideActionRunnable)
    if (canHideActionButtons) {
        hideActionHandler.postDelayed(hideActionRunnable, HIDE_ACTION_DURATION)
    }
}

fun hideActions() {
    if (canHideActionButtons) {
        imageCloseButton.invisible()
        if (haveFullscreen) {
            imageFullscreenButton.invisible()
        }
    }
}

fun showActions() {
    imageCloseButton.visible()
    if (haveFullscreen) {
        imageFullscreenButton.visible()
    }
}

}

In third class I can't understand what should be placed here to to change initial first Activity to another one

    button.setOnClickListener{
        println("pressed")
        fun alert(context: Context, text: String) {
            val intent = Intent(context, MainActivity2::class.java)
            intent.putExtra("text", text)
            context.startActivity(intent)
        }
    }

enter image description here

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions