Reputation: 1
I am trying to display a custom view/screen similar to WhatsApp’s incoming call popup, which appears whether the screen is locked or unlocked.
What I Tried:
Used Notification Channels, different flags, and services with a BroadcastReceiver. Implemented an overlay (SYSTEM_ALERT_WINDOW), which works fine when the screen is unlocked. It shows the notification and launches a full-screen popup.
However, when the screen is locked, I only receive the notification, but the full-screen popup does not appear.
I want to display a custom full-screen UI (like WhatsApp's call popup) even when the device screen is locked.
I also want simier functionality in iOS side, please provide me idea or code snippet for the same. Thank you.
Upvotes: 0
Views: 36
Reputation: 593
You need to use a combination of a BroadcastReceiver
, a Service
, and a WindowManager
with the appropriate flags. Here is a step-by-step guide:
class CallReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val serviceIntent = Intent(context, CallService::class.java)
context.startService(serviceIntent)
}
}
class CallService : Service() {
private lateinit var windowManager: WindowManager
private lateinit var callView: View
override fun onBind(intent: Intent?): IBinder? {
return null
}
override fun onCreate() {
super.onCreate()
windowManager = getSystemService(WINDOW_SERVICE) as WindowManager
callView = LayoutInflater.from(this).inflate(R.layout.call_layout, null)
val params = WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON or
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON,
PixelFormat.TRANSLUCENT
)
windowManager.addView(callView, params)
}
override fun onDestroy() {
super.onDestroy()
if (::callView.isInitialized) {
windowManager.removeView(callView)
}
}
}
AndroidManifest.xml
:<service android:name=".CallService" android:exported="true" />
<receiver android:name=".CallReceiver">
<intent-filter>
<action android:name="com.example.INCOMING_CALL" />
</intent-filter>
</receiver>
AndroidManifest.xml
:<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
val intent = Intent("com.example.INCOMING_CALL")
sendBroadcast(intent)
For iOS, you can use CallKit
to achieve similar functionality. Here is a basic example:
CXProvider
and configure it:import CallKit
class CallManager {
private let provider: CXProvider
init() {
let providerConfiguration = CXProviderConfiguration(localizedName: "YourApp")
providerConfiguration.supportsVideo = true
providerConfiguration.maximumCallsPerCallGroup = 1
providerConfiguration.supportedHandleTypes = [.phoneNumber]
provider = CXProvider(configuration: providerConfiguration)
provider.setDelegate(self, queue: nil)
}
func reportIncomingCall(uuid: UUID, handle: String) {
let update = CXCallUpdate()
update.remoteHandle = CXHandle(type: .phoneNumber, value: handle)
update.hasVideo = true
provider.reportNewIncomingCall(with: uuid, update: update) { error in
if let error = error {
print("Error reporting incoming call: \(error.localizedDescription)")
}
}
}
}
extension CallManager: CXProviderDelegate {
func providerDidReset(_ provider: CXProvider) {
// Handle provider reset
}
func provider(_ provider: CXProvider, perform action: CXAnswerCallAction) {
// Handle call answer
action.fulfill()
}
func provider(_ provider: CXProvider, perform action: CXEndCallAction) {
// Handle call end
action.fulfill()
}
}
CallManager
to report an incoming call:let callManager = CallManager()
let uuid = UUID()
callManager.reportIncomingCall(uuid: uuid, handle: "1234567890")
This setup will allow you to display a custom full-screen UI for incoming calls on both Android and iOS, even when the screen is locked.
Upvotes: 0