I am Attempting very simple Xcode OS X program with swift 4.0 - this program builds and runs but I'm getting errors accessing the URL video file. Probably related to privilege or security setting somewhere but can't figure out where. Here is my program under class ViewController: NSViewController:
#IBOutlet var playerView: AVPlayerView!
//var url: URL!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
// guard let url = URL(string: "https://devimages.apple.com.edgekey.net/samplecode/avfoundationMedia/AVF oundationQueuePlayer_HLS2/master.m3u8")
// else {
// return
// }
let url1 = URL(string: "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4")
let player = AVPlayer(url: url1!)
// Create a new AVPlayer and associate it with the player view
let playerView = self.playerView
playerView?.player = player
playerView?.player!.play();
}
Also I have modified the info.plist file with the following:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>NSAllowsArbitraryLoadsInWebContent</key>
<true/>
<key>NSExceptionDomains</key>
<dict/>
</dict>
I get the following runtime errors trying to access either of the URLs
above why?
2017-11-05 10:12:21.757333-0800 AVPlayer[54381:5617593] startLogging:
logging starts... 2017-11-05 10:12:21.758024-0800
AVPlayer[54381:5617612] setMessageLoggingBlock: called 2017-11-05
10:12:21.758520-0800 AVPlayer[54381:5617612] initWithSessionInfo: XPC
connection interrupted 2017-11-05 10:12:21.758842-0800
AVPlayer[54381:5617612] startConfigurationWithCompletionHandler:
Failed to get remote object proxy: Error Domain=NSCocoaErrorDomain
Code=4097 "connection to service named com.apple.rtcreportingd"
UserInfo={NSDebugDescription=connection to service named
com.apple.rtcreportingd} 2017-11-05 10:12:21.759003-0800
AVPlayer[54381:5617612] startConfigurationWithCompletionHandler:
Failed to get remote object proxy: Error Domain=NSCocoaErrorDomain
Code=4097 "connection to service named com.apple.rtcreportingd"
UserInfo={NSDebugDescription=connection to service named
com.apple.rtcreportingd} 2017-11-05 10:12:21.925221-0800
AVPlayer[54381:5617654] App Transport Security has blocked a cleartext
HTTP (http://) resource load since it is insecure. Temporary
exceptions can be configured via your app's Info.plist file.
I found your question after you commented on a question I had answered previously, so lets continue here :)
I can get your code working by combining my original answer to that question with the answer provided by #callam above so...give him the credit for the correct answer :)
To summarize, you need to:
Add a AVPlayerView to your Storyboard and connect it to your ViewController
Setup your ViewController
Manage App Transport Security and the outgoing connection.
In greater detail
1. Add a AVPlayerView to your Storyboard and connect it to your ViewController
Drag a AVKit Player View to your view in the storyboard
In your ViewController class, create an outlet for the view:
#IBOutlet weak var playerView: AVPlayerView!
And connect it.
2. Setup your ViewController
Here is my code:
import Cocoa
import AVKit
class ViewController: NSViewController {
#IBOutlet weak var playerView: AVPlayerView!
override func viewDidLoad() {
super.viewDidLoad()
let fileURL = URL(string: "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4")
let avAsset = AVURLAsset(url: fileURL!, options: nil)
let playerItem = AVPlayerItem(asset: avAsset)
let videoPlayer = AVPlayer(playerItem: playerItem)
playerView.player = videoPlayer
videoPlayer.play()
}
}
Seems familiar no :)
Notice I create the videoPlayer right here, no need to for me to use the let playerView = self.playerView you mention in your comments.
If you just do these two steps, you end up with a player view that cannot play video and errors in your console. So you need to add the final piece to the puzzle, kindly provided by #callam above.
3. Manage App Transport Security and the outgoing connection.
First, if you cannot use a HTTPS connection you must allow HTTP connections in your info.plist file.
Here is my .plist file in its entirety
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2017 :) </string>
<key>NSMainStoryboardFile</key>
<string>Main</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
</dict>
</plist>
The important part being the NSAppTransportSecurity part
And then finally, you must enable Outgoing Connections (Client) under Capabilities of your project
If I do that, I end up with this:
But notice though, that I still see errors in the console.
Hope you are able to get to the same result following these steps :)
Even if you enable arbitrary loads, attempts to connect using insecure HTTP fail.
Change the protocol in your URL to https:// or add the domain to NSExceptionDomains.
let url1 = URL(string: "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4")
https://developer.apple.com/library/content/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/uid/TP40009251-SW35
I believe the XPC error can be fixed by selecting Outgoing Connections in your App Capabilities
https://developer.apple.com/library/content/documentation/Miscellaneous/Reference/EntitlementKeyReference/Chapters/EnablingAppSandbox.html
Related
In my AppDelegate I am using a function to rotate my device and lock the orientation.
iPhone shall be portrait only, and iPad landscape only.
It works on iPhones, but the following function does never get called on iPads:
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
print("Test")
return AppDelegate.orientationLock
}
I think it was working on iPads before I switched to "SwiftUI Life Cicle" but I am not absolutely sure if this was the point of time, where it stopped working:
#UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
The info.plist is also set to "Landscape only" for iPads, but the app starts in portrait mode anyway, which is strange too:
I also faced this issue in iPad, And got solution.
In your Info.Plist make this setting.
or
In your Project > General
I had to set this key in my info.plist to false, so that application(_:supportedInterfaceOrientationsFor:) gets called on iPads:
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
</dict>
Thanks #lorem ipsum for the hint!
I have seen this application on iTunes, it is creating custom icon in iphone. In my application I also want to change icon , specifically what I want to do is in my icon there is one label and programmatically I want to change the value of label.
From the video tutorial of the app, it seems like all they're doing is they created a web page with favicon of the custom icon that you created, then the user would tap "Add To Home Screen" to add the custom web page to the home screen. That should be enough to get you going.
It is possible to change appIcon from iOS 10.3.
Swift 3:
if UIApplication.shared.supportsAlternateIcons{
UIApplication.shared.setAlternateIconName("icon2", completionHandler: { (error) in
print(error ?? "")
})
}
Objective C:
[[UIApplication sharedApplication] setAlternateIconName:#"icon2" completionHandler:^(NSError * _Nullable error) {
//NSLog(#"Error...");
}];
set supportsAlternateIcon to Yes in info.plist. Both primary and secondary icons should be added in CFBundleIcons key of your app's Info.plist file.
//Info.plist
<key>CFBundleIcons</key>
<dict>
<key>CFBundleAlternateIcons</key>
<dict>
<key>Icon1</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>icon1</string>
</array>
<key>UIPrerenderedIcon</key>
<false/>
</dict>
<key>Icon2</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>icon2</string>
</array>
</dict>
</dict>
</dict>
References:
Apple Document: setAlternateIconName(_:completionHandler:)
How to change your app icon dynamically with setAlternateIconName()
This is not possible. Unless your app is of Newsstand category. For newsstand app, change the icon using the code,
UIApplication *app = [UIApplication sharedApplication];
[app setNewsstandIconImage:newsstandImage];
Note: What #Enrico suggests is a different solution. Your app icon will still be there in home screen, a duplicate icon will be created. Which most of the users wont prefer.
Only my two cents.
Adding to plist directly is fine, the net effect is to have a "strange" value (IOS5...) in plist if seen visually in Xcode:
2) on simulator (Xcode 10 beta...) debug console on run you will see:
MobileGestalt.c:890: MGIsDeviceOneOfType is not supported on this platform.
but works
3) don't call directly in AppDelegate. if needed so, call it dispatched:
final func changeIcon(){
let name = "Icon1"
let icon = UIImage(named: name)
if UIApplication.shared.supportsAlternateIcons{
UIApplication.shared.setAlternateIconName(name, completionHandler: { (error) in
print(error ?? "ok")
})
}
}
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
let when = DispatchTime.now() + 1
DispatchQueue.main.asyncAfter(deadline: when) {
self.changeIcon()
}
return true
}
.....
4) note: icon name is the symbolic name you put in key in upper level, so for example:
<key>CFBundleIcons</key>
<dict>
<key>CFBundleAlternateIcons</key>
<dict>
<key>Icon1</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>logo2_120x120</string>
</array>
<key>UIPrerenderedIcon</key>
<false/>
</dict>
<key>Icon2</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>logo3_120x120</string>
</array>
</dict>
</dict>
</dict>
and do NOT add #2x or similar in plist.
I am trying to launch my app with a custom URL scheme. If the app is backgrounded, all is fine. If the app is not backgrounded, it launches, and the launch screen never disappears, eventually it gets killed by iOS for taking too long. I have extensively debugged this, and cannot figure out the problem. I have even removed everything from my application didFinishLauinchingWithOptions to make sure that nothing was stopping it there. This is my altered code, all I am asking is that it opens and gives me a blank window, but won't even do that. Just hangs on launch screen.
if ([launchOptions objectForKey:UIApplicationLaunchOptionsURLKey]) {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[self.window makeKeyAndVisible];
self.window.rootViewController = [[UIViewController alloc]init];
return YES;
}
URL Scheme in plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>fb23423444322</string>
<string>test</string>
</array>
</dict>
</array>
</plist>
How are you handling what happens when your application responds to the URL Scheme. You should be use this delegate method in your App Delegate:
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
// Do what you need here
return YES;
}
Check the contents of didFinishLaunchingWithOptions. The code in this method should not be commented out. Also it looks like you have a conditional in the didFinishLaunchingWithOptions method. This is most likely while the app is hanging on startup.
I need to send file from one application to another. I use UIDocumentInteractionController to copy file.
Here is my code implementing UIDocumentInterationController in my ViewController in SendingApp.
NSString *path = [[NSBundle mainBundle] pathForResource:#"1" ofType:#"zip"];
NSURL *urlPath = [NSURL fileURLWithPath:path];
self.docController = [UIDocumentInteractionController interactionControllerWithURL:urlPath];
[docController retain];
docController.delegate = self;
[docController presentOpenInMenuFromRect:self.view.frame
inView:self.view
animated:YES];
docController is property. ViewController implements UIDocumentInteractionControllerDelegate.
The ReceiverApp is set to handle the files of this extension.
My ReceiverAppInfo.plist
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>zip</string>
</array>
<key>CFBundleTypeName</key>
<string>ZIP</string>
<key>LSItemContentTypes</key>
<array>
<string>public.zip-archive</string>
<string>com.pkware.zip-archive</string>
</array>
<key>LSHandlerRank</key>
<string>Alternate</string>
</dict>
</array>
In ReceiverAppDelegate I use
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
to handle opening of receiving file.
So problem is that this code works just perfect on iOS 5.1 BUT it doesn't work on iOS 6. UIDocumentInteractionController OpenIn menu appears and shows my ReceiverApp but it doesn't do anything if you select the app. I looked in Console and found out that iPhone Simulator 6.1 tries to copy file to one directory while Simulator 5.1 copies to another.
iPhoneSimulator 6.1
com.apple.mdt[2342]:
Copy ~/Library/Application Support/iPhone Simulator/6.1/Applications/367D395F-DC8B-4F4C-83C7-B22992E34C64/sendingZIP.app/1.zip ->
/var/mobile/Library/Application Support/Containers/-23.ReceiveApp/Documents/Inbox
iPhoneSimulator 5.1
com.apple.mdt[2439]:
Copy ~/Library/Application Support/iPhone Simulator/5.1/Applications/0DE1852A-F803-4583-87BC-8F1EBBE362A4/sendingZIP.app/1.zip ->
~/Library/Application Support/iPhone Simulator/5.1/Applications/927E310A-2766-4709-81CB-0E759F24236D/Documents/Inbox
Has anybody such problem? Does anybody know what to do?
Notice that the only discernible API difference is
Managing Actions
– documentInteractionController:canPerformAction: Deprecated in iOS 6.0
– documentInteractionController:performAction: Deprecated in iOS 6.0
Are you still implementing these methods? Maybe they are responsible for the unexpected results.
I'm just getting into iOS development, but something I'm going to have to do early on is add a button to the system menus like how Dropbox has added its button when interacting with email attachments.
This application will be for video so adding a button on the share menu for quicktime players would be ideal.
I've scoured the documentation and have only found the UIMenuItem class. Is this what I want or is there another way to implement this functionality?
Set project-info.plist -> add new item (UTExportedTypeDeclarations)
<key>UTExportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>com.apple.quicktime-movie</string>
</array>
<key>UTTypeIdentifier</key>
<string>com.company.project</string>
<key>UTTypeTagSpecification</key>
<dict/>
</dict>
</array>
Coding your ButtonClick event in .m file
-(IBAction)actionClick:(id)sender{
UIDocumentInteractionController *documentController =
[UIDocumentInteractionController interactionControllerWithURL:
[NSURL fileURLWithPath:MOVIE_FILE_PATH]];
documentController.delegate = self;
documentController.UTI = #"com.apple.quicktime-movie";
[documentController presentOpenInMenuFromRect:CGRectZero
inView:self.view
animated:YES];
}