How to Upload Image file into dropbox? - ios

I want to select image into gallery and that image i want to upload in dropbox.How can i do this?
i tried dropbox SDK but i do not know how to upload selected image
- (void)uploadFile:(NSString*)filename toPath:(NSString*)path fromPath:(NSString *)sourcePath
this method is defined in DBRestClient.h,a library file from the DropBox SDK for iOS. But as from the above declaration of the method, the "fromPath" of the image which is present in the UIImageView needs to be ascertained to upload it to my account on dropbox. Can you please help me in how to determine the path, or for that matter, any work around which can be applicable.

NSData *data = UIImagePNGRepresentation(imageView.image);
NSString *file = [NSTemporaryDirectory() stringByAppendingPathComponent:#"upload.png"];
[data writeToFile:file atomically:YES];
[DBRestClient uploadFile:#"upload.png" toPath:#"Dropbox/Path" fromPath:file];

Here is a tutorial of how to achieve that. It´s a couple of steps and hard to tell what you´re doing wrong, that´s why I have only included a link for the answer.
But basically
let uploadTextFileAction = UIAlertAction(title: "Upload text file", style: UIAlertActionStyle.Default) { (action) -> Void in
let uploadFilename = "testtext.txt"
let sourcePath = NSBundle.mainBundle().pathForResource("testtext", ofType: "txt")
let destinationPath = "/"
self.dbRestClient.uploadFile(uploadFilename, toPath: destinationPath, withParentRev: nil, fromPath: sourcePath)
}
I recommend you to check the tutorial, since there are some framework imports and other stuff that is required.

Related

XCODE / IOS - Share audio file to whatsapp with a direct opening

I am trying to share an audio file from my ios app to whatsapp, but with a direct opening of whatsapp, and not an opening of the sharing menu with all the tiles.
Here is what i have now:
// Getting the original file
let fileName = #MY FILE NAME#
let filePath = Bundle.main.path(forResource: fileName, ofType: "mp3")!
let urlData = URL.init(fileURLWithPath: filePath)
let nsData = NSData(contentsOf: urlData)
if (nsData != nil){
// Creating the temporary file to share in the accessible ressources
let newFileName = "file.mp3"
let newFilePath = "\(NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0])/\(newFileName)"
nsData?.write(toFile: newFilePath, atomically: true)
let newUrlData = URL.init(fileURLWithPath: newFilePath)
// Sharing the file to whatsapp
// Possibility 1 (does not work yet)
// let documentController = UIDocumentInteractionController(url: newUrlData)
// documentController.uti = "net.whatsapp.audio"
// documentController.presentOpenInMenu(from: CGRect.zero, in: self.view, animated: true)
// Possibility 2 (works only with the sharing menu)
let activityVC = UIActivityViewController(activityItems: [NSURL(fileURLWithPath: newFilePath)], applicationActivities: nil)
self.present(activityVC, animated: true, completion: nil)
}
As I do this, sharing an audio file to whatsapp works, but it first open the sharing menu, with the messenger tile, message tile, notes tile, ... (and it doesn't works for the messenger app). In the end I would like to be able to share on messenger AND whatsapp.
As explicated here in the whatsapp documentation, I want to open directly the whatsapp application when I try to share the file:
Alternatively, if you want to show only WhatsApp in the application list (instead of WhatsApp plus any other public/*-conforming apps) you can specify a file of one of aforementioned types saved with the extension that is exclusive to WhatsApp:
images - «.wai» which is of type net.whatsapp.image
videos - «.wam» which is of type net.whatsapp.movie
audio files - «.waa» which is of type net.whatsapp.audio
When triggered, WhatsApp will immediately present the user with the contact/group picker screen. The media will be automatically sent to a selected contact/group.
So I tried to change the line :
let newFileName = "file.mp3"
To one of these :
let newFileName = "file.mp3.waa"
let newFileName = "file.waa"
let newFileName = "file.waa.mp3"
But it still shows the same sharing menu (and can't read the audiofile if it ends with the .waa extension).
-> 1) Is it possible to do what I want to do ?
-> 2) If not, is there a way to share to messenger & whatsapp with the same code keeping one sharing menu
-> 3) If not, is there a way to reduce the sharing menu to only one tile depending on different calling event, so there is no confusing choosing of tiles
Thanks,
Antoine
Cf: XCODE / IOS - How to use exclusive extension to immediately present whatsapp (.wai, .waa, .wam)
FYI: As I went through a lot of tests with this, I couldn't find any solution yet.
Whatsapp recognize the file extension, but cannot even read it. Once shared, when you click on it, it's written ".whatsapp audio file", nothing more (And it's not even shared directly).
I sent a email to whatsapp developper team, they said they have others problem to fix currently, so it's not even on their to do list.
Wait & see..

converting video to NSData in share extension in ios

I have created a share extension for my ios app. When I click on the share option in the photo app my share extension is shown and I click on it and my controller is shown. Everything is working fine up to this. I am uploading video to youtube using the youtube api. I am using this method to create the parameter
GTLUploadParameters *uploadParameters = [GTLUploadParameters uploadParametersWithData:fileData MIMEType:#"video/*"];
Now if the video is small then it is easily converted to NSData using this code
NSData *fileData = [NSData dataWithContentsOfURL:[NSURL URLWithString:videoURL]];
and everything is working and video is uploaded.
But if the video is large then it simply crash and exit from the share extension(I put breakpoint and found this problem. If I remove the fileData conversion then its not crashing.). So what I did was instead of converting it to NSData I used this youtube api method
GTLUploadParameters *uploadParameters = [GTLUploadParameters uploadParametersWithFileURL:[NSURL URLWithString:videoURL] MIMEType:#"video/*"];
Now app is not crashing but I am getting network error. The error is
Error Domain=NSURLErrorDomain Code=-995 "(null)"
little searching found that it is because of NSURLSession and told to use something like this
sessionConfiguration.sharedContainerIdentifier = #“com.me.myapp.containerIdentifier”;
I am using youtube api. I am not sure where to use it OR is there any other way to use youtube api in share extension with large video file.
NOTE: I am using youtube api in my app and its working fine with NSData.
Hope question is clear. I am stuck on it for a day now. Please help.
Thanks in advance.
EDIT 1:
I used this code
NSData *fileData = [NSData dataWithContentsOfURL:[NSURL fileURLWithPath:videoURL] options:0 error:&error];
filedata is nil. The error I am getting is
Error Domain=NSCocoaErrorDomain Code=260 "The file “IMG_2187.MOV”
couldn’t be opened because there is no such file."
UserInfo={NSFilePath=/file:/var/mobile/Media/DCIM/102APPLE/IMG_2187.MOV,
Consider this line:
var videoDataURL = info[UIImagePickerControllerMediaURL] as! NSURL!
This does a forced unwrapping of info[UIImagePickerControllerMediaURL] (which is bad, because if it was nil, the app would crash) and that casts it as an implicitly unwrapped optional NSURL!. That doesn't make sense. Just do a conditional unwrapping (and unwrap to a NSURL, not a NSURL!):
if let videoDataURL = info[UIImagePickerControllerMediaURL] as? NSURL { ... }
The next line calls filePathURL:
var videoFileURL = videoDataURL.filePathURL
If you wanted a file URL, you already have one, so no conversion is needed, but instead just use videoDataURL. If you really wanted a path, you'd use path method:
let videoPath = videoDataURL.path
Frankly, Apple is trying to shift us away from using string paths, so just use the original videoDataURL and avoid the use of both path and filePathURL.
You are using dataWithContentsOfMappedFile:
var video = NSData.dataWithContentsOfMappedFile("\(videoDataURL)")
If you really wanted to use dataWithContentsOfMappedFile, the proper Swift syntax is:
let video = NSData(contentsOfMappedFile: videoPath!)
But dataWithContentsOfMappedFile deprecated, so you should instead use:
let video = try NSData(contentsOfFile: videoPath!, options: .DataReadingMappedIfSafe)
Or, bypassing that videoPath altogether, you could:
let video3 = try NSData(contentsOfURL: videoDataURL, options: .DataReadingMappedIfSafe)
Obviously, those try renditions should be done within a do block with a catch block.
By the way, as you'll see in all of my above examples, one should use let where possible.
Quite frankly, I would advise against loading it into a NSData at all. Just copy it with NSFileManager, which is a more efficient use of memory. If the video is long, it could be quite large, and you should avoid loading the whole thing into memory at any given point in time.
So you could:
if let videoDataURL = info[UIImagePickerControllerMediaURL] as? NSURL {
do {
// build your destination URL however you want
//
// let tempFolder = NSURL(fileURLWithPath: NSTemporaryDirectory())
// let destinationURL = tempFolder.URLByAppendingPathComponent("test.mov")
// or
let documents = try NSFileManager.defaultManager().URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: false)
let destinationURL = documents.URLByAppendingPathComponent("test.mov")
// but just copy from the video URL to the destination URL
try NSFileManager.defaultManager().copyItemAtURL(videoDataURL, toURL: destinationURL)
} catch {
print(error)
}
}
If you're uploading this to a web service, you'd then use a NSURLSessionUploadTask, using file or stream options. The construction of this request is a separate question, but hopefully you get the idea: With large assets like photos or, especially, videos, don't instantiate a NSData with the asset if you can possibly avoid it.
Please try this if your file exist in your phone instead of [NSURL URLWithString:videoURL].
NSData *fileData = [NSData dataWithContentsOfURL:[NSURL fileURLWithPath:videoURL]];

Copy GIF to UIPasteboard

I'm trying to copy a GIF image to the UIPasteboard in swift, at the moment it only copies the static version of the image and seems to convert it to PNG looking at the file extension when I upload it somewhere.
Wondered if anyone had any idea how to achieve this? All other soltions I've found only seem to work when getting NSData from a URL rather than from an image in the bundle
For anyone who ever encounters this problem I managed to find a solution
let url: NSURL = NSBundle.mainBundle().URLForResource("\(self.imageNames[indexPath.row])", withExtension: ".gif")!
let data: NSData = NSData(contentsOfURL: url)!
UIPasteboard.generalPasteboard().setData(data, forPasteboardType: "com.compuserve.gif")
As it turns out you do need to use a URL and extract the NSData of the GIF from that URL.
Here I am getting the URL of the GIF that is in my bundle, searching for it using the name and extension of the image. I am then setting the data in the pasteboard and bingo we have an animated GIF when pasting the result from the pasteboard
It doesn't look like the image property on the pasteboard supports the GIF type.
The associated array of representation types is UIPasteboardTypeListImage, which includes types kUTTypePNG and kUTTypeJPEG.
You could probably do this using the NSData from the GIF though:
import MobileCoreServices
// ...
var image = UIImage(...)
let data = NSData(bytes: &image, length: sizeof(UIImage))
UIPasteboard.generalPasteboard().setData(data, forPasteboardType: kUTTypeGIF as String)) // com.compuserve.gif

Extract video portion from Live Photo

Has anyone figured out how to extract the video portion from a Live Photo? I'm working on an app to convert Live Photos into a GIF, and the first step is to get the video file from the Live Photo. It seems like it should be possible, because if you plug in your phone to a Mac you can see the separate image and video files. I've kinda run into a brick wall in the extraction process, and I've tried many ways to do it and they all fail.
The first thing I did was obtain a PHAsset for what I think is the video part of the Live Photo, by doing the following:
if let livePhoto = info["UIImagePickerControllerLivePhoto"] as? PHLivePhoto {
let assetResources = PHAssetResource.assetResourcesForLivePhoto(livePhoto)
for assetRes in assetResources {
if (assetRes.type == .PairedVideo) {
let assets = PHAsset.fetchAssetsWithLocalIdentifiers([assetRes.assetLocalIdentifier], options: nil)
if let asset = assets.firstObject as? PHAsset {
To convert the PHAsset to an AVAsset I've tried:
asset.requestContentEditingInputWithOptions(nil, completionHandler: { (contentEditingInput, info) -> Void in
if let url = contentEditingInput?.fullSizeImageURL {
let movieUrl = url.absoluteString + ".mov"
let avAsset = AVURLAsset(URL: NSURL(fileURLWithPath: movieUrl), options: nil)
debugPrint(avAsset)
debugPrint(avAsset.duration.value)
}
})
I don't think this one works because the debug print with the duration.value gives 0.
I've also tried without the ".mov" addition and it still doesn't work.
I also tried:
PHImageManager.defaultManager().requestAVAssetForVideo(asset, options: nil, resultHandler: { (avAsset, audioMix, info) -> Void in
debugPrint(avAsset)
})
And the debugPrint(avAsset) prints nil so it doesn't work.
I'm kind of afraid they might have made it impossible to do, it seems like I'm going in circles since it seems like the PHAsset I got is still a Live Photo and not actually a video.
Use the PHAssetResourceManager to get the video file from the PHAssetResource.
PHAssetResourceManager.defaultManager().writeDataForAssetResource(assetRes,
toFile: fileURL, options: nil, completionHandler:
{
// Video file has been written to path specified via fileURL
}
NOTE: The Live Photo specific APIs were introduced in iOS 9.1
// suppose you have PHAsset instance (you can get it via [PHAsset fetchAssetsWithOptions:...])
PHAssetResource *videoResource = nil;
NSArray *resourcesArray = [PHAssetResource assetResourcesForAsset:asset];
const NSInteger livePhotoAssetResourcesCount = 2;
const NSInteger videoPartIndex = 1;
if (resourcesArray.count == livePhotoAssetResourcesCount) {
videoResource = resourcesArray[videoPartIndex];
}
if (videoResource) {
NSString * const fileURLKey = #"_fileURL";
NSURL *videoURL = [videoResource valueForKey:fileURLKey];
// load video url using AVKit or AVFoundation
}
I accidentally did. I have an ios app called Goodreader (available in the appstore) which features a windows-like file manager. When importing a live photo, it will save it as a folder ending in .pvt containing the jpg and mov files in it. There is only one caveat: you need to open the live photo from within the messages app after you've sent it to yourself or somebody else to see the "import to goodreader" option, not from the photos app.

How do I count a number of images in a folder reference in swift

I'm working on an custom emoji keyboard in Swift and I'm having trouble finding and counting the images in a folder reference called "emojis".
EDIT: To clarify my issue is that let contents always end up as nil.
The structure from the location of the .xcodeproj file looks like this:
EmojiBoard/emojis/emoji-0.png and so on.
I've been trying to use the NSFileManager with no luck.
let fileManager = NSFileManager.defaultManager()
let contents = fileManager.contentsOfDirectoryAtPath("emojis", error: &error)
println(contents)
This prints nil. I've also tried "EmojiBoard/emojis" and "/EmojiBoard/emojis".
I need this to determine how many images there are and loop them all out without having to resort to an insane switch statement or something like that.
Thank you!
P.S. Please note that I'm coding in Swift, not Objective C. I'm not proficient enough to convert C programming to swift I'm afraid. D.S.
if you created folder reference when adding the folder to your project use it like this (emojis folder icon is a blue folder):
let resourceURL = Bundle.main.resourceURL!.appendingPathComponent("emojis")
var resourcesContent: [URL] {
(try? FileManager.default.contentsOfDirectory(at: resourceURL, includingPropertiesForKeys: nil)) ?? []
}
let emojiCount = resourcesContent.count
print(emojiCount)
if you created groups when adding the folder to your project use it like this (emojis folder icon is a yellow folder):
let resourceURL = Bundle.main.resourceURL!
let resourcesContent = (try? FileManager.default.contentsOfDirectory(at: resourceURL, includingPropertiesForKeys: nil)) ?? []
let emojiCount = resourcesContent.filter { $0.lastPathComponent.hasPrefix("emoji-") }.count
print(emojiCount)
From the top of my head, without access to an IDE to test this code, I reckon something like this:
let fileManager = NSFileManager.defaultManager()
let contents = fileManager.contentsOfDirectoryAtPath(path, error: &error)
for var index = 0; index < contents.count; ++index {
println("File is \(contents[index])")
}
If you replace 'path' above with your documents directory, this code should loop through the whole folder and print out all files.
If you just want the count of items just do this:
println("count is \(contents.count)")
The problem (or at least a major part of the problem) is your path. You can't pass in a path that's just a filename. You need an absolute path to one of the sandboxed directories available to your app like the documents directory.
Your code might look like this:
let documentsDir = NSSearchPathForDirectoriesInDomains(
NSSearchPathDirectory.DocumentDirectory,
NSSearchPathDomainMask.UserDomainMask,
true)[0] as! NSString
let emojisPath = documentsDir.stringByAppendingPathCompnent("emojis")
let contents = fileManager.contentsOfDirectoryAtPath(emojisPath,
error: &error)
println(contents)
(That would work if your emojis folder is in your app's documents folder. If instead your emojis are in your app bundle (built into the app) you would need to use different code entirely (using NSBundle functions to get a path to the directory inside the bundle).
EDIT:
If you want to find files in your app's bundle use the NSBundle method resourcePath, and then append the folder name to the bundle's resourcePath using stringByAppendingPathCompnent, like the code above.

Resources