I have successfully recorded and played the voice for the local notification sound and it also get played on calling that function.
But problem is when i give sound's link to the notification sound property, it do not work.
notification.sound = UNNotificationSound.init(named: "martian-gun copy.m4a")
Above code works perfectly. But when i gave it URL(in the form of string) it do not play the exact sound.
Code not working is follows:
let fm = FileManager.default
let docsurl = try! fm.url(for:.documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
let myurl = docsurl.appendingPathComponent("sound.m4a")
notification.sound = UNNotificationSound.init(named: myurl)
myurl have same path at which voice play on playButton.
Finally question is how to set notification custom sound from the sound URL?
According to the document of UNNotificationSound, you need to place a copy of your audio file in the Library/Sounds folder of your app’s container directory.
let docsurl = try FileManager.default.url(for:.documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
let myurl = docsurl.appendingPathComponent("sound.m4a")
let filename = myurl.lastPathComponent
let targetURL = try FileManager.default.soundsLibraryURL(for: filename)
// copy audio file to /Library/Sounds
if !FileManager.default.fileExists(atPath: targetURL.path) {
try FileManager.default.copyItem(at: sourceURL, to: targetURL)
}
let content = UNMutableNotificationContent()
content.sound = UNNotificationSound(named: UNNotificationSoundName(filename))
extension FileManager {
func soundsLibraryURL(for filename: String) throws -> URL {
let libraryURL = try url(for: .libraryDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
let soundFolderURL = libraryURL.appendingPathComponent("Sounds", isDirectory: true)
if !fileExists(atPath: soundFolderURL.path) {
try createDirectory(at: soundFolderURL, withIntermediateDirectories: true)
}
return soundFolderURL.appendingPathComponent(filename, isDirectory: false)
}
}
Related
This portion of the code is supposed to download a txt file from a website. By running this code it is able to successfully download the file from the website and place it into the app's Documents directory. I am able to see where the file is stored because in the last couple of lines in the code it prints out the location of the file. However, I am not able to get the file name that was recently downloaded. The goal is for me to try to get the name of the file so that I can be able to open it and read from it. What are my options in approaching this? What am I missing in this block of code that is preventing me from getting the name of the file that was recently downloaded?
guard let url1 = URL(string: website) else { return }
//This portion of the code focuses on creating a download task with a completion handler
//Completion handler moves the downloaded file to the app's directory
let downloadTask = URLSession.shared.downloadTask(with: url1) {
urlOrNil, responseOrNil, errorOrNil in
// check for and handle errors:
// * errorOrNil should be nil
// * responseOrNil should be an HTTPURLResponse with statusCode in 200..<299
guard let fileURL = urlOrNil else { return }
do {
let documentsURL = try
FileManager.default.url(for: .documentDirectory,
in: .userDomainMask,
appropriateFor: nil,
create: false)
let savedURL = documentsURL.appendingPathComponent(
fileURL.lastPathComponent)
try FileManager.default.moveItem(at: fileURL, to: savedURL)
} catch {
print ("file error: \(error)")
}
}
downloadTask.resume()
//If you want to receive progress updates as the download proceeds, you must use a delegate.
var urlSession = URLSession(configuration: .default, delegate: self as? URLSessionDelegate, delegateQueue: nil)
func startDownload(url1: URL) -> String? {
let downloadTask = urlSession.downloadTask(with: url1)
let fname = downloadTask.response?.suggestedFilename
downloadTask.resume()
return fname
//self.downloadTask = downloadTask
}
let name = startDownload(url1: url1)
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true) as NSArray
let documentsDir = paths.firstObject as! String
print("Path to the Documents directory\n\(documentsDir)")
You can get the name of the file at a given path by initialising a URL object from the path:
let name = URL(fileURLWithPath: yourPath).lastPathComponent
This returns an optional string. The name will be automatically unescaped, so it will be human-readable (no percent encoding).
The filename should be available to you from your fileURL variable, as this is where you got the filename in order to save it:
let name = fileURL.lastPathComponent
I have attempted to export videos from Photo Library, but the export callback is never executed. I periodically check the progress of the export, and the progress is always zero.
The code below works in 99.9% cases, but sometimes on some devices (absolutely randomly) it stops working and only restart of the iPhone helps.
AVAssetExportSession.Status always in waiting state
class FilesInteractor {
static func tempDirectoryPath() -> String {
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString
return documentsPath.appendingPathComponent("temp") as String
}
static func createTempDirectory() {
if !FileManager.default.fileExists(atPath: tempDirectoryPath()) {
try? FileManager.default.createDirectory(atPath: tempDirectoryPath(), withIntermediateDirectories: true, attributes: nil)
}
}
static func testVideoURL(name: String, ext: String = "mov") -> URL {
createTempDirectory()
let outputURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0].appendingPathComponent("test").appendingPathComponent("\(name).\(ext)", isDirectory: false)
log.debug("Test video URL: \(outputURL)")
return outputURL
}
}
import AVFoundation
let asset = AVAsset()
let outputURL = FilesInteractor.testVideoURL("output")
let exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPreset1280x720)
exportSession?.outputFileType = .mov
exportSession?.outputURL = outputURL
try? FileManager.default.removeItem(at: outputURL)
exportSession?.exportAsynchronously(completionHandler: {
print("sometimes never calls")
})
Other video apps also freeze (Filto, Videoleap):
I saw this issue a couple of times on some Github projects and usually it had something to do with how the URL was created. Not sure if the code you put in your question was just some placeholder but I think you should create a fileURL like this instead of "string".
var tempFileUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0].appendingPathComponent("temp_video_data.mp4", isDirectory: false)
tempFileUrl = URL(fileURLWithPath: tempFileUrl.path)
exportSession.outputURL = tempFileUrl
Perhaps this will fix it?
I am using AVPlayer to play a video with the localPath URL but it is not playing on AVPlayer.
And i am getting localPath with this code:
var selectedAssets = [TLPHAsset]()
for abcd in self.selectedAssets {
let asset = abcd
if asset.type == .video {
//------------- Video Path --------------------//
let fm = FileManager.default
let docsurl = try! fm.url(for:.documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
let url = docsurl.appendingPathComponent(stringUrl!)
}
}
here is the path:-
file:///var/mobile/Containers/Data/Application/915BA33E-5DB9-42C4-B5CD-3898D81FBDC5/Documents/77666c29-75a3-4d89-aecf-15d0f47fbe83.mp4
let video = dbImageDataModel[indexPath.row].fileUrl
print(video)
playerView = AVPlayer(url: URL(fileURLWithPath: video))
playerViewController.player = playerView
self.present(playerViewController, animated: true, completion: {
self.playerViewController.player!.play()
})
You are using the wrong API.
absoluteString returns the URL string including the file:// scheme. To create a new URL you have to use URL(string rather than URL(fileURLWithPath.
To clarify
absoluteString returns file:///var/mobile/Containers/Data/Application.... To create an URL use URL(string:
path returns /var/mobile/Containers/Data/Application.... To create an URL use URL(fileURLWithPath:
I am trying to download one text file from the server and I have completed it.
Also, I have stored that file but it seems like it stores at some private location and not able to access that file from other file explorer.
Heres the code for it:
let documentsUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first
// let destinationUrl = documentsUrl!.appendingPathComponent("10xFile.pdf")
let fileManager = FileManager.default
do {
let documentDirectory = try fileManager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor:nil, create:false)
let fileURL = documentDirectory.appendingPathComponent("10xFile.pdf")
let dataFromURL = NSData(contentsOf: location)
dataFromURL?.write(to: fileURL as! URL, atomically: true)
} catch {
print(error)
}
But I need to access this file very easily by any other file explore.
Thanks in advance
Actually as I commented - the feature of iOS - every app has completely separated filesystem sandbox, and one app can't access files of any another app without special permission created by another app.
But you can use UIActivityViewController to pass your pdf files to another app that can render your pdfs.
You can launch UIActivityViewController and pass your pdf file to it. In UIActivityViewController you can choose options - copy file or open in any of apps that can handle pdf file, for example FileManager app.
Here is the code sample somewhere based on code you provided in question, I created UIButton and added IBAction for it - UIActivityViewController is presented when user tap button.
override func viewDidLoad() {
super.viewDidLoad()
do {
let documentDirectory = getDocumentsDirectory()
let fileURL = documentDirectory.appendingPathComponent("10xFile.pdf")
let dataFromURL = try Data(contentsOf: location!)
try dataFromURL.write(to: fileURL, options: [])
} catch {
print(error)
}
}
func getDocumentsDirectory() -> URL {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let documentsDirectory = paths[0]
return documentsDirectory
}
#IBAction func actionButtonPressed(_ sender: Any) {
let documentsDir = getDocumentsDirectory()
let fileURL = documentsDir.appendingPathComponent("10xFile.pdf")
let ac = UIActivityViewController(activityItems: [fileURL], applicationActivities: nil)
self.present(ac, animated: true)
}
I am having problem with download pdf, saving to document directory and loading it in web view.
I have no experience with download things, saving things to directories and UIWebView before.
Before I ask this question, I've search multiple StackOverflow question and tried my best but it still doesn't work.
First This is how I download the PDF from url and save it to document directory
let myURL = URL(string: "https://example/example/product.pdf")
let urlRequest = NSURLRequest(url: myURL!)
do {
let theData = try NSURLConnection.sendSynchronousRequest(urlRequest as URLRequest, returning: nil)
var docURL = (FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)).last as? NSURL
docURL = docURL?.appendingPathComponent("my.pdf") as NSURL?
try theData.write(to: docURL as! URL)
print("downloaded")
} catch (let writeError) {
print("error : \(writeError)")
}
The application pauses for a while and prints "downloaded"
This is how I check the list of contacts in my document directory
let docURL = (FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last)
do{
let contents = try (FileManager.default.contentsOfDirectory(at: docURL!, includingPropertiesForKeys: nil, options: FileManager.DirectoryEnumerationOptions.skipsHiddenFiles))
print("There are")
print(contents)
}
catch (let error)
{
print("error contents \(error)")
}
It prints "There are [file:///private/var/mobile/Containers/Data/Application/DF6A310C-EB7E-405E-9B1B-654486B5D03A/Documents/my.pdf]"
This is how I load the pdf into webView
var webView = UIWebView(frame : vc.view.frame)
webView.scalesPageToFit = true
var paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
var documentsDirectory = paths[0]
var filePath = URL(fileURLWithPath: documentsDirectory).appendingPathComponent("my.pdf").absoluteString
var targetURL = URL(fileURLWithPath: filePath)
var request = URLRequest(url: targetURL)
webView.loadRequest(request)
vc.view.addSubview(webView)
The WebView comes up but shows nothing. I'm really confused if my.pdf is really saved with readable PDF format.
I don't know if there are some stuffs like I have to add something in info.plist or enable something in app capabilities. Thank you very much.
I didn't look through all of the code but the following two lines are a problem:
var filePath = URL(fileURLWithPath: documentsDirectory).appendingPathComponent("my.pdf").absoluteString
var targetURL = URL(fileURLWithPath: filePath)
The value of URL absoluteString does not give you a file path so the value of filePath is not a valid value for the URL fileURLWithPath: initializer.
And what's the point of going from URL to String (as a path) and back to a URL? Simply combine those two lines into:
var targetURL = URL(fileURLWithPath: documentsDirectory).appendingPathComponent("my.pdf")
As a side note, use some consistency. In other code you get the Documents folder URL using:
let docURL = (FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last)
and in other code you use:
var paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
var documentsDirectory = paths[0]
var ... = URL(fileURLWithPath: documentsDirectory)...
Pick one approach and use it consistently. Since you need a URL, use the first approach. This means the code I suggested should now be:
let docURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last!
let targetURL = docURL.appendingPathComponent("my.pdf")