I need to define a processing rule for web data in iOS and thought it would be a good idea to pull the processing rule as a script file from my server and execute it on the iOS device, since the web API I'm interacting with might change URLs or response syntax and I need to be able to fix such issues fast and cannot rely on pushing an update (takes forever).
I wanted to do it with a small JS file that is pulled from my server every once and a while, but unfortunately iOS doesn't include the JavaScriptCore framework.
Are there other options?
Apple developer agreement will not let you run a downloaded, interpreted script, on the device.
Your best bet is probably downloading a data structure (potentially in JSON format) and parse that and take some predefined actions in your client code based on that, rather than trying to execute the downloaded code directly.
You can let a UIWebView run a Javascript snippet, or you could use another scripting language like LUA (don't forget to add LUA for this). The real problem is: You are not allowed to download code from a webserver or somewhere else. Everything must either be already on the device, or calculated at runtime.
Depending on the information that you want, you could use an XML file that includes the new URLs and parse it, but I don't know if this fits your need.
You can compile JavaScriptCore into your app, evidently, and have it approved by Apple. However, as Mehrdad notes, any scripts run in the app must already be in the app at the time the app is reviewed.
Related
Note: I am very new to Swift programming (2 days only) and I am working on this piece of code as part of an ElectronJS project. So please don't mind my ignorance regarding the basics of the language. Thanks.
I have created a Swift app containing a Share App Extension.
Requirements:
The Share App Extension should be able to send the absolute file path of the shared files to the container app, i.e. If the user selects a file (abc.txt) from Desktop in Finder and Shares to my Application, then the Share App Extension should be able to get the file path as
/users/userName/Desktop/abc.txt
What I am struggling with here is how to get the file path of the files shared with the Share App Extension. What is the way to get file path of the attachments in NSExtensionItem that is available to the Share App Extension or is it available from some other object ?
(I am able to successfully use App Groups to share data between Share App Extension and the Application)
In the final project, the Share App Extension becomes a part of an ElectronJS project as mentioned earlier.
Is there a standard way to share the aforementioned information (file path of the attachments) from the Share App Extension to the main/renderer processes of the Electron application.
I am sharing the solutions below. Please bear in mind that these might not be the best possible solutions and I am open to suggestions.
Solution to Point #1:
Briefing: The user selects files from Finder to be shared via the Share App Extension of the application which is registered with the OS if the extension context of the selection matches to that of the Share App Extension. Upon doing so, the Share App Extension receives the extension context alongwith NSExtensionItem. The NSExtensionItem object contains the NSItemProvider object which is the object you'd get for all the files (attachments) shared via the Share App Extension.
Now, for each item type that you receive via the Share App Extension, after looking for the data that your function recognizes via hasItemConforminToTypeIdentifier(_:), you can use UTI (Uniform Type Identifier) to identify its data.
Remedy: Here, the crucial part is to understand that one should be treating their input files as firstly being of the type: kUTTypeURL. Then, in the completionHandler for the loadItem method of the NSItemProvider object one would get NSURL which is basically the file path I was looking for.
Solution to Point #2:
Briefing: The Share App Extension has the luxury of being written in Swift but the main app in our project does not ! The main application is written in ElectronJS which is far far far far from being integratable with Swift ! Except for the fact that the application written in ElectronJS has the ability to be packaged in the form of a dmg application, there is very little integratability between ElectronJS and Swift as far as the language and framework intertwining is concerned.
Premise:
So, the premise is to be able to share the filepaths extracted earlier to be passed from the Share App Extension (written in Swift) to the main application (written in ElectronJS). Now, if the main application was a Cocoa application, things would have been much easier. If both of them belong to the same App group, then using the Swift APIs they could have read/written synchronously to the Shared Memory. However, the problem arises as those APIs are not available in ElectronJS. One remedy can be to run the Swift code in a sandboxed environment within the ElectronJS application using nodeJS libraries. However, a sandboxed environment presents its own nuances in data sharing. So, I have kept this approach on hold for now.
So, the approach that I have chosen right now is to use App Data Directory to share this intermediary information. The Share App Extension would be writing the filepath information in the App Data directory of the application and the ElectronJS application would use nodeJs APIs to access this information. Keep in mind that this is a very primitive approach and requires menial efforts but the requirements for this particular case doesn't need stringent security measures anyhow.
However, I am positively looking for a better way to solve Problem #2.
I am using code first api for UI Automation.
I want to check whether file is downloaded or not on button click.
I am able to find the button and click is working fine .
i dont know how to check the file is downloaded or not.
I am new to this technology. sorry if it is a basic question.
Thanks in advance.
Coded UI does not have any built-in facility for checking that a download completed and actually downloaded a file. However, Coded UI tests can use the full facilities of the language they are written in plus the .Net libraries.
In the Coded UI test method, at the place where you expect the download to have been completed, add some code to check the properties of the file that should have been created. For example: its existence, its creation and/or modification date and time, its size. Use the normal file IO operations to perform the checks. Microsoft provide details on How to do basic file I/O in Visual C#.
After performing the checks it may be beneficial to delete the file, to reduce wasted disc space.
There is a very cool iPhone app called Viddy where you can download filters to apply to videos.
How can they pack filters outside the app, and make them available to users via downloading?
One way would be to have an in-app purchase that's just a document that describes an image processing graph. (Think of a nodal graph representation for something like Shake or Nuke.) For example, a glow is often implemented as a blurred image mixed with the original image. You could create a document which describes that processing graph. Once you've downloaded such a document into your app, you can implement it using Core Image filters, or write your own using GLSL, or even just straight CPU processing.
It's pretty simple, they do use shaders and they're downloaded from the internet.
Download iExplorer for Mac, connect your iPhone with Viddy installed.
Check Library/effects folder in Viddy.app. You'll find afx_1_0.xml and vfx_1_0.xml files there.
Download them to your Mac, open them and you'll find filters definitions there along with URL to download them.
An example is SOHO filter. Download this file, open it and you'll see three files there: shader.fx3 where shader is defined, thumb.png for thumbnail and vignette.png file, which is used for this shader as well.
We did use same approach in unnamed application, but we did encrypt all this information along with shaders itself to avoid analysis like this one :)
Encryption, decryption example request in comment
Let's say you have .fx file with your shader (or any other file).
Open Xcode and go to Build Rules where you can define build rule for *.fx files. Set it to run your Custom script: which can look like this one:
ENC_KEY="your-encryption-key"
${PROJECT_DIR}/../Tools/bin/crypt -e -k $ENC_KEY -i ${INPUT_FILE_PATH} \
-o "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/${INPUT_FILE_BASE}.cfx"
This script produces .cfx file, which has same content as .fx file, but is encrypted.
crypt binary came from this project: download crypt Xcode project.
Download encrypted resource demo.
Copy EncryptedFileURLProtocol.* and NSURL+EncryptedFileURLProtocol.* files into your project.
In app delegate call this to register your protocol [NSURLProtocol registerClass:[EncryptedFileURLProtocol class]];
And now when you do want to open encrypted resource, you have to use protocol encrypted-file instead of file://. This task handles NSURL category from demo project and you can simply use [NSURL encryptedFileURLWithPath:#"/path/to/my/encrypted/file"].
It's pretty simple and you'll find most info you need in sample app (link above). Also you can mangle your encryption / decryption key in application, so, people have to think and the key is not easily readable. Now, when you access encrypted file via this NSURL, it's automatically decrypted for you in app. The decryption key is set in sharedKey in EncryptedFileURLProtocol.m file.
The easiest way to do this is to build the filters into the app itself, and have the in-app purchase simply unlock the ability to use them.
If you wanted to avoid the download time for all the additional images or other pieces needed, you could still include the code in the main app, and just download the extra resources needed. You can use something like Urban Airship's IAP support to host & download the IAP resources. (You might also want to look into new features of iOS 6 in this vein.)
GLSL shaders may be downloaded in source code form and then to be used for processing. It gives very flexible way to create new filters after having app published. From another hand it might be enough just to update (download) additional filter data. For example, Instagram uses same color curve technique for most filters but with different curve data, so it they want, they will be able to update their filters online.
Filter for videos also uses CIImage class like intagram application for images. See the link here:"http://www.icapps.be/face-detection-with-core-image-on-live-video/". Now filters can be download the filter (actually its In App Purchase happening).
Put the purchase/download method right beneath the case:
case SKPaymentTransactionStatePurchased:
[self ...];
so whats happening is purchase of filter for free which can be used on any video. Actually method is enabled to have filter after SKPaymentTransactionStatePurchased.
I want to bind my app to some file extension so when I receive an email with an attached file with the correct extension, clicking on it will launch my app and pass it the attached file.
Is it possible ? How ?
Thx
--G.
As iPhone applications are not allowed to share files on the file system, what you're looking for is not immediately possible (not with the published APIs that I know of, anyway). You might still have a couple of options though.
Either way you'll have to use a custom URL scheme, which is associated with your app, and paste that into your email. This URL might point to some external location, which your app can download the file from.
Or it might contain the actual file contents if it's fairly small. URLs are 'just text' (some restrictions apply), so you're free to put any data you want to in it, as long as it is URL-encoded.
You still need to get the URL into the email though, which might or might not be as easy as attaching a file.
It's not possible to simply associate a file extension with an application on the iPhone.
You could create a custom URL scheme that would launch your app, but probably that won't help you.
This is actually possible, I'm working on this exact same problem and this great tutorial has really helped me.
I used the sample code from http://cocoawithlove.com/2008/09/streaming-and-playing-live-mp3-stream.html. it runs OK with default URL. But when I replace with my URL "http://dl.mp3.kapsule.info/fsfsdfdsfdserwrwq3/fc90613208cc3f16ae6d6ba05d21880c/4b5244f0/b/7e/b7e80afa18d06fdd3dd9f9fa44b51fc0.mp3?filename=Every-Day-I-Love-You.mp3", this app shows an message as "Audio not Found". But when I put my URL on Address Bar of Web Browser, I can download this .mp3 file.
really, I can't understand why it is?
pleased tell me!
Thank you very much
My guess would be that the app is designed to play a MP3 encoded audio stream with no limit in length (which is different from your ordinary music file). To set this up, you need a streaming server on the client side.
I think you can find out for sure by trying with a different radio station that transmits in MP3. If that works, it's most likely that your app doesn't like your file.
You should, as Vivek recommends, also try using a simpler download URL for your file, in case the App gets confused by the URL's length and/or structure.
As mentioned, this is due to the URL of the file. The AudioStreamer code specifically checks for the extension of the file and tries to figure out the audio type based on that. If you change that logic to handle your custom URLs, it will start working
So to point you in the right direction: open AudioStreamer.m and look for the references of
hintForFileExtension:
This function returns the type of file based on the extension. If you know the file type won't change (always mp3), the quick and dirty solution is to always assign mp3 type without any logic... like this:
err = AudioFileStreamOpen(self, MyPropertyListenerProc, MyPacketsProc, kAudioFileMP3Type, &audioFileStream);
Note: I've put kAudioFileMP3Type constant instead of calculated value
PS yes, it does work with static mp3 files, even though it's designed for streams and hence misses some of the functionality one would expect from a player that plays a static file on the server (caching, prefetching, proper seeking)
Thats because the default url directly points to a file in the webserver, whereas the the url you've mentioned is a HTTP (POST/GET) operation, which the application may not be designed to handle.
I suspect that your URL is one-time-use. When I try to visit it, I see 408 - Request Timeout.
Many links on mass file sharing websites are like this. If you could download the file directly, you wouldn't sit through a page of ads and premium account offers.
Try again with a file on a normal website, like this one.