I am trying to test my app clip's url handler by running the app clip from Xcode. However the URL method handler (SceneDelegate's continue method) never gets called, contrary to Apple's documentation documentation, which states:
For a UIKit-based app clip and full app that support scene-based app
life-cycle events, implement the callbacks defined in UISceneDelegate.
For example, implement scene(_:continue:) callback to access the user
activity object.
For a UIKit-based app clip and full app that respond
to app-based life-cycle events, implement the callbacks defined in
UIApplicationDelegate. Be sure to implement the
application(:continue:restorationHandler:) callback, because you
don’t have access to the NSUserActivity object in
application(:didFinishLaunchingWithOptions:).
The app delegate does not implement the application(_:continue:restorationHandler:) method
The app clip's scheme has the _XCApplClipURL parameter enabled and set to https://fruits.com/check?fruit_name=bananas
The app clip's Associated Domain lists appclips:fruits.com
The app clip's SceneDelegate is as follows
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
// UGHH!!! Never gets called
print("AppClip invocation url is : \(incomingURL)")
}
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// OK!! This gets called
guard let _ = (scene as? UIWindowScene) else { return }
}
}
I have been banging my head on the walls for the last 2 days. What am I missing?
Note: I am using this sample app available in github, just modified the signing configuration to get the app clip to compile & run.
The continue method mentioned is only called when your app is invoked after it was previously opened. In order to get the value set in _XCApplClipURL the first time your app is launched, you need to use the second method you mentioned (scene willConnectTo session).
You can try something like this:
if let activity = connectionOptions.userActivities.filter({ $0.activityType == NSUserActivityTypeBrowsingWeb }).first {
if let url = activity.webpageURL {
print("incoming URL: \(url)")
}
}
Thanks for your using AppsFlyer's public demo of App Clip and for highlighting this issue. I really appreciate it.
I can confirm you were doing great, this functionality was broken sometime after Beta 5.
Please follow and comment on this issue here
Related
I am implemeting Picture-in-picture on iOS. I added the background mode capability. When I call isPictureInPicturePossible, it returns false with error:
pictureInPictureController failedToStartPictureInPictureWithError Error Domain=AVKitErrorDomain Code=-1001 "Failed to start picture in picture." UserInfo={NSLocalizedDescription=Failed to start picture in picture., NSLocalizedFailureReason=The UIScene for the content source has an activation state other than UISceneActivationStateForegroundActive, which is not allowed.}
But I when I log the activationState, I can see that it is actually foregroundActive. Any idea what could be the reason?
(before that isPictureInPictureActive returns true, isPictureInPictureSuspended returns false, isPictureInPictureActive returns false.)
It is a little difficult to give an opinion without access to the code and without knowing the versions.
My suggestions:
Check if the app is really in the foreground. You can verify this by looking at the activationState of the UIScene for the content source. If it's not foregroundActive, you can't start the image in the image. If you are using a UISceneDelegate, you can check the activation state of the scene in the sceneWillEnterForeground: method. If using an AppDelegate, you can check the activation state of the scene in the applicationDidBecomeActive: method.
If you use using a UISceneDelegate instead of a AppDelegate. Change it to AppDelegate.
Set the sceneActivationState to foregroundActive in the AppDelegate.swift file:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
if #available(iOS 13.0, *) {
let scene = UIApplication.shared.connectedScenes.first
if let sceneDelegate = scene?.delegate as? SceneDelegate {
sceneDelegate.window?.windowScene?.activationState = .foregroundActive
}
}
return true
}
If no option to validate. We will give you more information about the problem.
Assumptions
I'm using SFSafari with Swift, but I'm having issues with typing on a third-party keyboard, so I'd like to use a standard (hardened) keyboard.
Addendum 1: After clearing the cache of Safari, it is fixed only at the next startup, but it can not be done to clear the cache. .. ..
Addendum 2: Opening another application with the keyboard that does not move open, and returning again, it was possible to input. What's going on inside ... Can this event happen intentionally?
The problem you are having
What I want to do is the same as 【Swift】 カスタムキーボードを無効化する,
It seems that App Delegate cannot be used on iOS 13 or later, so I wrote it like Scene Delegate, but no error occurs, but even if you execute it, a frozen keyboard of a third party appears.
Applicable source code
Code on the site
func application (_ application: UIApplication, shouldAllowExtensionPointIdentifier extensionPointIdentifier: UIApplicationExtensionPointIdentifier)-> Bool (
if extensionPointIdentifier == .keyboard {
return false
}
return true
}
Code rewritten in Scenne Delegate
func scene (_ scene: UIScene, willConnectTo session: UISceneSession, options a: UIApplication.ExtensionPointIdentifier)-> Bool (
if a == .keyboard {
return false
}
return true
}
What I tried
AppDelegate is executed by looking at here.
(Deleted the Scene Delegate) => It stopped working normally due to blackout.
There were several different ways to write the contents of scene () without error, so I tried it.
Additional information (FW / tool version, etc.)
XCode11.4.1
Basically I was able to do this. But I didn't know how to mess with the keyboard with SFSafariViewController, so I used WKWebView. (I used SFSafari because I had a bug and couldn't use it before.)
you should change the line breaks a little.
I have implemented the CallKit for my App to trigger/receive both Audio and Video Call within our App by using WebRTC. Which is working seamlessly without any problem.
As I see there are 3 ways to trigger a call from Call Kit.
Performing an interaction within the app
Opening a link with a supported custom URL scheme
Initiating a VoIP call using Siri
As of now, I don't have any requirement to initiate the call using Siri but we need to initiate the call when the user clicks on any cell in the native iOS Recent calls screen which then routes to our application and triggers the out going call.
And also our app contains few metadata when user calls the other user such as receiverID etc.. So when the user misses the call from the other user, I need to store this meta data and I need to trigger a call when user clicks on missed call list of iOS Recent call screen using all those metadata.
I was going through the Sample App for CallKit "Speakerbox" provided by Apple. And I found that they are using custom URL scheme just like what we use for DeepLinking of iOS apps.
So I need few suggestion whether this can be achieved using URL scheme and If so, How can I store the metadata ( custom object ) in CXHandle object.
Pasting the same answer here from me: Refer
Verify the remoteHandle and supportedHandleTypes, both should be similar as per your requirement.
callUpdate.remoteHandle = [[CXHandle alloc] initWithType:CXHandleTypeGeneric value:[NSString stringWithFormat:#"%#", phoneno]];
configuration.supportedHandleTypes = [NSSet setWithObjects:[NSNumber numberWithInteger:CXHandleTypeGeneric],[NSNumber numberWithInteger:CXHandleTypePhoneNumber], nil];
If the handles mismatches, you can't able to process the NSUserActivity.
Implement this method to get callback,
- (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull NSUserActivity *)userActivity restorationHandler:(nonnull void (^)(NSArray * _Nullable))restorationHandler {}
for Swift 5 you should define continueuserActivity function to SceneDelegate.swift like below
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
let interaction = userActivity.interaction
if let startAudioCallIntent = interaction?.intent as? INStartAudioCallIntent{
let contact = startAudioCallIntent.contacts?.first
let contactHandle = contact?.personHandle
if let phoneNumber = contactHandle?.value {
print(phoneNumber)
// Your call logic
}
}
return
}
please refer this answer
I am trying to integrate the Quickblox Webrtc Video Calling feature into a iOS Swift App. However, i'm having a lot of trouble with their SDK & api documentation, and it seems they don't have a tech team to help people with questions about their platforms, so maybe we can all help each other, so here are a few questions that I've noticed a lot of people have been asking on both StackOverFlow and Github regarding their webrtc SDK. Please restrict answers to the Swift language. The docs link is
http://quickblox.com/developers/SimpleSample-videochat-ios
My code so far:
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
//Firebase config
FIRApp.configure()
//Quickblox config
QBSettings.setApplicationID(xxxxx)
QBSettings.setAuthKey("xxxxxxxxxxx")
QBSettings.setAuthSecret("xxxxxxxx-xxxx")
QBSettings.setAccountKey("xxxxxxxxxxxxxxxxxxxx")
return true
}
Thats my appdelegate.swift now for the part that giving me problems the actual videochatviewcontroller. The documentation is very vague at the start all is says is:
// Initialize QuickbloxWebRTC and configure signaling
// You should call this method before any interact with
QuickbloxWebRTC QBRTCClient.initializeRTC() // Call this method when
you finish your work with QuickbloxWebRTC
QBRTCClient.deinitializeRTC()
I do not know if I am to call this in my appdelegate.swift or if I should call this in VideoChatViewController's viewDidLoad method or should I create a new method altogether?
Secondly,the docs say to CALL USERS use this method, but its not a method, just random variables, also it doesn't tell tell whether it goes to the viewDidLoad or to a newly created method :
QBRTCClient.instance().addDelegate(self) // self class must conform to QBRTCClientDelegate protocol
// 2123, 2123, 3122 - opponent's
let opponentsIDs = [3245, 2123, 3122]
let newSession = QBRTCClient.instance().createNewSessionWithOpponents(opponentsIDs, withConferenceType: QBRTCConferenceType.Video)
// userInfo - the custom user information dictionary for the call. May be nil.
let userInfo :[String:String] = ["key":"value"]
newSession.startCall(userInfo)
Next, they are vague regarding the method to receive a new session, below they refer to self.session which they never explain where this variable is from or what it consist of
func didReceiveNewSession(session: QBRTCSession!, userInfo: [NSObject : AnyObject]!) {
if self.session != nil {
// we already have a video/audio call session, so we reject another one
// userInfo - the custom user information dictionary for the call from caller. May be nil.
let userInfo :[String:String] = ["key":"value"]
session.rejectCall(userInfo)
}
else {
self.session = session
}
}
Does quickblox require authenticated Quickblox users to use their webrtc or can I Authenticate users with Firebase or parse?
Where do I use QBRTCConfig in the appdelegate or the viewDidLoad? I have tried both and have seen it used in both methods.
In one of my app it has a feature of playing sound that I achieved successfully. Even though when app is running (foreground state) and we received the incoming call, app music gets stopped and resume again when call gets disconnected.
Now real problem is here. When app enters in the background state, we are not receiving any event for incoming/outgoing call. In the background mode If music is playing inside my app and we get any incoming call, then app music is stopped automatically but not resume again when call disconnected unlike iPhone Music app.
Is it a limitation of the iOS or can we achieve that ?
Note: I'm not looking for any solution for Jailbreak devices or Enterprise apps
Have you tried to create call center and assign handler block in AppDelegate class? The following has to work.
import UIKit
import CoreLocation
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
let callCenter: CTCallCenter = CTCallCenter()
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
window = UIWindow(frame: UIScreen.mainScreen().bounds)
window?.rootViewController = ViewController()
window?.makeKeyAndVisible()
callCenter.callEventHandler = {
(call: CTCall!) in
switch call.callState {
case CTCallStateConnected:
print("CTCallStateConnected")
case CTCallStateDisconnected:
print("CTCallStateDisconnected")
case CTCallStateIncoming:
print("CTCallStateIncoming")
default:
print("default")
}
}
return true
}
}
Do not forget to switch on Background Modes for this. And perform something in the background as well, smth like receiving location.